diff --git a/src/RawPOSIX/src/safeposix/dispatcher.rs b/src/RawPOSIX/src/safeposix/dispatcher.rs index bb3a86ad..2e3e5f16 100644 --- a/src/RawPOSIX/src/safeposix/dispatcher.rs +++ b/src/RawPOSIX/src/safeposix/dispatcher.rs @@ -138,7 +138,6 @@ use crate::interface::{SigactionStruct, StatData}; use crate::{fdtables, interface}; use crate::interface::errnos::*; use crate::constants::*; -use crate::interface::check_and_convert_addr_ext; macro_rules! get_onearg { ($arg: expr) => { @@ -203,146 +202,59 @@ pub fn lind_syscall_api( let ret = match call_number { WRITE_SYSCALL => { - // Handles writing data from user buffer to file descriptor - - // Get file descriptor let fd = arg1 as i32; - + let buf = (start_address + arg2) as *const u8; let count = arg3 as usize; - if count == 0 { - return 0; // Early return for zero-length writes - } - - // Get cage reference for memory operations - let cage = interface::cagetable_getref(cageid); - - // Validate and convert user buffer address to system address - // PROT_READ is correct because write() reads FROM the buffer - let buf = match check_and_convert_addr_ext(&cage, arg2, count, PROT_READ) { - Ok(addr) => addr as *const u8, - Err(errno) => { - return syscall_error( - errno, - "write", - "buffer access violation or invalid address" - ); - } - }; - - // Perform write operation through cage abstraction - cage.write_syscall(fd, buf, count) + interface::cagetable_getref(cageid) + .write_syscall(fd, buf, count) } WRITEV_SYSCALL => { let fd = arg1 as i32; + let iovec = (start_address + arg2) as *const interface::IovecStruct; let iovcnt = arg3 as i32; - - // Validate count first - if iovcnt <= 0 { - return syscall_error( - Errno::EINVAL, - "writev", - "invalid iovec count" - ); - } - - let cage = interface::cagetable_getref(cageid); - - // Validate the iovec array address first - let iov_base = match check_and_convert_addr_ext( - &cage, - arg2, - (iovcnt as usize) * std::mem::size_of::(), - PROT_READ - ) { - Ok(addr) => addr as *const interface::IovecStruct, - Err(errno) => { - return syscall_error( - errno, - "writev", - "invalid iovec array address" - ); - } - }; - - // The actual write operation is delegated to the cage implementation - cage.writev_syscall(fd, iov_base, iovcnt) + + interface::cagetable_getref(cageid) + .writev_syscall(fd, iovec, iovcnt) } MUNMAP_SYSCALL => { - let addr = arg1 as *mut u8; - let length = arg2 as usize; - let cage = interface::cagetable_getref(cageid); - - if length == 0 { - return syscall_error( - Errno::EINVAL, - "munmap", - "length cannot be zero" - ); - } - - // Perform the unmapping operation - interface::munmap_handler(cageid, addr, length) + let addr = (start_address + arg1) as *mut u8; + let len = arg2 as usize; + + interface::cagetable_getref(cageid) + .munmap_syscall(addr, len) } MMAP_SYSCALL => { - let addr = arg1 as *mut u8; + let addr = (start_address + arg1) as *mut u8; let len = arg2 as usize; let prot = arg3 as i32; let flags = arg4 as i32; - let fd = arg5 as i32; + let fildes = arg5 as i32; let off = arg6 as i64; - - // Basic length validation - if len == 0 { - return syscall_error( - Errno::EINVAL, - "mmap", - "length cannot be zero" - ); - } - - // Force MAP_FIXED - let flags = flags | MAP_FIXED as i32; - - // Turn off PROT_EXEC for non-code pages - let prot = prot & !PROT_EXEC; - - interface::mmap_handler(cageid, addr, len, prot, flags, fd, off) as i32 + + interface::cagetable_getref(cageid) + .mmap_syscall(addr, len, prot, flags, fildes, off) } PREAD_SYSCALL => { let fd = arg1 as i32; + let buf = (start_address + arg2) as *mut u8; let count = arg3 as usize; let offset = arg4 as i64; - let cage = interface::cagetable_getref(cageid); - - // Validate and convert user buffer address - // Using PROT_WRITE since pread writes TO the buffer - let buf = match check_and_convert_addr_ext(&cage, arg2, count, PROT_WRITE) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "pread", "invalid buffer address"), - }; - - cage.pread_syscall(fd, buf, count, offset) + + interface::cagetable_getref(cageid) + .pread_syscall(fd, buf, count, offset) } READ_SYSCALL => { let fd = arg1 as i32; + let buf = (start_address + arg2) as *mut u8; let count = arg3 as usize; - let cage = interface::cagetable_getref(cageid); - - // Validate and convert user buffer address - // Using PROT_WRITE since read() writes TO the buffer - let buf = match check_and_convert_addr_ext(&cage, arg2, count, PROT_WRITE) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "read", "invalid buffer address"), - }; - // File descriptor validation and actual read operation - // handled by cage implementation - cage.read_syscall(fd, buf, count) + interface::cagetable_getref(cageid) + .read_syscall(fd, buf, count) } CLOSE_SYSCALL => { @@ -354,38 +266,26 @@ pub fn lind_syscall_api( } ACCESS_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert path string from user space - let path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr as u64) { - Ok(path_str) => path_str, - Err(_) => return -1, - }, - Err(errno) => return syscall_error(errno, "access", "invalid path address"), + let path = match interface::types::get_cstr(start_address + arg1) { + Ok(path_str) => path_str, + Err(_) => return -1, // Handle error appropriately, return an error code }; let amode = arg2 as i32; - // Perform access check through cage implementation - cage.access_syscall(path, amode) + interface::cagetable_getref(cageid) + .access_syscall(path, amode) } OPEN_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert path string from user space - let path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr as u64) { - Ok(path_str) => path_str, - Err(_) => return -1, - }, - Err(errno) => return syscall_error(errno, "open", "invalid path address"), + let path = match interface::types::get_cstr(start_address + arg1) { + Ok(path_str) => path_str, + Err(_) => return -1, // Handle error appropriately, return an error code }; let flags = arg2 as i32; let mode = arg3 as u32; - - // Perform open operation through cage implementation - cage.open_syscall(path, flags, mode) + + interface::cagetable_getref(cageid) + .open_syscall(path, flags, mode) } SOCKET_SYSCALL => { @@ -401,81 +301,45 @@ pub fn lind_syscall_api( CONNECT_SYSCALL => { let fd = arg1 as i32; - let cage = interface::cagetable_getref(cageid); - - // Validate and convert sockaddr from user space - let addr = match check_and_convert_addr_ext(&cage, arg2, arg3 as usize, PROT_READ) { - Ok(addr) => match interface::get_sockaddr(addr as u64, arg3 as u32) { - Ok(sockaddr) => sockaddr, - Err(_) => return syscall_error(Errno::EINVAL, "connect", "invalid sockaddr format"), - }, - Err(errno) => return syscall_error(errno, "connect", "invalid address"), - }; + let addrlen = arg3 as u32; + let addr = get_onearg!(interface::get_sockaddr(arg2, addrlen)); - // Convert to reference for connect operation let remoteaddr = match Ok::<&interface::GenSockaddr, i32>(&addr) { Ok(addr) => addr, Err(_) => panic!("Failed to get sockaddr"), // Handle error appropriately }; - - // Perform connect operation through cage implementation - // File descriptor validation handled by cage layer - cage.connect_syscall(fd, remoteaddr) + interface::cagetable_getref(cageid) + .connect_syscall(fd, remoteaddr) } BIND_SYSCALL => { let fd = arg1 as i32; - let cage = interface::cagetable_getref(cageid); - - // Validate and convert sockaddr from user space - let addr = match check_and_convert_addr_ext(&cage, arg2, arg3 as usize, PROT_READ) { - Ok(addr) => match interface::get_sockaddr(addr as u64, arg3 as u32) { - Ok(sockaddr) => sockaddr, - Err(_) => return syscall_error(Errno::EINVAL, "bind", "invalid sockaddr format"), - }, - Err(errno) => return syscall_error(errno, "bind", "invalid address"), - }; - - // Convert to reference for bind operation + let addrlen = arg3 as u32; + let addr = interface::get_sockaddr(start_address + arg2, addrlen).unwrap(); let localaddr = match Ok::<&interface::GenSockaddr, i32>(&addr) { Ok(addr) => addr, Err(_) => panic!("Failed to get sockaddr"), // Handle error appropriately }; - - // Perform bind operation through cage implementation - // File descriptor validation handled by cage layer - cage.bind_syscall(fd, localaddr) + interface::cagetable_getref(cageid) + .bind_syscall(fd, localaddr) } ACCEPT_SYSCALL => { - let mut addr = interface::GenSockaddr::V4(interface::SockaddrV4::default()); + let mut addr = interface::GenSockaddr::V4(interface::SockaddrV4::default()); //value doesn't matter let nullity1 = interface::arg_nullity(arg2); let nullity2 = interface::arg_nullity(arg3); - let cage = interface::cagetable_getref(cageid); - - // Handle NULL address case (both NULL) + if nullity1 && nullity2 { - cage.accept_syscall(arg1 as i32, &mut Some(&mut addr)) - } - // Handle non-NULL case (both non-NULL) - else if !(nullity1 || nullity2) { - // Perform accept operation first - let rv = cage.accept_syscall(arg1 as i32, &mut Some(&mut addr)); + interface::cagetable_getref(cageid) + .accept_syscall(arg1 as i32, &mut Some(&mut addr)) + } else if !(nullity1 || nullity2) { + let rv = interface::cagetable_getref(cageid) + .accept_syscall(arg1 as i32, &mut Some(&mut addr)); if rv >= 0 { - let addr2_addr = match check_and_convert_addr_ext(&cage, arg2, arg3 as usize, PROT_WRITE) { - Ok(addr) => addr, - Err(errno) => return syscall_error(errno, "accept", "invalid address buffer"), - }; - let len_addr = match check_and_convert_addr_ext(&cage, arg3, std::mem::size_of::(), PROT_WRITE) { - Ok(addr) => addr, - Err(errno) => return syscall_error(errno, "accept", "invalid length buffer"), - }; - interface::copy_out_sockaddr(addr2_addr as u64, len_addr as u64, addr); + interface::copy_out_sockaddr((start_address + arg2), (start_address + arg3), addr); } rv - } - // Handle invalid case (one NULL, one non-NULL) - else { + } else { syscall_error( Errno::EINVAL, "accept", @@ -505,152 +369,68 @@ pub fn lind_syscall_api( SELECT_SYSCALL => { // Get the number of file descriptors to check (highest fd + 1) let nfds = arg1 as i32; - // Get reference to the cage for memory operations - let cage = interface::cagetable_getref(cageid); - - // Validate and convert readfds buffer - // 1. check_and_convert_addr_ext validates memory access and converts user address to system address - // 2. PROT_READ | PROT_WRITE because select() both reads from and modifies the fd_sets - // 3. get_fdset converts the raw memory into an fd_set structure - let readfds = match check_and_convert_addr_ext(&cage, arg2, std::mem::size_of::(), PROT_READ | PROT_WRITE) { - Ok(addr) => match interface::get_fdset(addr) { - Ok(fds) => fds, - Err(_) => return syscall_error(Errno::EFAULT, "select", "failed to get readfds"), - }, - Err(errno) => return syscall_error(errno, "select", "invalid readfds address"), - }; - - // Validate and convert writefds buffer - // Similar to readfds, this fd_set indicates which descriptors to check for write-ready status - // The fd_set will be modified to show which descriptors are actually write-ready - let writefds = match check_and_convert_addr_ext(&cage, arg3, std::mem::size_of::(), PROT_READ | PROT_WRITE) { - Ok(addr) => match interface::get_fdset(addr) { - Ok(fds) => fds, - Err(_) => return syscall_error(Errno::EFAULT, "select", "failed to get writefds"), - }, - Err(errno) => return syscall_error(errno, "select", "invalid writefds address"), - }; - - // Validate and convert errorfds buffer (also called exceptfds in some implementations) - // This fd_set is used to monitor for exceptional conditions (like out-of-band data) - // Also requires both read and write access as select() modifies it - let errorfds = match check_and_convert_addr_ext(&cage, arg4, std::mem::size_of::(), PROT_READ | PROT_WRITE) { - Ok(addr) => match interface::get_fdset(addr) { - Ok(fds) => fds, - Err(_) => return syscall_error(Errno::EFAULT, "select", "failed to get errorfds"), - }, - Err(errno) => return syscall_error(errno, "select", "invalid errorfds address"), - }; - - // Validate and convert timeout buffer - // 1. Only needs PROT_READ as the timeout value is not modified by select() - // 2. duration_fromtimeval converts the timeval structure to a Duration - // 3. This specifies how long select() should block waiting for activity - let rposix_timeout = match check_and_convert_addr_ext(&cage, arg5, std::mem::size_of::(), PROT_READ) { - Ok(addr) => match interface::duration_fromtimeval(addr) { - Ok(timeout) => timeout, - Err(_) => return syscall_error(Errno::EFAULT, "select", "failed to get timeout"), - }, - Err(errno) => return syscall_error(errno, "select", "invalid timeout address"), - }; - - // Delegate to the cage's select implementation - // This will: - // 1. Monitor the specified file descriptors for activity - // 2. Modify the fd_sets to indicate which descriptors are ready - // 3. Return the number of ready descriptors or an error code - cage.select_syscall(nfds, readfds, writefds, errorfds, rposix_timeout) + let readfds = interface::get_fdset(arg2).unwrap(); + let writefds = interface::get_fdset(arg3).unwrap(); + let errorfds = interface::get_fdset(arg4).unwrap(); + let rposix_timeout = interface::duration_fromtimeval(arg5).unwrap(); + interface::cagetable_getref(cageid) + .select_syscall(nfds, readfds, writefds, errorfds, rposix_timeout) } RENAME_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert old path from user space - let old_path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "rename", "invalid old path string"), - }, - Err(errno) => return syscall_error(errno, "rename", "invalid old path address"), + let old_ptr = (start_address + arg1) as *const u8; + let new_ptr = (start_address + arg2) as *const u8; + + // Convert the raw pointers to `&str` + let old = unsafe { + CStr::from_ptr(old_ptr as *const i8).to_str().unwrap() }; - - // Validate and convert new path from user space - let new_path = match check_and_convert_addr_ext(&cage, arg2, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "rename", "invalid new path string"), - }, - Err(errno) => return syscall_error(errno, "rename", "invalid new path address"), + let new = unsafe { + CStr::from_ptr(new_ptr as *const i8).to_str().unwrap() }; - // Perform rename operation through cage implementation - cage.rename_syscall(old_path, new_path) + interface::cagetable_getref(cageid) + .rename_syscall(old, new) } XSTAT_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert path string from user space - // Using PROT_READ because we need to read the path string FROM user space - // (stat takes the path as input, we don't write to it) - let path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "xstat", "invalid path string"), - }, - Err(errno) => return syscall_error(errno, "xstat", "invalid path address"), + let fd_ptr = (start_address + arg1) as *const u8; + let buf = match interface::get_statdatastruct(start_address + arg2) { + Ok(val) => val, + Err(errno) => { + return errno; + } }; - - // Validate stat buffer and prepare for writing - // Using PROT_WRITE because stat() writes the results TO this user space buffer - let buf = match check_and_convert_addr_ext(&cage, arg2, std::mem::size_of::(), PROT_WRITE) { - Ok(addr) => match interface::get_statdatastruct(addr) { - Ok(val) => val, - Err(errno) => return errno, - }, - Err(errno) => return syscall_error(errno, "xstat", "invalid stat buffer address"), + + let fd = unsafe { + CStr::from_ptr(fd_ptr as *const i8).to_str().unwrap() }; - - // Perform stat operation through cage implementation - // Results written directly to user buffer by cage layer - cage.stat_syscall(path, buf) + + interface::cagetable_getref(cageid) + .stat_syscall(fd, buf) } MKDIR_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert path string from user space - // Using PROT_READ because we need to read the path string FROM user space - // (mkdir takes the path as input, we don't write to it) - let path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "mkdir", "invalid path string"), - }, - Err(errno) => return syscall_error(errno, "mkdir", "invalid path address"), - }; + let fd_ptr = (start_address + arg1) as *const u8; let mode = arg2 as u32; - - // Perform mkdir operation through cage implementation - cage.mkdir_syscall(path, mode) + + let fd= unsafe { + CStr::from_ptr(fd_ptr as *const i8).to_str().unwrap() + }; + + interface::cagetable_getref(cageid) + .mkdir_syscall(fd, mode) } RMDIR_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert path string from user space - // Using PROT_READ because we need to read the path string FROM user space - // (rmdir takes the path as input, we don't write to it) - let path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "rmdir", "invalid path string"), - }, - Err(errno) => return syscall_error(errno, "rmdir", "invalid path address"), - }; + let fd_ptr = (start_address + arg1) as *const u8; + + let fd= unsafe { + CStr::from_ptr(fd_ptr as *const i8).to_str().unwrap() + }; - // Perform rmdir operation through cage implementation - cage.rmdir_syscall(path) + interface::cagetable_getref(cageid) + .rmdir_syscall(fd) } FCHDIR_SYSCALL => { @@ -663,78 +443,39 @@ pub fn lind_syscall_api( } CHDIR_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert path string from user space - // Using PROT_READ because we need to read the path string FROM user space - // (chdir takes the path as input, we don't write to it) - let path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "chdir", "invalid path string"), - }, - Err(errno) => return syscall_error(errno, "chdir", "invalid path address"), - }; + let path = interface::types::get_cstr(start_address + arg1).unwrap(); - // Perform chdir operation through cage implementation - cage.chdir_syscall(path) + interface::cagetable_getref(cageid) + .chdir_syscall(path) } GETCWD_SYSCALL => { - let bufsize = arg2 as usize; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing - // Using PROT_WRITE because getcwd() writes the current working directory path - // TO this user space buffer - let buf = match check_and_convert_addr_ext(&cage, arg1, bufsize, PROT_WRITE) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "getcwd", "invalid buffer address"), - }; - - // Perform getcwd operation through cage implementation - // On success (ret == 0), return the buffer address - let ret = cage.getcwd_syscall(buf, bufsize as u32); + let buf = (start_address + arg1) as *mut u8; + let bufsize = arg2 as u32; + + let ret = interface::cagetable_getref(cageid) + .getcwd_syscall(buf, bufsize); if ret == 0 { return arg1 as i32; } ret } + FSTATFS_SYSCALL => { let fd = arg1 as i32; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing filesystem information - // Using PROT_WRITE because fstatfs() writes filesystem information - // TO this user space buffer - let buf = match check_and_convert_addr_ext(&cage, arg2, 1, PROT_WRITE) { - Ok(addr) => match interface::get_fsdatastruct(addr) { - Ok(val) => val, - Err(errno) => return errno, - }, - Err(errno) => return syscall_error(errno, "fstatfs", "invalid buffer address"), - }; + let buf = interface::get_fsdatastruct(start_address + arg2).unwrap(); - // Perform fstatfs operation through cage implementation - // File descriptor validation and actual operation handled by cage layer - cage.fstatfs_syscall(fd, buf) + interface::cagetable_getref(cageid) + .fstatfs_syscall(fd, buf) } CHMOD_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert path string from user space - // Using PROT_READ because we need to read the path string FROM user space - // (chmod takes the path as input, we don't write to it) - let path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "chmod", "invalid path string"), - }, - Err(errno) => return syscall_error(errno, "chmod", "invalid path address"), + let fd_ptr = (start_address + arg1) as *const u8; + let fd= unsafe { + CStr::from_ptr(fd_ptr as *const i8).to_str().unwrap() }; let mode = arg2 as u32; - - // Perform chmod operation through cage implementation - cage.chmod_syscall(path, mode) + + interface::cagetable_getref(cageid) + .chmod_syscall(fd, mode) } DUP_SYSCALL => { @@ -775,63 +516,36 @@ pub fn lind_syscall_api( FXSTAT_SYSCALL => { let fd = arg1 as i32; - let cage = interface::cagetable_getref(cageid); - - // Validate stat buffer and prepare for writing - // Using PROT_WRITE because fstat() writes the results TO this user space buffer - let buf = match check_and_convert_addr_ext(&cage, arg2, std::mem::size_of::(), PROT_WRITE) { - Ok(addr) => interface::get_statdatastruct(addr).unwrap(), - Err(errno) => return syscall_error(errno, "fxstat", "invalid buffer address"), - }; + let buf = interface::get_statdatastruct(start_address + arg2).unwrap(); - // Perform fstat operation through cage implementation - // File descriptor validation and actual operation handled by cage layer - cage.fstat_syscall(fd, buf) + interface::cagetable_getref(cageid) + .fstat_syscall(fd, buf) } UNLINK_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert path string from user space - // Using PROT_READ because we need to read the path string FROM user space - // (unlink takes the path as input, we don't write to it) - let path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "unlink", "invalid path string"), - }, - Err(errno) => return syscall_error(errno, "unlink", "invalid path address"), - }; + let fd_ptr = (start_address + arg1) as *const u8; - // Perform unlink operation through cage implementation - cage.unlink_syscall(path) + let fd = unsafe { + CStr::from_ptr(fd_ptr as *const i8).to_str().unwrap() + }; + + interface::cagetable_getref(cageid) + .unlink_syscall(fd) } LINK_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert old path string from user space - // Using PROT_READ because we need to read the path string FROM user space - let old_path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "link", "invalid old path string"), - }, - Err(errno) => return syscall_error(errno, "link", "invalid old path address"), - }; + let old_ptr = (start_address + arg1) as *const u8; + let new_ptr = (start_address + arg1) as *const u8; - // Validate and convert new path string from user space - // Using PROT_READ because we need to read the path string FROM user space - let new_path = match check_and_convert_addr_ext(&cage, arg2, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "link", "invalid new path string"), - }, - Err(errno) => return syscall_error(errno, "link", "invalid new path address"), - }; - - // Perform link operation through cage implementation - cage.link_syscall(old_path, new_path) + let old_fd= unsafe { + CStr::from_ptr(old_ptr as *const i8).to_str().unwrap() + }; + let new_fd = unsafe { + CStr::from_ptr(new_ptr as *const i8).to_str().unwrap() + }; + + interface::cagetable_getref(cageid) + .link_syscall(old_fd, new_fd) } LSEEK_SYSCALL => { @@ -857,21 +571,15 @@ pub fn lind_syscall_api( } TRUNCATE_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert path string from user space - // Using PROT_READ because we need to read the path string FROM user space - let path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "truncate", "invalid path string"), - }, - Err(errno) => return syscall_error(errno, "truncate", "invalid path address"), - }; + let fd_ptr = (start_address + arg1) as *const u8; let length = arg2 as isize; - - // Perform truncate operation through cage implementation - cage.truncate_syscall(path, length) + + let fd = unsafe { + CStr::from_ptr(fd_ptr as *const i8).to_str().unwrap() + }; + + interface::cagetable_getref(cageid) + .truncate_syscall(fd, length) } FTRUNCATE_SYSCALL => { @@ -886,46 +594,23 @@ pub fn lind_syscall_api( GETDENTS_SYSCALL => { let virtual_fd = arg1 as i32; + let buf = (start_address + arg2) as *mut u8; let nbytes = arg3 as u32; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing directory entries - // Using PROT_WRITE because getdents() writes directory entries TO this user space buffer - let buf = match check_and_convert_addr_ext(&cage, arg2, nbytes as usize, PROT_WRITE) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "getdents", "invalid buffer address"), - }; - - // Perform getdents operation through cage implementation - // File descriptor validation handled by cage layer - cage.getdents_syscall(virtual_fd, buf, nbytes) + + interface::cagetable_getref(cageid) + .getdents_syscall(virtual_fd, buf, nbytes) } STATFS_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate and convert path string from user space - // Using PROT_READ because we need to read the path string FROM user space - let path = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ) { - Ok(addr) => match interface::types::get_cstr(addr) { - Ok(path_str) => path_str, - Err(_) => return syscall_error(Errno::EFAULT, "statfs", "invalid path string"), - }, - Err(errno) => return syscall_error(errno, "statfs", "invalid path address"), - }; + let fd_ptr = (start_address + arg1) as *const u8; + let rposix_databuf = interface::get_fsdatastruct(start_address + arg2).unwrap(); - // Validate buffer for writing filesystem information - // Using PROT_WRITE because statfs() writes filesystem information TO this user space buffer - let rposix_databuf = match check_and_convert_addr_ext(&cage, arg2, 1, PROT_WRITE) { - Ok(addr) => match interface::get_fsdatastruct(addr) { - Ok(val) => val, - Err(errno) => return syscall_error(Errno::EFAULT, "statfs", "invalid stat buffer format"), - }, - Err(errno) => return syscall_error(errno, "statfs", "invalid stat buffer address"), - }; + let fd = unsafe { + CStr::from_ptr(fd_ptr as *const i8).to_str().unwrap() + }; - // Perform statfs operation through cage implementation - cage.statfs_syscall(&path, rposix_databuf) + interface::cagetable_getref(cageid) + .statfs_syscall(fd, rposix_databuf) } FCNTL_SYSCALL => { @@ -941,76 +626,46 @@ pub fn lind_syscall_api( RECV_SYSCALL => { let fd = arg1 as i32; - let count = arg3 as usize; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing received data - // Using PROT_WRITE because recv() writes received data TO this user space buffer - let buf = match check_and_convert_addr_ext(&cage, arg2, count, PROT_WRITE) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "recv", "invalid buffer address"), - }; + let buf = (start_address + arg2) as *mut u8; + let buflen = arg3 as usize; let flag = arg4 as i32; - - // Perform recv operation through cage implementation - // File descriptor validation handled by cage layer - cage.recv_syscall(fd, buf, count, flag) + + interface::cagetable_getref(cageid) + .recv_syscall(fd, buf, buflen, flag) } SENDTO_SYSCALL => { let fd = arg1 as i32; - let count = arg3 as usize; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for reading data to send - // Using PROT_READ because we need to read the data FROM user space - let buf = match check_and_convert_addr_ext(&cage, arg2, count, PROT_READ) { - Ok(addr) => addr as *const u8, - Err(errno) => return syscall_error(errno, "sendto", "invalid buffer address"), - }; + let buf = (start_address + arg2) as *const u8; + let buflen = arg3 as usize; let flag = arg4 as i32; // Get and validate socket address let addrlen = arg6 as u32; - let addr = match interface::get_sockaddr(start_address + arg5, addrlen) { - Ok(addr) => addr, - Err(_) => return syscall_error(Errno::EFAULT, "sendto", "invalid socket address"), - }; - - // Perform sendto operation through cage implementation - // File descriptor validation handled by cage layer - cage.sendto_syscall(fd, buf, count, flag, &addr) + let addr = interface::get_sockaddr(start_address + arg5, addrlen).unwrap(); + + interface::cagetable_getref(cageid) + .sendto_syscall(fd, buf, buflen, flag, &addr) } RECVFROM_SYSCALL => { let fd = arg1 as i32; - let count = arg3 as usize; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing received data - // Using PROT_WRITE because recvfrom() writes received data TO this user space buffer - let buf = match check_and_convert_addr_ext(&cage, arg2, count, PROT_WRITE) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "recvfrom", "invalid buffer address"), - }; + let buf = (start_address + arg2) as *mut u8; + let buflen = arg3 as usize; let flag = arg4 as i32; - - // Check if address and length arguments are provided let nullity1 = interface::arg_nullity(arg5); let nullity2 = interface::arg_nullity(arg6); // Handle different cases based on address arguments if nullity1 && nullity2 { - // Both address and length are NULL - simple receive - cage.recvfrom_syscall(fd, buf, count, flag, &mut None) - } + interface::cagetable_getref(cageid) + .recvfrom_syscall(fd, buf, buflen, flag, &mut None) + } else if !(nullity1 || nullity2) { - // Both address and length are provided - // Create a default sockaddr to store the sender's address - let mut newsockaddr = interface::GenSockaddr::V4(interface::SockaddrV4::default()); - - // Perform recvfrom operation - let rv = cage.recvfrom_syscall(fd, buf, count, flag, &mut Some(&mut newsockaddr)); + let mut newsockaddr = interface::GenSockaddr::V4(interface::SockaddrV4::default()); //dummy value, rust would complain if we used an uninitialized value here + + let rv = interface::cagetable_getref(cageid) + .recvfrom_syscall(fd, buf, buflen, flag, &mut Some(&mut newsockaddr)); if rv >= 0 { // Copy address information back to user space on success interface::copy_out_sockaddr(start_address + arg5, start_address + arg6, newsockaddr); @@ -1045,34 +700,21 @@ pub fn lind_syscall_api( interface::cagetable_getref(cageid) .shmget_syscall(key, size, shmfig) } + SHMAT_SYSCALL => { let shmid = arg1 as i32; - let cage = interface::cagetable_getref(cageid); - - // Validate shared memory address - // Using both PROT_READ and PROT_WRITE since shared memory needs both access types - let shmaddr = match check_and_convert_addr_ext(&cage, arg2, 1, PROT_READ | PROT_WRITE) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "shmat", "invalid shared memory address"), - }; + let shmaddr = (start_address + arg2) as *mut u8; let shmflg = arg3 as i32; - - // Perform shmat operation through cage implementation - cage.shmat_syscall(shmid, shmaddr, shmflg) + + interface::cagetable_getref(cageid) + .shmat_syscall(shmid, shmaddr, shmflg) } SHMDT_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate shared memory address - // Using both PROT_READ and PROT_WRITE since shared memory needs both access types - let shmaddr = match check_and_convert_addr_ext(&cage, arg1, 1, PROT_READ | PROT_WRITE) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "shmdt", "invalid shared memory address"), - }; + let shmaddr = (start_address + arg1) as *mut u8; - // Perform shmdt operation through cage implementation - cage.shmdt_syscall(shmaddr) + interface::cagetable_getref(cageid) + .shmdt_syscall(shmaddr) } MUTEX_DESTROY_SYSCALL => { @@ -1191,19 +833,13 @@ pub fn lind_syscall_api( } PWRITE_SYSCALL => { - let count = arg3 as usize; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for reading data to write - // Using PROT_READ because we need to read the data FROM user space - let buf = match check_and_convert_addr_ext(&cage, arg2, count, PROT_READ) { - Ok(addr) => addr as *const u8, - Err(errno) => return syscall_error(errno, "pwrite", "invalid buffer address"), - }; let virtual_fd = arg1 as i32; + let buf = (start_address + arg2) as *const u8; + let count = arg3 as usize; let offset = arg4 as i64; - - cage.pwrite_syscall(virtual_fd, buf, count, offset) + + interface::cagetable_getref(cageid) + .pwrite_syscall(virtual_fd, buf, count, offset) } GETUID_SYSCALL => { @@ -1261,18 +897,11 @@ pub fn lind_syscall_api( let virtual_fd = arg1 as i32; let level = arg2 as i32; let optname = arg3 as i32; - let optlen = arg5 as u32; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for reading socket option value - // Using PROT_READ because we need to read the option value FROM user space - let optval = match check_and_convert_addr_ext(&cage, arg4, optlen as usize, PROT_READ) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "setsockopt", "invalid optval address"), - }; + let optval = (start_address + arg4) as *mut u8; + let optlen = arg5 as u32; - // Perform setsockopt operation through cage implementation - cage.setsockopt_syscall(virtual_fd, level, optname, optval, optlen) + interface::cagetable_getref(cageid) + .setsockopt_syscall( virtual_fd, level, optname, optval, optlen) } SHUTDOWN_SYSCALL => { @@ -1290,19 +919,13 @@ pub fn lind_syscall_api( } SEND_SYSCALL => { - let fd = arg1 as i32; - let count = arg3 as usize; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for reading data to send - // Using PROT_READ because we need to read the data FROM user space - let buf = match check_and_convert_addr_ext(&cage, arg2, count, PROT_READ) { - Ok(addr) => addr as *const u8, - Err(errno) => return syscall_error(errno, "send", "invalid buffer address"), - }; + let virtual_fd = arg1 as i32; + let buf = (start_address + arg4) as *const u8; + let buflen = arg3 as usize; let flags = arg4 as i32; - - cage.send_syscall(fd, buf, count, flags) + + interface::cagetable_getref(cageid) + .send_syscall( virtual_fd, buf, buflen, flags) } LISTEN_SYSCALL => { @@ -1323,33 +946,18 @@ pub fn lind_syscall_api( } GETHOSTNAME_SYSCALL => { - let len = arg2 as usize; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing hostname - // Using PROT_WRITE because gethostname() writes hostname TO this user space buffer - let name = match check_and_convert_addr_ext(&cage, arg1, len, PROT_WRITE) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "gethostname", "invalid name address"), - }; - - // Perform gethostname operation through cage implementation - cage.gethostname_syscall(name, len as isize) - } + let name = (start_address + arg1) as *mut u8; + let len = arg2 as isize; + let ret = interface::cagetable_getref(cageid) + .gethostname_syscall(name, len); + ret + } GETIFADDRS_SYSCALL => { + let buf = (start_address + arg1) as *mut u8; let count = arg2 as usize; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing interface addresses - // Using PROT_WRITE because getifaddrs() writes interface data TO user space buffer - let buf = match check_and_convert_addr_ext(&cage, arg1, count, PROT_WRITE) { - Ok(addr) => addr as *mut u8, - Err(errno) => return syscall_error(errno, "getifaddrs", "invalid address"), - }; - - // Perform getifaddrs operation through cage implementation - cage.getifaddrs_syscall(buf, count) + interface::cagetable_getref(cageid) + .getifaddrs_syscall(buf, count) } KILL_SYSCALL => { @@ -1384,62 +992,25 @@ pub fn lind_syscall_api( } PIPE_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing pipe file descriptors - // Using PROT_WRITE because pipe() writes two fds TO this user space buffer - // Size is 8 bytes for two integers (file descriptors) - let pipe = match check_and_convert_addr_ext(&cage, arg1, 8, PROT_WRITE) { - Ok(addr) => match interface::get_pipearray(addr) { - Ok(pipe_array) => pipe_array, - Err(_) => return syscall_error(Errno::EFAULT, "pipe", "failed to get pipe array"), - }, - Err(errno) => return syscall_error(errno, "pipe", "invalid pipe address"), - }; - - cage.pipe_syscall(pipe) + let pipe = interface::get_pipearray(start_address + arg1).unwrap(); + + interface::cagetable_getref(cageid) + .pipe_syscall(pipe) } PIPE2_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing pipe file descriptors - // Using PROT_WRITE because pipe2() writes two fds TO this user space buffer - // Size is 8 bytes for two integers (file descriptors) - let pipe = match check_and_convert_addr_ext(&cage, arg1, 8, PROT_WRITE) { - Ok(addr) => match interface::get_pipearray(addr) { - Ok(pipe_array) => pipe_array, - Err(_) => return syscall_error(Errno::EFAULT, "pipe2", "failed to get pipe array"), - }, - Err(errno) => return syscall_error(errno, "pipe2", "invalid pipe address"), - }; + let pipe = interface::get_pipearray(start_address + arg1).unwrap(); let flag = arg2 as i32; - - cage.pipe2_syscall(pipe, flag) + + interface::cagetable_getref(cageid) + .pipe2_syscall(pipe, flag) } GETSOCKNAME_SYSCALL => { let fd = arg1 as i32; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing socket address - // Using PROT_WRITE because getsockname() writes address TO user space - let name_addr = match check_and_convert_addr_ext(&cage, arg2, 16, PROT_WRITE) { - Ok(addr) => addr, - Err(errno) => return syscall_error(errno, "getsockname", "invalid name address"), - }; - - // Validate buffer for writing address length - // Using PROT_WRITE because getsockname() writes length TO user space - let namelen_addr = match check_and_convert_addr_ext(&cage, arg3, 4, PROT_WRITE) { - Ok(addr) => addr, - Err(errno) => return syscall_error(errno, "getsockname", "invalid length address"), - }; - - // Initialize default socket address structure - let mut addr = interface::GenSockaddr::V4(interface::SockaddrV4::default()); - - // Check for null pointers + + let mut addr = interface::GenSockaddr::V4(interface::SockaddrV4::default()); //value doesn't matter + if interface::arg_nullity(arg2) || interface::arg_nullity(arg3) { return syscall_error( Errno::EINVAL, @@ -1447,12 +1018,12 @@ pub fn lind_syscall_api( "Either the address or the length were null", ); } - - let rv = cage.getsockname_syscall(fd, &mut Some(&mut addr)); - - // Copy out the address if operation was successful + + let rv = interface::cagetable_getref(cageid) + .getsockname_syscall(fd, &mut Some(&mut addr)); + if rv >= 0 { - interface::copy_out_sockaddr(name_addr, namelen_addr, addr); + interface::copy_out_sockaddr(start_address + arg2, start_address + arg3, addr); } rv } @@ -1461,59 +1032,31 @@ pub fn lind_syscall_api( let virtual_fd = arg1 as i32; let level = arg2 as i32; let optname = arg3 as i32; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing socket option value - // Using PROT_WRITE because getsockopt() writes option value TO user space - // Size is 4 bytes for an integer value - let optval_ptr = match check_and_convert_addr_ext(&cage, arg4, 4, PROT_WRITE) { - Ok(addr) => addr as *mut i32, - Err(errno) => return syscall_error(errno, "getsockopt", "invalid optval address"), - }; + + let optval_ptr = (start_address + arg4) as *mut i32; let optval = unsafe { &mut *optval_ptr }; - - cage.getsockopt_syscall(virtual_fd, level, optname, optval) + + interface::cagetable_getref(cageid) + .getsockopt_syscall(virtual_fd, level, optname, optval) } SOCKETPAIR_SYSCALL => { let domain = arg1 as i32; let _type = arg2 as i32; let protocol = arg3 as i32; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing socket pair file descriptors - // Using PROT_WRITE because socketpair() writes two fds TO this user space buffer - // Size is 8 bytes for two integers (file descriptors) - let virtual_socket_vector = match check_and_convert_addr_ext(&cage, arg4, 8, PROT_WRITE) { - Ok(addr) => match interface::get_sockpair(addr) { - Ok(sock_pair) => sock_pair, - Err(_) => return syscall_error(Errno::EFAULT, "socketpair", "failed to get socket pair array"), - }, - Err(errno) => return syscall_error(errno, "socketpair", "invalid socket vector address"), - }; - - cage.socketpair_syscall(domain, _type, protocol, virtual_socket_vector) + let virtual_socket_vector = interface::get_sockpair(start_address + arg4).unwrap(); + + interface::cagetable_getref(cageid) + .socketpair_syscall(domain, _type, protocol, virtual_socket_vector) } POLL_SYSCALL => { let nfds = arg2 as u64; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for reading and writing poll file descriptors - // Using PROT_READ | PROT_WRITE because: - // - READ: poll needs to read the fds and events to monitor - // - WRITE: poll needs to write back the returned events - // Size is nfds * 8 (size of pollfd struct) - let pollfds = match check_and_convert_addr_ext(&cage, arg1, (nfds * 8) as usize, PROT_READ | PROT_WRITE) { - Ok(addr) => match interface::get_pollstruct_slice(addr, nfds as usize) { - Ok(poll_array) => poll_array, - Err(_) => return syscall_error(Errno::EFAULT, "poll", "failed to get poll array"), - }, - Err(errno) => return syscall_error(errno, "poll", "invalid fds address"), - }; + let pollfds = interface::get_pollstruct_slice(start_address + arg1, nfds as usize).unwrap(); let timeout = arg3 as i32; - - cage.poll_syscall(pollfds, nfds, timeout) + + interface::cagetable_getref(cageid) + .poll_syscall(pollfds, nfds, timeout) } GETPID_SYSCALL => { @@ -1528,82 +1071,37 @@ pub fn lind_syscall_api( } FUTEX_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for futex operations - // Using PROT_READ | PROT_WRITE because: - // - READ: futex needs to read current value - // - WRITE: futex may modify the value depending on operation - let uaddr = match check_and_convert_addr_ext(&cage, arg1, 4, PROT_READ | PROT_WRITE) { - Ok(addr) => addr, - Err(errno) => return syscall_error(errno, "futex", "invalid uaddr address"), - }; - - // Convert remaining arguments + let uaddr = (start_address + arg1) as u64; let futex_op = arg2 as u32; let val = arg3 as u32; let timeout = arg4 as u32; let uaddr2 = arg5 as u32; let val3 = arg6 as u32; - - cage.futex_syscall(uaddr, futex_op, val, timeout, uaddr2, val3) + + interface::cagetable_getref(cageid) + .futex_syscall(uaddr, futex_op, val, timeout, uaddr2, val3) } NANOSLEEP_TIME64_SYSCALL => { let clockid = arg1 as u32; let flags = arg2 as i32; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for reading requested sleep time - // Using PROT_READ because we need to read the requested time FROM user space - // Size is 16 bytes for timespec64 structure - let req = match check_and_convert_addr_ext(&cage, arg3, 16, PROT_READ) { - Ok(addr) => addr as usize, - Err(errno) => return syscall_error(errno, "nanosleep", "invalid req address"), - }; - - // Validate buffer for writing remaining time - // Using PROT_WRITE because nanosleep writes remaining time TO user space - // Size is 16 bytes for timespec64 structure - let rem = match check_and_convert_addr_ext(&cage, arg4, 16, PROT_WRITE) { - Ok(addr) => addr as usize, - Err(errno) => return syscall_error(errno, "nanosleep", "invalid rem address"), - }; + let req = (start_address + arg3) as usize; + let rem = (start_address + arg4) as usize; - cage.nanosleep_time64_syscall(clockid, flags, req, rem) + interface::cagetable_getref(cageid) + .nanosleep_time64_syscall(clockid, flags, req, rem) } WAIT_SYSCALL => { - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing process status - // Using PROT_WRITE because wait() writes status information TO user space - // Size is 4 bytes for status integer - let status = match check_and_convert_addr_ext(&cage, arg1, 4, PROT_WRITE) { - Ok(addr) => match interface::get_i32_ref(addr) { - Ok(status_ref) => status_ref, - Err(_) => return syscall_error(Errno::EFAULT, "wait", "failed to get status reference"), - }, - Err(errno) => return syscall_error(errno, "wait", "invalid status address"), - }; - - cage.wait_syscall(status) + let mut status = interface::get_i32_ref(start_address + arg1).unwrap(); + + interface::cagetable_getref(cageid) + .wait_syscall(&mut status) } WAITPID_SYSCALL => { let pid = arg1 as i32; - let cage = interface::cagetable_getref(cageid); - - // Validate buffer for writing process status - // Using PROT_WRITE because waitpid() writes status information TO user space - // Size is 4 bytes for status integer - let status = match check_and_convert_addr_ext(&cage, arg2, 4, PROT_WRITE) { - Ok(addr) => match interface::get_i32_ref(addr) { - Ok(status_ref) => status_ref, - Err(_) => return syscall_error(Errno::EFAULT, "waitpid", "failed to get status reference"), - }, - Err(errno) => return syscall_error(errno, "waitpid", "invalid status address"), - }; + let mut status = interface::get_i32_ref(start_address + arg2).unwrap(); let options = arg3 as i32; cage.waitpid_syscall(pid, status, options)