diff --git a/src/syscall/process.rs b/src/syscall/process.rs index 4c3277be7f7a9e925350e6b177b24848fa8a1417..c9b041a06e56fe9f937e8924fc395657a4dff209 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -1351,30 +1351,39 @@ pub fn mprotect(address: usize, size: usize, flags: MapFlags) -> Result<usize> { let start_page = Page::containing_address(VirtualAddress::new(address)); let end_page = Page::containing_address(VirtualAddress::new(end_address)); for page in Page::range_inclusive(start_page, end_page) { - if let Some(mut page_flags) = active_table.translate_page_flags(page) { - if flags.contains(PROT_EXEC) { - page_flags.remove(EntryFlags::NO_EXECUTE); - } else { - page_flags.insert(EntryFlags::NO_EXECUTE); - } + // Check if the page is actually mapped before trying to change the flags. + // FIXME can other processes change if a page is mapped beneath our feet? + let mut page_flags = if let Some(page_flags) = active_table.translate_page_flags(page) { + page_flags + } else { + flush_all.flush(&mut active_table); + return Err(Error::new(EFAULT)); + }; + if !page_flags.contains(EntryFlags::PRESENT) { + flush_all.flush(&mut active_table); + return Err(Error::new(EFAULT)); + } - if flags.contains(PROT_WRITE) { - //TODO: Not allowing gain of write privileges - } else { - page_flags.remove(EntryFlags::WRITABLE); - } + if flags.contains(PROT_EXEC) { + page_flags.remove(EntryFlags::NO_EXECUTE); + } else { + page_flags.insert(EntryFlags::NO_EXECUTE); + } - if flags.contains(PROT_READ) { - //TODO: No flags for readable pages - } else { - //TODO: No flags for readable pages - } + if flags.contains(PROT_WRITE) { + //TODO: Not allowing gain of write privileges + } else { + page_flags.remove(EntryFlags::WRITABLE); + } - let flush = active_table.remap(page, page_flags); - flush_all.consume(flush); + if flags.contains(PROT_READ) { + //TODO: No flags for readable pages } else { - return Err(Error::new(EFAULT)); + //TODO: No flags for readable pages } + + let flush = active_table.remap(page, page_flags); + flush_all.consume(flush); } flush_all.flush(&mut active_table);