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:
@@ -999,27 +999,38 @@ 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);
|
|
||||||
|
|
||||||
// If reading fails, we only fail, if we haven't read anything yet.
|
|
||||||
if (error != B_OK) {
|
|
||||||
if (bytesRead > 0)
|
|
||||||
return B_OK;
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
bytesRead += toRead;
|
||||||
address += toRead;
|
address += toRead;
|
||||||
buffer += toRead;
|
buffer += toRead;
|
||||||
size -= toRead;
|
size -= toRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If reading fails, we only fail, if we haven't read anything yet.
|
||||||
|
if (error != B_OK) {
|
||||||
|
if (bytesRead > 0)
|
||||||
|
return B_OK;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user