diff --git a/crate/memory/src/memory_set/mod.rs b/crate/memory/src/memory_set/mod.rs index 4f0f9a5..decd828 100644 --- a/crate/memory/src/memory_set/mod.rs +++ b/crate/memory/src/memory_set/mod.rs @@ -205,29 +205,55 @@ impl MemorySet { } } /// Check the pointer is within the readable memory - pub fn check_read_ptr(&self, ptr: *const S) -> VMResult<()> { - self.check_read_array(ptr, 1) + pub unsafe fn check_read_ptr(&self, ptr: *const S) -> VMResult<&'static S> { + self.check_read_array(ptr, 1).map(|s| &s[0]) } /// Check the pointer is within the writable memory - pub fn check_write_ptr(&self, ptr: *mut S) -> VMResult<()> { - self.check_write_array(ptr, 1) + pub unsafe fn check_write_ptr(&self, ptr: *mut S) -> VMResult<&'static mut S> { + self.check_write_array(ptr, 1).map(|s| &mut s[0]) } /// Check the array is within the readable memory - pub fn check_read_array(&self, ptr: *const S, count: usize) -> VMResult<()> { + pub unsafe fn check_read_array( + &self, + ptr: *const S, + count: usize, + ) -> VMResult<&'static [S]> { self.areas .iter() .find(|area| area.check_read_array(ptr, count)) - .map(|_| ()) + .map(|_| core::slice::from_raw_parts(ptr, count)) .ok_or(VMError::InvalidPtr) } /// Check the array is within the writable memory - pub fn check_write_array(&self, ptr: *mut S, count: usize) -> VMResult<()> { + pub unsafe fn check_write_array( + &self, + ptr: *mut S, + count: usize, + ) -> VMResult<&'static mut [S]> { self.areas .iter() .find(|area| area.check_write_array(ptr, count)) - .map(|_| ()) + .map(|_| core::slice::from_raw_parts_mut(ptr, count)) .ok_or(VMError::InvalidPtr) } + /// Check the null-end C string pointer array + /// Used for getting argv & envp + pub unsafe fn check_and_clone_cstr_array( + &self, + mut argv: *const *const u8, + ) -> VMResult> { + let mut args = Vec::new(); + loop { + let cstr = *self.check_read_ptr(argv)?; + if cstr.is_null() { + break; + } + let arg = self.check_and_clone_cstr(cstr)?; + args.push(arg); + argv = argv.add(1); + } + Ok(args) + } /// Check the null-end C string is within the readable memory, and is valid. /// If so, clone it to a String. /// diff --git a/kernel/src/syscall/custom.rs b/kernel/src/syscall/custom.rs index e21fa12..d774b91 100644 --- a/kernel/src/syscall/custom.rs +++ b/kernel/src/syscall/custom.rs @@ -43,10 +43,8 @@ pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult { /// mapped to a list of virtual addresses. pub fn sys_get_paddr(vaddrs: *const u64, paddrs: *mut u64, count: usize) -> SysResult { let mut proc = process(); - proc.vm.check_read_array(vaddrs, count)?; - proc.vm.check_write_array(paddrs, count)?; - let vaddrs = unsafe { slice::from_raw_parts(vaddrs, count) }; - let paddrs = unsafe { slice::from_raw_parts_mut(paddrs, count) }; + let vaddrs = unsafe { proc.vm.check_read_array(vaddrs, count)? }; + let paddrs = unsafe { proc.vm.check_write_array(paddrs, count)? }; for i in 0..count { let paddr = proc.vm.translate(vaddrs[i] as usize).unwrap_or(0); paddrs[i] = paddr as u64; diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index e80cd39..1c005d9 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -21,8 +21,7 @@ pub fn sys_read(fd: usize, base: *mut u8, len: usize) -> SysResult { // we trust pid 0 process info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len); } - proc.vm.check_write_array(base, len)?; - let slice = unsafe { slice::from_raw_parts_mut(base, len) }; + let slice = unsafe { proc.vm.check_write_array(base, len)? }; let file_like = proc.get_file_like(fd)?; let len = file_like.read(slice)?; Ok(len) @@ -34,8 +33,7 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult { // we trust pid 0 process info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len); } - proc.vm.check_read_array(base, len)?; - let slice = unsafe { slice::from_raw_parts(base, len) }; + let slice = unsafe { proc.vm.check_read_array(base, len)? }; let file_like = proc.get_file_like(fd)?; let len = file_like.write(slice)?; Ok(len) @@ -47,9 +45,7 @@ pub fn sys_pread(fd: usize, base: *mut u8, len: usize, offset: usize) -> SysResu fd, base, len, offset ); let mut proc = process(); - proc.vm.check_write_array(base, len)?; - - let slice = unsafe { slice::from_raw_parts_mut(base, len) }; + let slice = unsafe { proc.vm.check_write_array(base, len)? }; let len = proc.get_file(fd)?.read_at(offset, slice)?; Ok(len) } @@ -60,9 +56,7 @@ pub fn sys_pwrite(fd: usize, base: *const u8, len: usize, offset: usize) -> SysR fd, base, len, offset ); let mut proc = process(); - proc.vm.check_read_array(base, len)?; - - let slice = unsafe { slice::from_raw_parts(base, len) }; + let slice = unsafe { proc.vm.check_read_array(base, len)? }; let len = proc.get_file(fd)?.write_at(offset, slice)?; Ok(len) } @@ -72,8 +66,8 @@ pub fn sys_ppoll(ufds: *mut PollFd, nfds: usize, timeout: *const TimeSpec) -> Sy let timeout_msecs = if timeout.is_null() { 1 << 31 // infinity } else { - proc.vm.check_read_ptr(timeout)?; - unsafe { (*timeout).to_msec() } + let timeout = unsafe { proc.vm.check_read_ptr(timeout)? }; + timeout.to_msec() }; drop(proc); @@ -89,9 +83,8 @@ pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResu ufds, nfds, timeout_msecs ); } - proc.vm.check_write_array(ufds, nfds)?; - let polls = unsafe { slice::from_raw_parts_mut(ufds, nfds) }; + let polls = unsafe { proc.vm.check_write_array(ufds, nfds)? }; for poll in polls.iter() { if proc.files.get(&(poll.fd as usize)).is_none() { return Err(SysError::EINVAL); @@ -156,9 +149,9 @@ pub fn sys_select( let mut read_fds = FdSet::new(&proc.vm, read, nfds)?; let mut write_fds = FdSet::new(&proc.vm, write, nfds)?; let mut err_fds = FdSet::new(&proc.vm, err, nfds)?; - let timeout_msecs = if timeout as usize != 0 { - proc.vm.check_read_ptr(timeout)?; - unsafe { *timeout }.to_msec() + let timeout_msecs = if !timeout.is_null() { + let timeout = unsafe { proc.vm.check_read_ptr(timeout)? }; + timeout.to_msec() } else { // infinity 1 << 31 @@ -214,7 +207,7 @@ pub fn sys_readv(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResul fd, iov_ptr, iov_count ); let mut proc = process(); - let mut iovs = IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, true)?; + let mut iovs = unsafe { IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, true)? }; // read all data to a buf let file_like = proc.get_file_like(fd)?; @@ -234,7 +227,7 @@ pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResu fd, iov_ptr, iov_count ); } - let iovs = IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, false)?; + let iovs = unsafe { IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, false)? }; let buf = iovs.read_all_to_vec(); let len = buf.len(); @@ -315,12 +308,12 @@ pub fn sys_getcwd(buf: *mut u8, len: usize) -> SysResult { // we trust pid 0 process info!("getcwd: buf: {:?}, len: {:#x}", buf, len); } - proc.vm.check_write_array(buf, len)?; + let buf = unsafe { proc.vm.check_write_array(buf, len)? }; if proc.cwd.len() + 1 > len { return Err(SysError::ERANGE); } - unsafe { util::write_cstr(buf, &proc.cwd) } - Ok(buf as usize) + unsafe { util::write_cstr(buf.as_mut_ptr(), &proc.cwd) } + Ok(buf.as_ptr() as usize) } pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult { @@ -330,19 +323,17 @@ pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult { pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult { info!("fstat: fd: {}, stat_ptr: {:?}", fd, stat_ptr); let mut proc = process(); - proc.vm.check_write_ptr(stat_ptr)?; + let stat_ref = unsafe { proc.vm.check_write_ptr(stat_ptr)? }; let file = proc.get_file(fd)?; let stat = Stat::from(file.metadata()?); - unsafe { - stat_ptr.write(stat); - } + *stat_ref = stat; Ok(0) } pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: usize) -> SysResult { let proc = process(); let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; - proc.vm.check_write_ptr(stat_ptr)?; + let stat_ref = unsafe { proc.vm.check_write_ptr(stat_ptr)? }; let flags = AtFlags::from_bits_truncate(flags); info!( "fstatat: dirfd: {}, path: {:?}, stat_ptr: {:?}, flags: {:?}", @@ -351,9 +342,7 @@ pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: us let inode = proc.lookup_inode_at(dirfd, &path, !flags.contains(AtFlags::SYMLINK_NOFOLLOW))?; let stat = Stat::from(inode.metadata()?); - unsafe { - stat_ptr.write(stat); - } + *stat_ref = stat; Ok(0) } @@ -368,14 +357,13 @@ pub fn sys_readlink(path: *const u8, base: *mut u8, len: usize) -> SysResult { pub fn sys_readlinkat(dirfd: usize, path: *const u8, base: *mut u8, len: usize) -> SysResult { let proc = process(); let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; - proc.vm.check_write_array(base, len)?; + let slice = unsafe { proc.vm.check_write_array(base, len)? }; info!("readlink: path: {:?}, base: {:?}, len: {}", path, base, len); let inode = proc.lookup_inode_at(dirfd, &path, false)?; if inode.metadata()?.type_ == FileType::SymLink { // TODO: recursive link resolution and loop detection - let mut slice = unsafe { slice::from_raw_parts_mut(base, len) }; - let len = inode.read_at(0, &mut slice)?; + let len = inode.read_at(0, slice)?; Ok(len) } else { Err(SysError::EINVAL) @@ -429,13 +417,13 @@ pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> Sy fd, buf, buf_size ); let mut proc = process(); - proc.vm.check_write_array(buf as *mut u8, buf_size)?; + let buf = unsafe { proc.vm.check_write_array(buf as *mut u8, buf_size)? }; let file = proc.get_file(fd)?; let info = file.metadata()?; if info.type_ != FileType::Dir { return Err(SysError::ENOTDIR); } - let mut writer = unsafe { DirentBufWriter::new(buf, buf_size) }; + let mut writer = DirentBufWriter::new(buf); loop { let name = match file.read_entry() { Err(FsError::EntryNotFound) => break, @@ -631,7 +619,7 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult { info!("pipe: fds: {:?}", fds); let mut proc = process(); - proc.vm.check_write_array(fds, 2)?; + let fds = unsafe { proc.vm.check_write_array(fds, 2)? }; let (read, write) = Pipe::create_pair(); let read_fd = proc.add_file( @@ -656,10 +644,8 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult { )), ); - unsafe { - fds.write(read_fd as u32); - fds.add(1).write(write_fd as u32); - } + fds[0] = read_fd as u32; + fds[1] = write_fd as u32; info!("pipe: created rfd: {} wfd: {}", read_fd, write_fd); @@ -690,8 +676,7 @@ pub fn sys_sendfile( let mut read_offset = if !offset_ptr.is_null() { unsafe { - (*proc_cell.get()).vm.check_read_ptr(offset_ptr)?; - offset_ptr.read() + *(*proc_cell.get()).vm.check_read_ptr(offset_ptr)? } } else { in_file.seek(SeekFrom::Current(0))? as usize @@ -880,18 +865,20 @@ pub struct LinuxDirent64 { name: [u8; 0], } -struct DirentBufWriter { +struct DirentBufWriter<'a> { + buf: &'a mut [u8], ptr: *mut LinuxDirent64, rest_size: usize, written_size: usize, } -impl DirentBufWriter { - unsafe fn new(buf: *mut LinuxDirent64, size: usize) -> Self { +impl<'a> DirentBufWriter<'a> { + fn new(buf: &'a mut [u8]) -> Self { DirentBufWriter { - ptr: buf, - rest_size: size, + ptr: buf.as_mut_ptr() as *mut LinuxDirent64, + rest_size: buf.len(), written_size: 0, + buf, } } fn try_write(&mut self, inode: u64, type_: u8, name: &str) -> bool { @@ -1239,28 +1226,28 @@ pub struct IoVec { pub struct IoVecs(Vec<&'static mut [u8]>); impl IoVecs { - pub fn check_and_new( + pub unsafe fn check_and_new( iov_ptr: *const IoVec, iov_count: usize, vm: &MemorySet, readv: bool, ) -> Result { - vm.check_read_array(iov_ptr, iov_count)?; - let iovs = unsafe { slice::from_raw_parts(iov_ptr, iov_count) }.to_vec(); + let iovs = vm.check_read_array(iov_ptr, iov_count)?.to_vec(); // check all bufs in iov for iov in iovs.iter() { - if iov.len > 0 { - // skip empty iov - if readv { - vm.check_write_array(iov.base, iov.len)?; - } else { - vm.check_read_array(iov.base, iov.len)?; - } + // skip empty iov + if iov.len == 0 { + continue; + } + if readv { + vm.check_write_array(iov.base, iov.len)?; + } else { + vm.check_read_array(iov.base, iov.len)?; } } let slices = iovs .iter() - .map(|iov| unsafe { slice::from_raw_parts_mut(iov.base, iov.len) }) + .map(|iov| slice::from_raw_parts_mut(iov.base, iov.len)) .collect(); Ok(IoVecs(slices)) } @@ -1342,11 +1329,10 @@ impl FdSet { }) } else { let len = (nfds + FD_PER_ITEM - 1) / FD_PER_ITEM; - vm.check_write_array(addr, len)?; if len > MAX_FDSET_SIZE { return Err(SysError::EINVAL); } - let slice = unsafe { slice::from_raw_parts_mut(addr, len) }; + let slice = unsafe { vm.check_write_array(addr, len)? }; let bitset: &'static mut BitSlice = slice.into(); // save the fdset, and clear it diff --git a/kernel/src/syscall/misc.rs b/kernel/src/syscall/misc.rs index a5367e1..79bda93 100644 --- a/kernel/src/syscall/misc.rs +++ b/kernel/src/syscall/misc.rs @@ -18,16 +18,16 @@ pub fn sys_arch_prctl(code: i32, addr: usize, tf: &mut TrapFrame) -> SysResult { } pub fn sys_uname(buf: *mut u8) -> SysResult { - info!("sched_uname: buf: {:?}", buf); + info!("uname: buf: {:?}", buf); let offset = 65; let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"]; let proc = process(); - proc.vm.check_write_array(buf, strings.len() * offset)?; + let buf = unsafe { proc.vm.check_write_array(buf, strings.len() * offset)? }; for i in 0..strings.len() { unsafe { - util::write_cstr(buf.add(i * offset), &strings[i]); + util::write_cstr(&mut buf[i * offset], &strings[i]); } } Ok(0) @@ -39,22 +39,20 @@ pub fn sys_sched_getaffinity(pid: usize, size: usize, mask: *mut u32) -> SysResu pid, size, mask ); let proc = process(); - proc.vm.check_write_array(mask, size / size_of::())?; + let mask = unsafe { proc.vm.check_write_array(mask, size / size_of::())? }; // we only have 4 cpu at most. // so just set it. - unsafe { - *mask = 0b1111; - } + mask[0] = 0b1111; Ok(0) } pub fn sys_sysinfo(sys_info: *mut SysInfo) -> SysResult { let proc = process(); - proc.vm.check_write_ptr(sys_info)?; + let sys_info = unsafe { proc.vm.check_write_ptr(sys_info)? }; let sysinfo = SysInfo::default(); - unsafe { *sys_info = sysinfo }; + *sys_info = sysinfo; Ok(0) } @@ -74,13 +72,11 @@ pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> S if uaddr % size_of::() != 0 { return Err(SysError::EINVAL); } - process().vm.check_write_ptr(uaddr as *mut AtomicI32)?; - let atomic = unsafe { &mut *(uaddr as *mut AtomicI32) }; + let atomic = unsafe { process().vm.check_write_ptr(uaddr as *mut AtomicI32)? }; let _timeout = if timeout.is_null() { None } else { - process().vm.check_read_ptr(timeout)?; - Some(unsafe { *timeout }) + Some(unsafe { *process().vm.check_read_ptr(timeout)? }) }; const OP_WAIT: u32 = 0; @@ -156,38 +152,32 @@ pub fn sys_prlimit64( match resource { RLIMIT_STACK => { if !old_limit.is_null() { - proc.vm.check_write_ptr(old_limit)?; - unsafe { - *old_limit = RLimit { - cur: USER_STACK_SIZE as u64, - max: USER_STACK_SIZE as u64, - }; - } + let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? }; + *old_limit = RLimit { + cur: USER_STACK_SIZE as u64, + max: USER_STACK_SIZE as u64, + }; } Ok(0) } RLIMIT_NOFILE => { if !old_limit.is_null() { - proc.vm.check_write_ptr(old_limit)?; - unsafe { - *old_limit = RLimit { - cur: 1024, - max: 1024, - }; - } + let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? }; + *old_limit = RLimit { + cur: 1024, + max: 1024, + }; } Ok(0) } RLIMIT_RSS | RLIMIT_AS => { if !old_limit.is_null() { - proc.vm.check_write_ptr(old_limit)?; - unsafe { - // 1GB - *old_limit = RLimit { - cur: 1024 * 1024 * 1024, - max: 1024 * 1024 * 1024, - }; - } + let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? }; + // 1GB + *old_limit = RLimit { + cur: 1024 * 1024 * 1024, + max: 1024 * 1024 * 1024, + }; } Ok(0) } @@ -206,8 +196,7 @@ pub fn sys_getrandom( buf: *mut u8, len: usize, flag: u32) -> SysResult { //info!("getrandom: buf: {:?}, len: {:?}, falg {:?}", buf, len,flag); let mut proc = process(); - proc.vm.check_write_array(buf, len)?; - let slice = unsafe { slice::from_raw_parts_mut(buf, len) }; + let slice = unsafe { proc.vm.check_write_array(buf, len)? }; let mut i=0; for elm in slice { unsafe{ *elm=i+ crate::trap::TICK as u8;} diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 34ebb14..af28065 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -55,8 +55,7 @@ pub fn sys_setsockopt( fd, level, optname ); let mut proc = process(); - proc.vm.check_read_array(optval, optlen)?; - let data = unsafe { slice::from_raw_parts(optval, optlen) }; + let data = unsafe { proc.vm.check_read_array(optval, optlen)? }; let socket = proc.get_socket(fd)?; socket.setsockopt(level, optname, data) } @@ -73,23 +72,19 @@ pub fn sys_getsockopt( fd, level, optname, optval, optlen ); let proc = process(); - proc.vm.check_write_ptr(optlen)?; + let optlen = unsafe { proc.vm.check_write_ptr(optlen)? }; match level { SOL_SOCKET => match optname { SO_SNDBUF => { - proc.vm.check_write_array(optval, 4)?; - unsafe { - *(optval as *mut u32) = crate::net::TCP_SENDBUF as u32; - *optlen = 4; - } + let optval = unsafe { proc.vm.check_write_ptr(optval as *mut u32)? }; + *optval = crate::net::TCP_SENDBUF as u32; + *optlen = 4; Ok(0) } SO_RCVBUF => { - proc.vm.check_write_array(optval, 4)?; - unsafe { - *(optval as *mut u32) = crate::net::TCP_RECVBUF as u32; - *optlen = 4; - } + let optval = unsafe { proc.vm.check_write_ptr(optval as *mut u32)? }; + *optval = crate::net::TCP_RECVBUF as u32; + *optlen = 4; Ok(0) } _ => Err(SysError::ENOPROTOOPT), @@ -129,9 +124,8 @@ pub fn sys_sendto( ); let mut proc = process(); - proc.vm.check_read_array(base, len)?; - let slice = unsafe { slice::from_raw_parts(base, len) }; + let slice = unsafe { proc.vm.check_read_array(base, len)? }; let endpoint = if addr.is_null() { None } else { @@ -157,10 +151,9 @@ pub fn sys_recvfrom( ); let mut proc = process(); - proc.vm.check_write_array(base, len)?; + let mut slice = unsafe { proc.vm.check_write_array(base, len)? }; let socket = proc.get_socket(fd)?; - let mut slice = unsafe { slice::from_raw_parts_mut(base, len) }; let (result, endpoint) = socket.read(&mut slice); if result.is_ok() && !addr.is_null() { @@ -176,9 +169,8 @@ pub fn sys_recvfrom( pub fn sys_recvmsg(fd: usize, msg: *mut MsgHdr, flags: usize) -> SysResult { info!("recvmsg: fd: {}, msg: {:?}, flags: {}", fd, msg, flags); let mut proc = process(); - proc.vm.check_read_ptr(msg)?; - let hdr = unsafe { &mut *msg }; - let mut iovs = IoVecs::check_and_new(hdr.msg_iov, hdr.msg_iovlen, &proc.vm, true)?; + let hdr = unsafe { proc.vm.check_write_ptr(msg)? }; + let mut iovs = unsafe { IoVecs::check_and_new(hdr.msg_iov, hdr.msg_iovlen, &proc.vm, true)? }; let mut buf = iovs.new_buf(true); let socket = proc.get_socket(fd)?; @@ -406,16 +398,16 @@ fn sockaddr_to_endpoint( if len < size_of::() { return Err(SysError::EINVAL); } - proc.vm.check_read_array(addr as *const u8, len)?; + let addr = unsafe { proc.vm.check_read_ptr(addr)? }; unsafe { - match AddressFamily::from((*addr).family) { + match AddressFamily::from(addr.family) { AddressFamily::Internet => { if len < size_of::() { return Err(SysError::EINVAL); } - let port = u16::from_be((*addr).addr_in.sin_port); + let port = u16::from_be(addr.addr_in.sin_port); let addr = IpAddress::from(Ipv4Address::from_bytes( - &u32::from_be((*addr).addr_in.sin_addr).to_be_bytes()[..], + &u32::from_be(addr.addr_in.sin_addr).to_be_bytes()[..], )); Ok(Endpoint::Ip((addr, port).into())) } @@ -425,7 +417,7 @@ fn sockaddr_to_endpoint( return Err(SysError::EINVAL); } Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new( - (*addr).addr_ll.sll_ifindex as usize, + addr.addr_ll.sll_ifindex as usize, ))) } AddressFamily::Netlink => { @@ -433,8 +425,8 @@ fn sockaddr_to_endpoint( return Err(SysError::EINVAL); } Ok(Endpoint::Netlink(NetlinkEndpoint::new( - (*addr).addr_nl.nl_pid, - (*addr).addr_nl.nl_groups, + addr.addr_nl.nl_pid, + addr.addr_nl.nl_groups, ))) } _ => Err(SysError::EINVAL), @@ -456,7 +448,7 @@ impl SockAddr { return Ok(0); } - proc.vm.check_write_ptr(addr_len)?; + let addr_len = unsafe { proc.vm.check_write_ptr(addr_len)? }; let max_addr_len = *addr_len as usize; let full_len = match AddressFamily::from(self.family) { AddressFamily::Internet => size_of::(), @@ -468,12 +460,11 @@ impl SockAddr { let written_len = min(max_addr_len, full_len); if written_len > 0 { - proc.vm.check_write_array(addr as *mut u8, written_len)?; + let target = unsafe { proc.vm.check_write_array(addr as *mut u8, written_len)? }; let source = slice::from_raw_parts(&self as *const SockAddr as *const u8, written_len); - let target = slice::from_raw_parts_mut(addr as *mut u8, written_len); target.copy_from_slice(source); } - addr_len.write(full_len as u32); + *addr_len = full_len as u32; return Ok(0); } } diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index c58f8b8..dd04326 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -43,19 +43,14 @@ pub fn sys_clone( ); //return Err(SysError::ENOSYS); } - { - let proc = process(); - proc.vm.check_write_ptr(parent_tid)?; - proc.vm.check_write_ptr(child_tid)?; - } + let parent_tid_ref = unsafe { process().vm.check_write_ptr(parent_tid)? }; + let child_tid_ref = unsafe { process().vm.check_write_ptr(child_tid)? }; let new_thread = current_thread().clone(tf, newsp, newtls, child_tid as usize); // FIXME: parent pid let tid = processor().manager().add(new_thread); info!("clone: {} -> {}", thread::current().id(), tid); - unsafe { - parent_tid.write(tid as u32); - child_tid.write(tid as u32); - } + *parent_tid_ref = tid as u32; + *child_tid_ref = tid as u32; Ok(tid) } @@ -63,9 +58,11 @@ pub fn sys_clone( /// Return the PID. Store exit code to `wstatus` if it's not null. pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult { //info!("wait4: pid: {}, code: {:?}", pid, wstatus); - if !wstatus.is_null() { - process().vm.check_write_ptr(wstatus)?; - } + let wstatus = if !wstatus.is_null() { + Some(unsafe { process().vm.check_write_ptr(wstatus)? }) + } else { + None + }; #[derive(Debug)] enum WaitFor { AnyChild, @@ -90,10 +87,8 @@ pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult { // if found, return if let Some((pid, exit_code)) = find { proc.child_exit_code.remove(&pid); - if !wstatus.is_null() { - unsafe { - wstatus.write(exit_code as i32); - } + if let Some(wstatus) = wstatus { + *wstatus = exit_code as i32; } return Ok(pid); } @@ -124,69 +119,49 @@ pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult { } } +/// Replaces the current ** process ** with a new process image +/// +/// `argv` is an array of argument strings passed to the new program. +/// `envp` is an array of strings, conventionally of the form `key=value`, +/// which are passed as environment to the new program. +/// +/// NOTICE: `argv` & `envp` can not be NULL (different from Linux) +/// +/// NOTICE: for multi-thread programs +/// A call to any exec function from a process with more than one thread +/// shall result in all threads being terminated and the new executable image +/// being loaded and executed. pub fn sys_exec( - name: *const u8, + path: *const u8, argv: *const *const u8, envp: *const *const u8, tf: &mut TrapFrame, ) -> SysResult { - info!("exec:BEG: name: {:?}, argv: {:?}, envp: {:?}", name, argv, envp); + info!( + "exec:BEG: path: {:?}, argv: {:?}, envp: {:?}", + path, argv, envp + ); let proc = process(); - let exec_name = if name.is_null() { - String::from("") - } else { - unsafe { proc.vm.check_and_clone_cstr(name)? } - }; - - if argv.is_null() { - info!("exec:END:ERR1: exec_name: {:?}, name: {:?}, argv: is NULL", exec_name, name); - return Err(SysError::EINVAL); - } - // Check and copy args to kernel - let mut args = Vec::new(); - unsafe { - let mut current_argv = argv as *const *const u8; - proc.vm.check_read_ptr(current_argv)?; - while !(*current_argv).is_null() { - let arg = proc.vm.check_and_clone_cstr(*current_argv)?; - info!(" arg: {}",arg); - args.push(arg); - current_argv = current_argv.add(1); - } - } - // Check and copy envs to kernel - let mut envs = Vec::new(); - unsafe { - let mut current_env = envp as *const *const u8; - if !current_env.is_null() { - proc.vm.check_read_ptr(current_env)?; - while !(*current_env).is_null() { - let env = proc.vm.check_and_clone_cstr(*current_env)?; - info!(" env: {}",env); - envs.push(env); - current_env = current_env.add(1); - } - } - } + let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; + let args = unsafe { proc.vm.check_and_clone_cstr_array(argv)? }; + let envs = unsafe { proc.vm.check_and_clone_cstr_array(envp)? }; if args.is_empty() { - info!("exec:END:ERR2: exec_name: {:?}, name: {:?}, args is empty", exec_name, name); + error!("exec: args is null"); return Err(SysError::EINVAL); } info!( - "exec:STEP2: exec_name: {:?}, name{:?}, args: {:?}, envp: {:?}", - exec_name, name, args, envs + "exec:STEP2: path: {:?}, args: {:?}, envs: {:?}", + path, args, envs ); // Read program file - //let path = args[0].as_str(); - let exec_path = exec_name.as_str(); - let inode = proc.lookup_inode(exec_path)?; + let inode = proc.lookup_inode(&path)?; let buf = inode.read_as_vec()?; // Make new Thread - let mut thread = Thread::new_user(buf.as_slice(), exec_path, args, envs); + let mut thread = Thread::new_user(buf.as_slice(), &path, args, envs); thread.proc.lock().clone_for_exec(&proc); // Activate new page table @@ -201,10 +176,7 @@ pub fn sys_exec( ::core::mem::swap(&mut current_thread().kstack, &mut thread.kstack); ::core::mem::swap(current_thread(), &mut *thread); - info!( - "exec:END: exec_name: {:?}", - exec_name - ); + info!("exec:END: path: {:?}", path); Ok(0) } @@ -337,8 +309,7 @@ pub fn sys_exit_group(exit_code: usize) -> ! { } pub fn sys_nanosleep(req: *const TimeSpec) -> SysResult { - process().vm.check_read_ptr(req)?; - let time = unsafe { req.read() }; + let time = unsafe { *process().vm.check_read_ptr(req)? }; info!("nanosleep: time: {:#?}", time); // TODO: handle spurious wakeup thread::sleep(time.to_duration()); diff --git a/kernel/src/syscall/time.rs b/kernel/src/syscall/time.rs index dd2834c..0fc3f39 100644 --- a/kernel/src/syscall/time.rs +++ b/kernel/src/syscall/time.rs @@ -83,12 +83,10 @@ pub fn sys_gettimeofday(tv: *mut TimeVal, tz: *const u8) -> SysResult { } let proc = process(); - proc.vm.check_write_ptr(tv)?; + let tv = unsafe { proc.vm.check_write_ptr(tv)? }; let timeval = TimeVal::get_epoch(); - unsafe { - *tv = timeval; - } + *tv = timeval; Ok(0) } @@ -96,12 +94,10 @@ pub fn sys_clock_gettime(clock: usize, ts: *mut TimeSpec) -> SysResult { info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts); let proc = process(); - proc.vm.check_write_ptr(ts)?; + let ts = unsafe { proc.vm.check_write_ptr(ts)? }; let timespec = TimeSpec::get_epoch(); - unsafe { - *ts = timespec; - } + *ts = timespec; Ok(0) } @@ -109,10 +105,8 @@ pub fn sys_time(time: *mut u64) -> SysResult { let sec = get_epoch_usec() / USEC_PER_SEC; if time as usize != 0 { let proc = process(); - proc.vm.check_write_ptr(time)?; - unsafe { - time.write(sec as u64); - } + let time = unsafe { proc.vm.check_write_ptr(time)? }; + *time = sec as u64; } Ok(sec as usize) } @@ -127,7 +121,7 @@ pub struct RUsage { pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult { info!("getrusage: who: {}, rusage: {:?}", who, rusage); let proc = process(); - proc.vm.check_write_ptr(rusage)?; + let rusage = unsafe { proc.vm.check_write_ptr(rusage)? }; let tick_base = *TICK_BASE; let tick = unsafe { crate::trap::TICK as u64 }; @@ -143,7 +137,7 @@ pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult { usec: (usec % USEC_PER_SEC) as usize, }, }; - unsafe { *rusage = new_rusage }; + *rusage = new_rusage; Ok(0) } @@ -159,7 +153,7 @@ pub struct Tms { pub fn sys_times(buf: *mut Tms) -> SysResult { info!("times: buf: {:?}", buf); let proc = process(); - proc.vm.check_write_ptr(buf)?; + let buf = unsafe { proc.vm.check_write_ptr(buf)? }; let tick_base = *TICK_BASE; let tick = unsafe { crate::trap::TICK as u64 }; @@ -171,6 +165,6 @@ pub fn sys_times(buf: *mut Tms) -> SysResult { tms_cstime: 0, }; - unsafe { *buf = new_buf }; + *buf = new_buf; Ok(tick as usize) }