Made reading and writing memory overflow safe.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13306 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2005-06-28 11:19:30 +00:00
parent a87826801c
commit 07b6630b86
+30 -15
View File
@@ -999,13 +999,30 @@ read_user_memory(const void *_address, void *_buffer, int32 size,
// If the region to be read crosses page boundaries, we split it up into // If the region to be read crosses page boundaries, we split it up into
// smaller chunks. // smaller chunks.
status_t error = B_OK;
bytesRead = 0; bytesRead = 0;
while (size > 0) { while (size > 0) {
int32 toRead = size; // check whether we're still in user address space
if ((uint32)address % B_PAGE_SIZE + toRead > B_PAGE_SIZE) if (!IS_USER_ADDRESS(address)) {
toRead = B_PAGE_SIZE - (uint32)address % B_PAGE_SIZE; error = B_BAD_ADDRESS;
break;
}
status_t error = user_memcpy(buffer, address, toRead); // don't cross page boundaries in a single read
int32 toRead = size;
int32 maxRead = B_PAGE_SIZE - (addr_t)address % B_PAGE_SIZE;
if (toRead > maxRead)
toRead = maxRead;
error = user_memcpy(buffer, address, toRead);
if (error != B_OK)
break;
bytesRead += toRead;
address += toRead;
buffer += toRead;
size -= toRead;
}
// If reading fails, we only fail, if we haven't read anything yet. // If reading fails, we only fail, if we haven't read anything yet.
if (error != B_OK) { if (error != B_OK) {
@@ -1014,12 +1031,6 @@ read_user_memory(const void *_address, void *_buffer, int32 size,
return error; return error;
} }
bytesRead += toRead;
address += toRead;
buffer += toRead;
size -= toRead;
}
return B_OK; return B_OK;
} }
@@ -1042,7 +1053,11 @@ write_user_memory(void *_address, const void *_buffer, int32 size,
status_t error = B_OK; status_t error = B_OK;
bytesWritten = 0; bytesWritten = 0;
while (size > 0) { while (size > 0) {
int32 toWrite = size; // check whether we're still in user address space
if (!IS_USER_ADDRESS(address)) {
error = B_BAD_ADDRESS;
break;
}
// get the area for the address (we need to use _user_area_for(), since // get the area for the address (we need to use _user_area_for(), since
// we're looking for a user area) // we're looking for a user area)
@@ -1064,10 +1079,10 @@ write_user_memory(void *_address, const void *_buffer, int32 size,
} }
// restrict this round of writing to the found area // restrict this round of writing to the found area
if (toWrite > (int32)areaInfo.size) int32 toWrite = size;
toWrite = areaInfo.size; int32 maxWrite = (char*)areaInfo.address + areaInfo.size - address;
if (address + toWrite > (char*)areaInfo.address + areaInfo.size) if (toWrite > maxWrite)
toWrite = (char*)areaInfo.address + areaInfo.size - address; toWrite = maxWrite;
// if the area is read-only, we temporarily need to make it writable // if the area is read-only, we temporarily need to make it writable
bool protectionChanged = false; bool protectionChanged = false;