fix: round_up_to_page_size overflow

Closes: #200

The spec doesn't define which error code to set if `len` is too large.
`ENOMEM` is the closest defined condition that fits:

>> [...] the range [addr,addr+len) exceeds that allowed for the address
space of a process [...]

Logically, `len` would lead to `addr` exceeding the address space of a
process if rounding it up to the next page size causes an overflow.
This commit is contained in:
Josh Megnauth
2024-11-25 23:04:43 -05:00
parent a64a6a4cd0
commit 6ec03b6f4a
+24 -5
View File
@@ -44,8 +44,9 @@ static mut BRK_CUR: *mut c_void = ptr::null_mut();
static mut BRK_END: *mut c_void = ptr::null_mut();
const PAGE_SIZE: usize = 4096;
fn round_up_to_page_size(val: usize) -> usize {
(val + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE
fn round_up_to_page_size(val: usize) -> Option<usize> {
val.checked_add(PAGE_SIZE)
.map(|val| (val - 1) / PAGE_SIZE * PAGE_SIZE)
}
mod clone;
@@ -594,9 +595,17 @@ impl Pal for Sys {
fildes: c_int,
off: off_t,
) -> Result<*mut c_void> {
// 0 is invalid per spec
if len == 0 {
return Err(Errno(EINVAL));
}
let Some(size) = round_up_to_page_size(len) else {
return Err(Errno(ENOMEM));
};
let map = Map {
offset: off as usize,
size: round_up_to_page_size(len),
size,
flags: syscall::MapFlags::from_bits_truncate(
((prot as usize) << 16) | ((flags as usize) & 0xFFFF),
),
@@ -621,9 +630,12 @@ impl Pal for Sys {
}
unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> Result<()> {
let Some(len) = round_up_to_page_size(len) else {
return Err(Errno(ENOMEM));
};
syscall::mprotect(
addr as usize,
round_up_to_page_size(len),
len,
syscall::MapFlags::from_bits((prot as usize) << 16)
.expect("mprotect: invalid bit pattern"),
)?;
@@ -656,7 +668,14 @@ impl Pal for Sys {
}
unsafe fn munmap(addr: *mut c_void, len: usize) -> Result<()> {
syscall::funmap(addr as usize, round_up_to_page_size(len))?;
// 0 is invalid per spec
if len == 0 {
return Err(Errno(EINVAL));
}
let Some(len) = round_up_to_page_size(len) else {
return Err(Errno(ENOMEM));
};
syscall::funmap(addr as usize, len)?;
Ok(())
}