From 6ec03b6f4abc199a6c3243f1f309c19ad97008de Mon Sep 17 00:00:00 2001 From: Josh Megnauth Date: Mon, 25 Nov 2024 23:04:43 -0500 Subject: [PATCH] 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. --- src/platform/redox/mod.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 8cbd5b7b8e..2c6c2e9b3f 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -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 { + 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(()) }