Move cwd from kernel to relibc.
This commit is contained in:
+5
-18
@@ -11,7 +11,7 @@ use alloc::{
|
||||
use crate::{
|
||||
c_str::CStr,
|
||||
header::{sys_auxv::AT_NULL, unistd},
|
||||
platform::{new_mspace, types::c_char},
|
||||
platform::{get_auxvs, get_auxv, new_mspace, types::c_char},
|
||||
start::Stack,
|
||||
sync::mutex::Mutex,
|
||||
ALLOCATOR,
|
||||
@@ -57,19 +57,6 @@ unsafe fn get_env(mut ptr: *const usize) -> (BTreeMap<String, String>, *const us
|
||||
return (envs, ptr);
|
||||
}
|
||||
|
||||
unsafe fn get_auxv(mut ptr: *const usize) -> BTreeMap<usize, usize> {
|
||||
//traverse the stack and collect argument environment variables
|
||||
let mut auxv = BTreeMap::new();
|
||||
while *ptr != AT_NULL {
|
||||
let kind = *ptr;
|
||||
ptr = ptr.add(1);
|
||||
let value = *ptr;
|
||||
ptr = ptr.add(1);
|
||||
auxv.insert(kind, value);
|
||||
}
|
||||
return auxv;
|
||||
}
|
||||
|
||||
unsafe fn adjust_stack(sp: &'static mut Stack) {
|
||||
let mut argv = sp.argv() as *mut usize;
|
||||
|
||||
@@ -163,7 +150,7 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
|
||||
let argv_start = sp.argv() as *mut usize;
|
||||
let (argv, argv_end) = get_argv(argv_start);
|
||||
let (envs, envs_end) = get_env(argv_end.add(1));
|
||||
let auxv = get_auxv(envs_end.add(1));
|
||||
let auxv = get_auxvs(envs_end.add(1));
|
||||
(argv, envs, auxv)
|
||||
};
|
||||
|
||||
@@ -183,8 +170,8 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
|
||||
crate::platform::environ = crate::platform::OUR_ENVIRON.as_mut_ptr();
|
||||
}
|
||||
|
||||
let is_manual = if let Some(img_entry) = auxv.get(&AT_ENTRY) {
|
||||
*img_entry == ld_entry
|
||||
let is_manual = if let Some(img_entry) = get_auxv(&auxv, AT_ENTRY) {
|
||||
img_entry == ld_entry
|
||||
} else {
|
||||
true
|
||||
};
|
||||
@@ -229,7 +216,7 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
|
||||
let base_addr = {
|
||||
let mut base = None;
|
||||
if !is_manual && cfg!(not(target_os = "redox")) {
|
||||
let phdr = *auxv.get(&AT_PHDR).unwrap();
|
||||
let phdr = get_auxv(&auxv, AT_PHDR).unwrap();
|
||||
if phdr != 0 {
|
||||
base = Some(phdr - SIZEOF_EHDR);
|
||||
}
|
||||
|
||||
@@ -25,3 +25,9 @@ pub const AT_BASE_PLATFORM: usize = 24; /* String identifying real platforms.*/
|
||||
pub const AT_RANDOM: usize = 25; /* Address of 16 random bytes. */
|
||||
pub const AT_HWCAP2: usize = 26; /* More machine-dependent hints about*/
|
||||
pub const AT_EXECFN: usize = 31; /* Filename of executable. */
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
// XXX: The name AT_CWD is already used in openat... for a completely different purpose.
|
||||
pub const AT_REDOX_INITIALCWD_PTR: usize = 32;
|
||||
#[cfg(target_os = "redox")]
|
||||
pub const AT_REDOX_INITIALCWD_LEN: usize = 33;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::io::{self, Read, Write};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
use core::{fmt, ptr};
|
||||
|
||||
@@ -261,3 +262,41 @@ impl<T: Write> Write for CountingWriter<T> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Set a global variable once get_auxvs is called, and then implement getauxval based on
|
||||
// get_auxv.
|
||||
|
||||
#[cold]
|
||||
pub unsafe fn get_auxvs(mut ptr: *const usize) -> Box<[[usize; 2]]> {
|
||||
//traverse the stack and collect argument environment variables
|
||||
let mut auxvs = Vec::new();
|
||||
|
||||
while *ptr != self::auxv_defs::AT_NULL {
|
||||
let kind = ptr.read();
|
||||
ptr = ptr.add(1);
|
||||
let value = ptr.read();
|
||||
ptr = ptr.add(1);
|
||||
auxvs.push([kind, value]);
|
||||
}
|
||||
|
||||
auxvs.sort_unstable_by_key(|[kind, _]| *kind);
|
||||
auxvs.into_boxed_slice()
|
||||
}
|
||||
pub fn get_auxv(auxvs: &[[usize; 2]], key: usize) -> Option<usize> {
|
||||
auxvs.binary_search_by_key(&key, |[entry_key, _]| *entry_key).ok().map(|idx| auxvs[idx][1])
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[cfg(target_os = "redox")]
|
||||
pub fn init(auxvs: Box<[[usize; 2]]>) {
|
||||
use self::auxv_defs::*;
|
||||
|
||||
if let (Some(cwd_ptr), Some(cwd_len)) = (get_auxv(&auxvs, AT_REDOX_INITIALCWD_PTR), get_auxv(&auxvs, AT_REDOX_INITIALCWD_LEN)) {
|
||||
let cwd_bytes: &'static [u8] = unsafe { core::slice::from_raw_parts(cwd_ptr as *const u8, cwd_len) };
|
||||
if let Ok(cwd) = core::str::from_utf8(cwd_bytes) {
|
||||
self::sys::path::setcwd_manual(cwd.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub fn init(auxvs: Box<[[usize; 2]]>) {}
|
||||
|
||||
@@ -31,7 +31,6 @@ pub unsafe fn pte_clone_impl(stack: *mut usize) -> Result<usize> {
|
||||
}
|
||||
|
||||
copy_str(*cur_pid_fd, *new_pid_fd, "name")?;
|
||||
copy_str(*cur_pid_fd, *new_pid_fd, "cwd")?;
|
||||
|
||||
// Reuse existing address space
|
||||
{
|
||||
|
||||
+13
-10
@@ -7,9 +7,9 @@ use crate::platform::{sys::{S_ISUID, S_ISGID}, types::*};
|
||||
use syscall::data::Stat;
|
||||
use syscall::flag::*;
|
||||
use syscall::error::*;
|
||||
use redox_exec::{FdGuard, FexecResult};
|
||||
use redox_exec::{FdGuard, ExtraInfo, FexecResult};
|
||||
|
||||
fn fexec_impl(file: File, path: &[u8], args: &[&[u8]], envs: &[&[u8]], total_args_envs_size: usize, interp_override: Option<redox_exec::InterpOverride>) -> Result<usize> {
|
||||
fn fexec_impl(file: File, path: &[u8], args: &[&[u8]], envs: &[&[u8]], total_args_envs_size: usize, extrainfo: &ExtraInfo, interp_override: Option<redox_exec::InterpOverride>) -> Result<usize> {
|
||||
let fd = *file;
|
||||
core::mem::forget(file);
|
||||
let image_file = FdGuard::new(fd as usize);
|
||||
@@ -17,7 +17,7 @@ fn fexec_impl(file: File, path: &[u8], args: &[&[u8]], envs: &[&[u8]], total_arg
|
||||
let open_via_dup = FdGuard::new(syscall::open("thisproc:current/open_via_dup", 0)?);
|
||||
let memory = FdGuard::new(syscall::open("memory:", 0)?);
|
||||
|
||||
let addrspace_selection_fd = match redox_exec::fexec_impl(image_file, open_via_dup, &memory, path, args.iter().rev(), envs.iter().rev(), total_args_envs_size, interp_override)? {
|
||||
let addrspace_selection_fd = match redox_exec::fexec_impl(image_file, open_via_dup, &memory, path, args.iter().rev(), envs.iter().rev(), total_args_envs_size, extrainfo, interp_override)? {
|
||||
FexecResult::Normal { addrspace_handle } => addrspace_handle,
|
||||
FexecResult::Interp { image_file, open_via_dup, path, interp_override: new_interp_override } => {
|
||||
drop(image_file);
|
||||
@@ -75,6 +75,8 @@ pub fn execve(path: &CStr, arg_env: ArgEnv, interp_override: Option<redox_exec::
|
||||
}
|
||||
let wants_setugid = stat.st_mode & ((S_ISUID | S_ISGID) as u16) != 0;
|
||||
|
||||
let cwd: Box<[u8]> = super::path::clone_cwd().unwrap_or_default().into();
|
||||
|
||||
// Count arguments
|
||||
let mut len = 0;
|
||||
|
||||
@@ -103,12 +105,11 @@ pub fn execve(path: &CStr, arg_env: ArgEnv, interp_override: Option<redox_exec::
|
||||
}
|
||||
shebang == *b"#!"
|
||||
};
|
||||
// Since the fexec implementation is almost fully done in userspace, the kernel can no
|
||||
// longer set UID/GID accordingly, and this code checking for them before using
|
||||
// hypothetical interfaces to upgrade UID/GID, can not be trusted. So we ask the
|
||||
// `escalate:` scheme for help. Note that `escalate:` can be deliberately excluded from the
|
||||
// scheme namespace to deny privilege escalation (such as su/sudo/doas) for untrusted
|
||||
// processes.
|
||||
// Since the fexec implementation is almost fully done in userspace, the kernel can no longer
|
||||
// set UID/GID accordingly, and this code checking for them before using interfaces to upgrade
|
||||
// UID/GID, can not be trusted. So we ask the `escalate:` scheme for help. Note that
|
||||
// `escalate:` can be deliberately excluded from the scheme namespace to deny privilege
|
||||
// escalation (such as su/sudo/doas) for untrusted processes.
|
||||
//
|
||||
// According to execve(2), Linux and most other UNIXes ignore setuid/setgid for interpreted
|
||||
// executables and thereby simply keep the privileges as is. For compatibility we do that
|
||||
@@ -224,6 +225,7 @@ pub fn execve(path: &CStr, arg_env: ArgEnv, interp_override: Option<redox_exec::
|
||||
// individual items. This can be copied directly into the new executable's memory.
|
||||
let _ = syscall::write(*escalate_fd, &flatten_with_nul(args))?;
|
||||
let _ = syscall::write(*escalate_fd, &flatten_with_nul(envs))?;
|
||||
let _ = syscall::write(*escalate_fd, &cwd);
|
||||
|
||||
// Closing will notify the scheme, and from that point we will no longer have control
|
||||
// over this process (unless it fails). We do this manually since drop cannot handle
|
||||
@@ -235,7 +237,8 @@ pub fn execve(path: &CStr, arg_env: ArgEnv, interp_override: Option<redox_exec::
|
||||
|
||||
unreachable!()
|
||||
} else {
|
||||
fexec_impl(image_file, path.to_bytes(), &args, &envs, total_args_envs_size, interp_override)
|
||||
let extrainfo = ExtraInfo { cwd: Some(&cwd) };
|
||||
fexec_impl(image_file, path.to_bytes(), &args, &envs, total_args_envs_size, &extrainfo, interp_override)
|
||||
}
|
||||
}
|
||||
fn flatten_with_nul<T>(iter: impl IntoIterator<Item = T>) -> Box<[u8]> where T: AsRef<[u8]> {
|
||||
|
||||
+27
-28
@@ -29,6 +29,8 @@ use crate::{
|
||||
io::{self, prelude::*, BufReader, SeekFrom},
|
||||
};
|
||||
|
||||
pub use redox_exec::FdGuard;
|
||||
|
||||
use super::{errno, types::*, Pal, Read};
|
||||
|
||||
static mut BRK_CUR: *mut c_void = ptr::null_mut();
|
||||
@@ -43,6 +45,7 @@ mod clone;
|
||||
mod epoll;
|
||||
mod exec;
|
||||
mod extra;
|
||||
pub(crate) mod path;
|
||||
mod ptrace;
|
||||
mod signal;
|
||||
mod socket;
|
||||
@@ -61,6 +64,8 @@ macro_rules! path_from_c_str {
|
||||
}};
|
||||
}
|
||||
|
||||
use self::path::canonicalize;
|
||||
|
||||
pub fn e(sys: Result<usize>) -> usize {
|
||||
match sys {
|
||||
Ok(ok) => ok,
|
||||
@@ -163,7 +168,7 @@ impl Pal for Sys {
|
||||
|
||||
fn chdir(path: &CStr) -> c_int {
|
||||
let path = path_from_c_str!(path);
|
||||
e(syscall::chdir(path)) as c_int
|
||||
e(path::chdir(path).map(|()| 0)) as c_int
|
||||
}
|
||||
|
||||
fn chmod(path: &CStr, mode: mode_t) -> c_int {
|
||||
@@ -354,29 +359,20 @@ impl Pal for Sys {
|
||||
}
|
||||
|
||||
fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
|
||||
// TODO: Not using MaybeUninit seems a little unsafe
|
||||
|
||||
let buf_slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size as usize) };
|
||||
if !buf_slice.is_empty() {
|
||||
let nonnull_size = buf_slice.len() - 1;
|
||||
let read = e(syscall::getcwd(&mut buf_slice[..nonnull_size]));
|
||||
if read == !0 {
|
||||
ptr::null_mut()
|
||||
} else if read == nonnull_size {
|
||||
unsafe {
|
||||
errno = ERANGE;
|
||||
}
|
||||
ptr::null_mut()
|
||||
} else {
|
||||
for b in &mut buf_slice[read..] {
|
||||
*b = 0;
|
||||
}
|
||||
buf
|
||||
}
|
||||
} else {
|
||||
unsafe {
|
||||
errno = EINVAL;
|
||||
}
|
||||
ptr::null_mut()
|
||||
if buf_slice.is_empty() {
|
||||
unsafe { errno = EINVAL; }
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
if path::getcwd(buf_slice).is_none() {
|
||||
unsafe { errno = ERANGE; }
|
||||
return ptr::null_mut()
|
||||
}
|
||||
|
||||
buf
|
||||
}
|
||||
|
||||
fn getdents(fd: c_int, mut dirents: *mut dirent, max_bytes: usize) -> c_int {
|
||||
@@ -708,10 +704,13 @@ impl Pal for Sys {
|
||||
|
||||
fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
|
||||
let path = path_from_c_str!(path);
|
||||
e(syscall::open(
|
||||
path,
|
||||
((oflag as usize) & 0xFFFF_0000) | ((mode as usize) & 0xFFFF),
|
||||
)) as c_int
|
||||
|
||||
e(canonicalize(path).and_then(|canon| {
|
||||
syscall::open(
|
||||
&canon,
|
||||
((oflag as usize) & 0xFFFF_0000) | ((mode as usize) & 0xFFFF),
|
||||
)
|
||||
})) as c_int
|
||||
}
|
||||
|
||||
fn pipe2(fds: &mut [c_int], flags: c_int) -> c_int {
|
||||
@@ -764,7 +763,7 @@ impl Pal for Sys {
|
||||
|
||||
fn rmdir(path: &CStr) -> c_int {
|
||||
let path = path_from_c_str!(path);
|
||||
e(syscall::rmdir(path)) as c_int
|
||||
e(canonicalize(path).and_then(|path| syscall::rmdir(&path))) as c_int
|
||||
}
|
||||
|
||||
fn sched_yield() -> c_int {
|
||||
@@ -891,7 +890,7 @@ impl Pal for Sys {
|
||||
|
||||
fn unlink(path: &CStr) -> c_int {
|
||||
let path = path_from_c_str!(path);
|
||||
e(syscall::unlink(path)) as c_int
|
||||
e(canonicalize(path).and_then(|path| syscall::unlink(&path))) as c_int
|
||||
}
|
||||
|
||||
fn waitpid(mut pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
use syscall::error::*;
|
||||
use syscall::flag::*;
|
||||
|
||||
use alloc::borrow::ToOwned;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::sync::Mutex;
|
||||
|
||||
// TODO: Define in syscall
|
||||
const PATH_MAX: usize = 4096;
|
||||
|
||||
/// Make a relative path absolute.
|
||||
///
|
||||
/// Given a cwd of "scheme:/path", this his function will turn "foo" into "scheme:/path/foo".
|
||||
/// "/foo" will turn into "scheme:/foo". "bar:/foo" will be used directly, as it is already
|
||||
/// absolute
|
||||
pub fn canonicalize_using_cwd(cwd_opt: Option<&str>, path: &str) -> Option<String> {
|
||||
let mut canon = if path.find(':').is_none() {
|
||||
let cwd = cwd_opt?;
|
||||
let path_start = cwd.find(':')? + 1;
|
||||
|
||||
let mut canon = if !path.starts_with('/') {
|
||||
let mut c = cwd.to_owned();
|
||||
if ! c.ends_with('/') {
|
||||
c.push('/');
|
||||
}
|
||||
c
|
||||
} else {
|
||||
cwd[..path_start].to_owned()
|
||||
};
|
||||
|
||||
canon.push_str(&path);
|
||||
canon
|
||||
} else {
|
||||
path.to_owned()
|
||||
};
|
||||
|
||||
// NOTE: assumes the scheme does not include anything like "../" or "./"
|
||||
let mut result = {
|
||||
let parts = canon.split('/')
|
||||
.rev()
|
||||
.scan(0, |nskip, part| {
|
||||
if part == "." {
|
||||
Some(None)
|
||||
} else if part == ".." {
|
||||
*nskip += 1;
|
||||
Some(None)
|
||||
} else if *nskip > 0 {
|
||||
*nskip -= 1;
|
||||
Some(None)
|
||||
} else {
|
||||
Some(Some(part))
|
||||
}
|
||||
})
|
||||
.filter_map(|x| x)
|
||||
.filter(|x| !x.is_empty())
|
||||
.collect::<Vec<_>>();
|
||||
parts
|
||||
.iter()
|
||||
.rev()
|
||||
.fold(String::new(), |mut string, &part| {
|
||||
string.push_str(part);
|
||||
string.push('/');
|
||||
string
|
||||
})
|
||||
};
|
||||
result.pop(); // remove extra '/'
|
||||
|
||||
// replace with the root of the scheme if it's empty
|
||||
Some(if result.is_empty() {
|
||||
let pos = canon.find(':')
|
||||
.map_or(canon.len(), |p| p + 1);
|
||||
canon.truncate(pos);
|
||||
canon
|
||||
} else {
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
// XXX: chdir is not marked thread-safe (MT-safe) by POSIX. But on Linux it is simply run as a
|
||||
// syscall and is therefore atomic, which is presumably why Rust's libstd doesn't synchronize
|
||||
// access to this.
|
||||
//
|
||||
// https://internals.rust-lang.org/t/synchronized-ffi-access-to-posix-environment-variable-functions/15475
|
||||
//
|
||||
// chdir is however signal-safe, forbidding the use of locks. We therefore call sigprocmask before
|
||||
// and after acquiring the locks. (TODO: ArcSwap? That will need to be ported to no_std first,
|
||||
// though).
|
||||
pub fn chdir(path: &str) -> Result<()> {
|
||||
let _siglock = SignalMask::lock();
|
||||
let mut cwd_guard = CWD.lock();
|
||||
|
||||
let canonicalized = canonicalize_using_cwd(cwd_guard.as_deref(), path).ok_or(Error::new(ENOENT))?;
|
||||
|
||||
*cwd_guard = Some(canonicalized.into_boxed_str());
|
||||
|
||||
// TODO: Check that the dir exists and is a directory.
|
||||
|
||||
Ok(())
|
||||
|
||||
}
|
||||
|
||||
pub fn clone_cwd() -> Option<Box<str>> {
|
||||
let _siglock = SignalMask::lock();
|
||||
CWD.lock().clone()
|
||||
}
|
||||
|
||||
// TODO: MaybeUninit
|
||||
pub fn getcwd(buf: &mut [u8]) -> Option<usize> {
|
||||
let _siglock = SignalMask::lock();
|
||||
let cwd_guard = CWD.lock();
|
||||
let cwd = cwd_guard.as_deref().unwrap_or("").as_bytes();
|
||||
|
||||
// But is already checked not to be empty.
|
||||
if buf.len() - 1 < cwd.len() { return None; }
|
||||
|
||||
buf[..cwd.len()].copy_from_slice(&cwd);
|
||||
buf[cwd.len()..].fill(0_u8);
|
||||
|
||||
Some(cwd.len())
|
||||
}
|
||||
|
||||
// TODO: Move cwd from kernel to libc. It is passed via auxiliary vectors.
|
||||
pub fn canonicalize(path: &str) -> Result<String> {
|
||||
let _siglock = SignalMask::lock();
|
||||
let cwd = CWD.lock();
|
||||
canonicalize_using_cwd(cwd.as_deref(), path).ok_or(Error::new(ENOENT))
|
||||
}
|
||||
|
||||
// TODO: arraystring?
|
||||
static CWD: Mutex<Option<Box<str>>> = Mutex::new(None);
|
||||
|
||||
pub fn setcwd_manual(cwd: Box<str>) {
|
||||
let _siglock = SignalMask::lock();
|
||||
*CWD.lock() = Some(cwd);
|
||||
}
|
||||
|
||||
/// RAII guard able to magically fix signal unsafety, by disabling signals during a critical
|
||||
/// section.
|
||||
pub struct SignalMask {
|
||||
oldset: [u64; 2],
|
||||
}
|
||||
impl SignalMask {
|
||||
pub fn lock() -> Self {
|
||||
let mut oldset = [0; 2];
|
||||
syscall::sigprocmask(syscall::SIG_SETMASK, Some(&[!0, !0]), Some(&mut oldset)).expect("failed to run sigprocmask");
|
||||
Self { oldset }
|
||||
}
|
||||
}
|
||||
impl Drop for SignalMask {
|
||||
fn drop(&mut self) {
|
||||
let _ = syscall::sigprocmask(syscall::SIG_SETMASK, Some(&self.oldset), None);
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,11 @@ pub struct InterpOverride {
|
||||
tree: BTreeMap<usize, usize>,
|
||||
}
|
||||
|
||||
pub fn fexec_impl<A, E>(image_file: FdGuard, open_via_dup: FdGuard, memory_scheme_fd: &FdGuard, path: &[u8], args: A, envs: E, total_args_envs_size: usize, mut interp_override: Option<InterpOverride>) -> Result<FexecResult>
|
||||
pub struct ExtraInfo<'a> {
|
||||
pub cwd: Option<&'a [u8]>,
|
||||
}
|
||||
|
||||
pub fn fexec_impl<A, E>(image_file: FdGuard, open_via_dup: FdGuard, memory_scheme_fd: &FdGuard, path: &[u8], args: A, envs: E, total_args_envs_size: usize, extrainfo: &ExtraInfo, mut interp_override: Option<InterpOverride>) -> Result<FexecResult>
|
||||
where
|
||||
A: IntoIterator,
|
||||
E: IntoIterator,
|
||||
@@ -178,7 +182,8 @@ where
|
||||
push(interp_override.as_ref().map_or(header.e_phentsize as usize, |o| o.at_phent))?;
|
||||
push(AT_PHENT)?;
|
||||
|
||||
let args_envs_size_aligned = (total_args_envs_size+PAGE_SIZE-1)/PAGE_SIZE*PAGE_SIZE;
|
||||
let total_args_envs_auxvpointee_size = total_args_envs_size + extrainfo.cwd.map_or(0, |s| s.len() + 1);
|
||||
let args_envs_size_aligned = (total_args_envs_auxvpointee_size+PAGE_SIZE-1)/PAGE_SIZE*PAGE_SIZE;
|
||||
let target_args_env_address = find_free_target_addr(&tree, args_envs_size_aligned).ok_or(Error::new(ENOMEM))?;
|
||||
allocate_remote(&grants_fd, memory_scheme_fd, target_args_env_address, args_envs_size_aligned, MapFlags::PROT_READ | MapFlags::PROT_WRITE)?;
|
||||
tree.insert(target_args_env_address, args_envs_size_aligned);
|
||||
@@ -195,6 +200,13 @@ where
|
||||
Ok(address)
|
||||
};
|
||||
|
||||
if let Some(cwd) = extrainfo.cwd {
|
||||
push(append(cwd)?)?;
|
||||
push(AT_REDOX_INITIALCWD_PTR)?;
|
||||
push(cwd.len())?;
|
||||
push(AT_REDOX_INITIALCWD_LEN)?;
|
||||
}
|
||||
|
||||
push(0)?;
|
||||
|
||||
for env in envs {
|
||||
@@ -424,7 +436,6 @@ fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
|
||||
}
|
||||
|
||||
copy_str(*cur_pid_fd, *new_pid_fd, "name")?;
|
||||
copy_str(*cur_pid_fd, *new_pid_fd, "cwd")?;
|
||||
|
||||
{
|
||||
let cur_sigaction_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"sigactions")?);
|
||||
|
||||
+3
-1
@@ -4,7 +4,7 @@ use core::{intrinsics, ptr};
|
||||
use crate::{
|
||||
header::{libgen, stdio, stdlib},
|
||||
ld_so,
|
||||
platform::{self, new_mspace, types::*, Pal, Sys},
|
||||
platform::{self, get_auxvs, new_mspace, types::*, Pal, Sys},
|
||||
ALLOCATOR,
|
||||
};
|
||||
|
||||
@@ -185,6 +185,8 @@ pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! {
|
||||
platform::OUR_ENVIRON = copy_string_array(envp, len);
|
||||
platform::environ = platform::OUR_ENVIRON.as_mut_ptr();
|
||||
}
|
||||
let auxvs = get_auxvs(sp.auxv().cast());
|
||||
crate::platform::init(auxvs);
|
||||
|
||||
// Setup signal stack, otherwise we cannot handle any signals besides SIG_IGN/SIG_DFL behavior.
|
||||
#[cfg(target_os = "redox")]
|
||||
|
||||
Reference in New Issue
Block a user