From 87241a9d3cdd30ee53d798980f5a71fa96110930 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 1 Aug 2021 14:57:41 +0200 Subject: [PATCH] Pass AT_PHDR via a grant rather than the stack. --- src/syscall/process.rs | 61 ++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/src/syscall/process.rs b/src/syscall/process.rs index af15f50..97d613f 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -586,8 +586,8 @@ fn fexec_noreturn( setuid: Option, setgid: Option, name: Box, - phdrs_region: core::ops::Range, data: Box<[u8]>, + phdr_grant: context::memory::Grant, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>]>, auxv: Box<[usize]>, @@ -596,11 +596,6 @@ fn fexec_noreturn( let singlestep; let mut sp = crate::USER_STACK_OFFSET + crate::USER_STACK_SIZE - 256; - let phdrs_len = 4096; - let phdrs_base_addr = sp - phdrs_len; - - sp -= phdrs_len; - { let (vfork, ppid, files) = { let contexts = context::contexts(); @@ -615,6 +610,8 @@ fn fexec_noreturn( empty(&mut context, false); + context.grants.write().insert(phdr_grant); + #[cfg(all(target_arch = "x86_64"))] { context.arch.fsbase = 0; @@ -701,19 +698,14 @@ fn fexec_noreturn( true )); + // Data no longer required, can deallocate + drop(data); + let mut push = |arg| { sp -= mem::size_of::(); unsafe { *(sp as *mut usize) = arg; } }; - unsafe { - let mut source = core::slice::from_raw_parts_mut(phdrs_base_addr as *mut u8, phdrs_len); - source[..phdrs_region.len()].copy_from_slice(&data[phdrs_region.clone()]); - } - - // Data no longer required, can deallocate - drop(data); - // Push auxiliary vector push(AT_NULL); for &arg in auxv.iter().rev() { @@ -822,7 +814,7 @@ fn fexec_noreturn( unsafe { usermode(entry, sp, 0, usize::from(singlestep)) } } -pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>]>, name_override_opt: Option>, auxv: Option>) -> Result { +pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]>]>, name_override_opt: Option>, auxv: Option<(Vec, context::memory::Grant)>) -> Result { let (uid, gid) = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -922,21 +914,42 @@ pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]> // `fexec_kernel` can recurse if an interpreter is found. We get the // auxiliary vector from the first invocation, which is passed via an // argument, or if this is the first one we create it. - let auxv = if let Some(auxv) = auxv { - auxv + let (auxv, phdr_grant) = if let Some((auxv, phdr_grant)) = auxv { + (auxv, phdr_grant) } else { + let phdr_grant = match context::contexts().current().ok_or(Error::new(ESRCH))?.read().grants.write() { + mut grants => { + let size = elf.program_headers_size() * elf.program_header_count(); + let aligned_size = (size + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE; + + if aligned_size > MAX_PHDRS_SIZE { + return Err(Error::new(ENOMEM)); + } + + let phdrs_region = grants.find_free(aligned_size); + let grant = context::memory::Grant::map(phdrs_region.start_address(), aligned_size, PageFlags::new().write(true).user(true)); + + unsafe { + let dst = core::slice::from_raw_parts_mut(grant.start_address().data() as *mut u8, aligned_size); + dst[..size].copy_from_slice(&data[elf.program_headers()..elf.program_headers() + elf.program_headers_size() * elf.program_header_count()]); + } + + grant + } + + }; let mut auxv = Vec::with_capacity(3); auxv.push(AT_ENTRY); auxv.push(elf.entry()); auxv.push(AT_PHDR); - auxv.push(crate::USER_STACK_OFFSET + crate::USER_STACK_SIZE - 256 - 4096); + auxv.push(phdr_grant.start_address().data()); auxv.push(AT_PHENT); auxv.push(elf.program_headers_size()); auxv.push(AT_PHNUM); auxv.push(elf.program_header_count()); - auxv + (auxv, phdr_grant) }; // We check the validity of all loadable sections here @@ -980,23 +993,19 @@ pub fn fexec_kernel(fd: FileHandle, args: Box<[Box<[u8]>]>, vars: Box<[Box<[u8]> args_vec.into_boxed_slice(), vars, Some(name_override), - Some(auxv), + Some((auxv, phdr_grant)), ); }, _ => (), } } - let phdr_range = elf.program_headers()..elf.program_headers() + elf.program_headers_size() * elf.program_header_count(); - if phdr_range.len() > 4096 { - return Err(Error::new(ENOMEM)); - } - // This is the point of no return, quite literaly. Any checks for validity need // to be done before, and appropriate errors returned. Otherwise, we have nothing // to return to. - fexec_noreturn(setuid, setgid, name.into_boxed_str(), phdr_range, data.into_boxed_slice(), args, vars, auxv.into_boxed_slice()); + fexec_noreturn(setuid, setgid, name.into_boxed_str(), data.into_boxed_slice(), phdr_grant, args, vars, auxv.into_boxed_slice()); } +const MAX_PHDRS_SIZE: usize = PAGE_SIZE; pub fn fexec(fd: FileHandle, arg_ptrs: &[[usize; 2]], var_ptrs: &[[usize; 2]]) -> Result { let mut args = Vec::new();