diff --git a/src/RawPOSIX/src/interface/mem.rs b/src/RawPOSIX/src/interface/mem.rs index 48913cfc1..f136db368 100644 --- a/src/RawPOSIX/src/interface/mem.rs +++ b/src/RawPOSIX/src/interface/mem.rs @@ -50,9 +50,6 @@ pub fn round_up_page(length: u64) -> u64 { /// * `parent_vmmap` - vmmap struct of parent /// * `child_vmmap` - vmmap struct of child pub fn fork_vmmap(parent_vmmap: &Vmmap, child_vmmap: &Vmmap) { - let parent_base = parent_vmmap.base_address.unwrap(); - let child_base = child_vmmap.base_address.unwrap(); - // iterate through each vmmap entry for (_interval, entry) in parent_vmmap.entries.iter() { // translate page number to user address @@ -633,6 +630,7 @@ pub fn brk_handler(cageid: u64, brk: u32) -> i32 { } // update vmmap entry + vmmap.remove_entry(0, old_brk_page); let _ = vmmap.add_entry_with_overwrite( 0, brk_page, diff --git a/src/RawPOSIX/src/interface/signal.rs b/src/RawPOSIX/src/interface/signal.rs index 5efccc8d3..62448250e 100644 --- a/src/RawPOSIX/src/interface/signal.rs +++ b/src/RawPOSIX/src/interface/signal.rs @@ -138,19 +138,25 @@ pub fn signal_get_handler(cageid: u64, signo: i32) -> u32 { // send specified signal to the cage, return value indicates whether the cage exists // thread safety: this function could possibly be invoked by multiple threads of the same cage +// NOTE: signo should be checked to make sure it's valid before passing to this function pub fn lind_send_signal(cageid: u64, signo: i32) -> bool { if let Some(cage) = cagetable_getref_opt(cageid) { - let mut pending_signals = cage.pending_signals.write(); - // TODO: currently we are queuing the same signals instead of merging the same signal - // this is different from linux which always merge the same signal if they havn't been handled yet - // we queue the signals for now because our epoch based signal implementation could have much longer - // gap for signal checkings than linux. We need to finally decide whether do the queuing or merging - // in the future, probably based on some experimental data - pending_signals.push(signo); - - // we only trigger epoch if the signal is not blocked - if !signal_check_block(cageid, signo) { - signal_epoch_trigger(cageid); + // From https://man7.org/linux/man-pages/man2/kill.2.html + // If sig is 0, then no signal is sent, but existence and permission + // checks are still performed + if signo > 0 { + let mut pending_signals = cage.pending_signals.write(); + // TODO: currently we are queuing the same signals instead of merging the same signal + // this is different from linux which always merge the same signal if they havn't been handled yet + // we queue the signals for now because our epoch based signal implementation could have much longer + // gap for signal checkings than linux. We need to finally decide whether do the queuing or merging + // in the future, probably based on some experimental data + pending_signals.push(signo); + + // we only trigger epoch if the signal is not blocked + if !signal_check_block(cageid, signo) { + signal_epoch_trigger(cageid); + } } true diff --git a/src/RawPOSIX/src/safeposix/dispatcher.rs b/src/RawPOSIX/src/safeposix/dispatcher.rs index eb4297354..f66d7b013 100644 --- a/src/RawPOSIX/src/safeposix/dispatcher.rs +++ b/src/RawPOSIX/src/safeposix/dispatcher.rs @@ -1022,7 +1022,8 @@ pub fn lind_syscall_api( // Convert user space buffer address to physical address let optval_ptr = translate_vmmap_addr(&cage, arg4).unwrap() as *mut i32; let optval = unsafe { &mut *optval_ptr }; - cage.getsockopt_syscall(virtual_fd, level, optname, optval) + let optlen = arg5 as u32; + cage.getsockopt_syscall(virtual_fd, level, optname, optval, optlen) } SOCKETPAIR_SYSCALL => { @@ -1089,18 +1090,30 @@ pub fn lind_syscall_api( WAIT_SYSCALL => { let cage = interface::cagetable_getref(cageid); - // Convert user space buffer address to physical address - let status_addr = translate_vmmap_addr(&cage, arg1).unwrap() as u64; - let status = interface::get_i32_ref(status_addr).unwrap(); + // status could possibly be NULL + let status = { + if arg1 == 0 { + None + } else { + let status_addr = translate_vmmap_addr(&cage, arg1).unwrap() as u64; + Some(interface::get_i32_ref(status_addr).unwrap()) + } + }; cage.wait_syscall(status) } WAITPID_SYSCALL => { let pid = arg1 as i32; let cage = interface::cagetable_getref(cageid); - // Convert user space buffer address to physical address - let status_addr = translate_vmmap_addr(&cage, arg2).unwrap(); - let status = interface::get_i32_ref(status_addr).unwrap(); + // status could possibly be NULL + let status = { + if arg2 == 0 { + None + } else { + let status_addr = translate_vmmap_addr(&cage, arg2).unwrap() as u64; + Some(interface::get_i32_ref(status_addr).unwrap()) + } + }; let options = arg3 as i32; cage.waitpid_syscall(pid, status, options) diff --git a/src/RawPOSIX/src/safeposix/syscalls/fs_calls.rs b/src/RawPOSIX/src/safeposix/syscalls/fs_calls.rs index 8353bf216..90c81e45c 100644 --- a/src/RawPOSIX/src/safeposix/syscalls/fs_calls.rs +++ b/src/RawPOSIX/src/safeposix/syscalls/fs_calls.rs @@ -1435,9 +1435,10 @@ impl Cage { return syscall_error(Errno::EBADF, "getdents", "Bad File Descriptor"); } let vfd = wrappedvfd.unwrap(); + // calling getdents64 instead of getdents since glibc expects result from getdents64 let ret = unsafe { libc::syscall( - libc::SYS_getdents as c_long, + libc::SYS_getdents64 as c_long, vfd.underfd as i32, buf as *mut c_void, nbytes, diff --git a/src/RawPOSIX/src/safeposix/syscalls/net_calls.rs b/src/RawPOSIX/src/safeposix/syscalls/net_calls.rs index 50fe0df58..30bd0d403 100644 --- a/src/RawPOSIX/src/safeposix/syscalls/net_calls.rs +++ b/src/RawPOSIX/src/safeposix/syscalls/net_calls.rs @@ -657,6 +657,7 @@ impl Cage { level: i32, optname: i32, optval: &mut i32, + optlen: u32, ) -> i32 { let wrappedvfd = fdtables::translate_virtual_fd(self.cageid, virtual_fd as u64); if wrappedvfd.is_err() { diff --git a/src/RawPOSIX/src/safeposix/syscalls/sys_calls.rs b/src/RawPOSIX/src/safeposix/syscalls/sys_calls.rs index 96c4ce6e9..f4f958476 100644 --- a/src/RawPOSIX/src/safeposix/syscalls/sys_calls.rs +++ b/src/RawPOSIX/src/safeposix/syscalls/sys_calls.rs @@ -201,7 +201,7 @@ impl Cage { * into the end of its parent's zombie list. Then when parent wants to wait for any of child, it could just check its * zombie list and retrieve the first entry from it (first in, first out). */ - pub fn waitpid_syscall(&self, cageid: i32, status: &mut i32, options: i32) -> i32 { + pub fn waitpid_syscall(&self, cageid: i32, status: Option<&mut i32>, options: i32) -> i32 { let mut zombies = self.zombies.write(); let child_num = self.child_num.load(interface::RustAtomicOrdering::Relaxed); @@ -311,13 +311,13 @@ impl Cage { // reach here means we already found the desired exited child let zombie = zombie_opt.unwrap(); // update the status - *status = zombie.exit_code; + let _ = status.map(|st| *st = zombie.exit_code); // return child's cageid zombie.cageid as i32 } - pub fn wait_syscall(&self, status: &mut i32) -> i32 { + pub fn wait_syscall(&self, status: Option<&mut i32>) -> i32 { self.waitpid_syscall(0, status, 0) } @@ -336,7 +336,7 @@ impl Cage { if self.getgid.load(interface::RustAtomicOrdering::Relaxed) == -1 { self.getgid .store(DEFAULT_GID as i32, interface::RustAtomicOrdering::Relaxed); - return -1; + return DEFAULT_GID as i32; } DEFAULT_GID as i32 //Lind is only run in one group so a default value is returned } @@ -344,7 +344,7 @@ impl Cage { if self.getegid.load(interface::RustAtomicOrdering::Relaxed) == -1 { self.getegid .store(DEFAULT_GID as i32, interface::RustAtomicOrdering::Relaxed); - return -1; + return DEFAULT_GID as i32; } DEFAULT_GID as i32 //Lind is only run in one group so a default value is returned } @@ -353,7 +353,7 @@ impl Cage { if self.getuid.load(interface::RustAtomicOrdering::Relaxed) == -1 { self.getuid .store(DEFAULT_UID as i32, interface::RustAtomicOrdering::Relaxed); - return -1; + return DEFAULT_UID as i32; } DEFAULT_UID as i32 //Lind is only run as one user so a default value is returned } @@ -361,7 +361,7 @@ impl Cage { if self.geteuid.load(interface::RustAtomicOrdering::Relaxed) == -1 { self.geteuid .store(DEFAULT_UID as i32, interface::RustAtomicOrdering::Relaxed); - return -1; + return DEFAULT_UID as i32; } DEFAULT_UID as i32 //Lind is only run as one user so a default value is returned } @@ -407,6 +407,15 @@ impl Cage { return syscall_error(Errno::EINVAL, "sigkill", "Invalid signal number"); } + // if cage id is 0, send signal to itself + let cage_id = { + if cage_id == 0 { + self.cageid + } else { + cage_id as u64 + } + }; + if !lind_send_signal(cage_id as u64, sig) { return syscall_error(Errno::ESRCH, "kill", "Target cage does not exist"); }