diff --git a/kernel/src/memory.rs b/kernel/src/memory.rs index 5b69ab8..15c290c 100644 --- a/kernel/src/memory.rs +++ b/kernel/src/memory.rs @@ -132,12 +132,8 @@ impl Drop for KernelStack { pub fn handle_page_fault(addr: usize) -> bool { debug!("page fault @ {:#x}", addr); - // FIXME: fix racing caused by force_unlock - unsafe { - let thread = current_thread(); - thread.proc.force_unlock(); - thread.proc.lock().vm.handle_page_fault(addr) - } + let thread = unsafe { current_thread() }; + thread.vm.lock().handle_page_fault(addr) } pub fn init_heap() { diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index d5942ba..2afab29 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -23,13 +23,14 @@ use super::abi::{self, ProcInitInfo}; use core::mem::uninitialized; use rcore_fs::vfs::INode; -// TODO: avoid pub pub struct Thread { - pub context: Context, - pub kstack: KernelStack, + context: Context, + kstack: KernelStack, /// Kernel performs futex wake when thread exits. /// Ref: [http://man7.org/linux/man-pages/man2/set_tid_address.2.html] pub clear_child_tid: usize, + // This is same as `proc.vm` + pub vm: Arc>, pub proc: Arc>, } @@ -57,7 +58,7 @@ impl fmt::Display for Pid { pub struct Process { // resources - pub vm: MemorySet, + pub vm: Arc>, pub files: BTreeMap, pub cwd: String, pub exec_path: String, @@ -108,11 +109,14 @@ impl Thread { /// Make a new kernel thread starting from `entry` with `arg` pub fn new_kernel(entry: extern "C" fn(usize) -> !, arg: usize) -> Box { let vm = MemorySet::new(); + let vm_token = vm.token(); + let vm = Arc::new(Mutex::new(vm)); let kstack = KernelStack::new(); Box::new(Thread { - context: unsafe { Context::new_kernel_thread(entry, arg, kstack.top(), vm.token()) }, + context: unsafe { Context::new_kernel_thread(entry, arg, kstack.top(), vm_token) }, kstack, clear_child_tid: 0, + vm: vm.clone(), // TODO: kernel thread should not have a process proc: Process { vm, @@ -243,6 +247,8 @@ impl Thread { ) -> Box { let (vm, entry_addr, ustack_top) = Self::new_user_vm(inode, exec_path, args, envs).unwrap(); + let vm_token = vm.token(); + let vm = Arc::new(Mutex::new(vm)); let kstack = KernelStack::new(); let mut files = BTreeMap::new(); @@ -285,10 +291,11 @@ impl Thread { Box::new(Thread { context: unsafe { - Context::new_user_thread(entry_addr, ustack_top, kstack.top(), vm.token()) + Context::new_user_thread(entry_addr, ustack_top, kstack.top(), vm_token) }, kstack, clear_child_tid: 0, + vm: vm.clone(), proc: Process { vm, files, @@ -308,12 +315,15 @@ impl Thread { /// Fork a new process from current one pub fn fork(&self, tf: &TrapFrame) -> Box { - let mut proc = self.proc.lock(); let kstack = KernelStack::new(); - let vm = proc.vm.clone(); - let context = unsafe { Context::new_fork(tf, kstack.top(), vm.token()) }; + let vm = self.vm.lock().clone(); + let vm_token = vm.token(); + let vm = Arc::new(Mutex::new(vm)); + let context = unsafe { Context::new_fork(tf, kstack.top(), vm_token) }; + + let mut proc = self.proc.lock(); let new_proc = Process { - vm, + vm: vm.clone(), files: proc.files.clone(), cwd: proc.cwd.clone(), exec_path: proc.exec_path.clone(), @@ -333,6 +343,7 @@ impl Thread { context, kstack, clear_child_tid: 0, + vm, proc: new_proc, }) } @@ -346,11 +357,12 @@ impl Thread { clear_child_tid: usize, ) -> Box { let kstack = KernelStack::new(); - let token = self.proc.lock().vm.token(); + let vm_token = self.vm.lock().token(); Box::new(Thread { - context: unsafe { Context::new_clone(tf, stack_top, kstack.top(), token, tls) }, + context: unsafe { Context::new_clone(tf, stack_top, kstack.top(), vm_token, tls) }, kstack, clear_child_tid, + vm: self.vm.clone(), proc: self.proc.clone(), }) } diff --git a/kernel/src/syscall/custom.rs b/kernel/src/syscall/custom.rs index 770ddd2..2803f0e 100644 --- a/kernel/src/syscall/custom.rs +++ b/kernel/src/syscall/custom.rs @@ -23,9 +23,9 @@ impl Syscall<'_> { let (base, len) = pci::get_bar0_mem(tag).ok_or(SysError::ENOENT)?; let mut proc = self.process(); - let virt_addr = proc.vm.find_free_area(0, len); + let virt_addr = self.vm().find_free_area(0, len); let attr = MemoryAttr::default().user(); - proc.vm.push( + self.vm().push( virt_addr, virt_addr + len, attr, @@ -42,12 +42,17 @@ impl Syscall<'_> { /// Get start physical addresses of frames /// mapped to a list of virtual addresses. - pub fn sys_get_paddr(&mut self, vaddrs: *const u64, paddrs: *mut u64, count: usize) -> SysResult { + pub fn sys_get_paddr( + &mut self, + vaddrs: *const u64, + paddrs: *mut u64, + count: usize, + ) -> SysResult { let mut proc = self.process(); - let vaddrs = unsafe { proc.vm.check_read_array(vaddrs, count)? }; - let paddrs = unsafe { proc.vm.check_write_array(paddrs, count)? }; + let vaddrs = unsafe { self.vm().check_read_array(vaddrs, count)? }; + let paddrs = unsafe { self.vm().check_write_array(paddrs, count)? }; for i in 0..count { - let paddr = proc.vm.translate(vaddrs[i] as usize).unwrap_or(0); + let paddr = self.vm().translate(vaddrs[i] as usize).unwrap_or(0); paddrs[i] = paddr as u64; } Ok(0) diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 6a5a18e..e6aaffd 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -22,7 +22,7 @@ impl Syscall<'_> { // we trust pid 0 process info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len); } - let slice = unsafe { proc.vm.check_write_array(base, len)? }; + let slice = unsafe { self.vm().check_write_array(base, len)? }; let file_like = proc.get_file_like(fd)?; let len = file_like.read(slice)?; Ok(len) @@ -34,7 +34,7 @@ impl Syscall<'_> { // we trust pid 0 process info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len); } - let slice = unsafe { proc.vm.check_read_array(base, len)? }; + let slice = unsafe { self.vm().check_read_array(base, len)? }; let file_like = proc.get_file_like(fd)?; let len = file_like.write(slice)?; Ok(len) @@ -46,28 +46,39 @@ impl Syscall<'_> { fd, base, len, offset ); let mut proc = self.process(); - let slice = unsafe { proc.vm.check_write_array(base, len)? }; + let slice = unsafe { self.vm().check_write_array(base, len)? }; let len = proc.get_file(fd)?.read_at(offset, slice)?; Ok(len) } - pub fn sys_pwrite(&mut self, fd: usize, base: *const u8, len: usize, offset: usize) -> SysResult { + pub fn sys_pwrite( + &mut self, + fd: usize, + base: *const u8, + len: usize, + offset: usize, + ) -> SysResult { info!( "pwrite: fd: {}, base: {:?}, len: {}, offset: {}", fd, base, len, offset ); let mut proc = self.process(); - let slice = unsafe { proc.vm.check_read_array(base, len)? }; + let slice = unsafe { self.vm().check_read_array(base, len)? }; let len = proc.get_file(fd)?.write_at(offset, slice)?; Ok(len) } - pub fn sys_ppoll(&mut self, ufds: *mut PollFd, nfds: usize, timeout: *const TimeSpec) -> SysResult { + pub fn sys_ppoll( + &mut self, + ufds: *mut PollFd, + nfds: usize, + timeout: *const TimeSpec, + ) -> SysResult { let proc = self.process(); let timeout_msecs = if timeout.is_null() { 1 << 31 // infinity } else { - let timeout = unsafe { proc.vm.check_read_ptr(timeout)? }; + let timeout = unsafe { self.vm().check_read_ptr(timeout)? }; timeout.to_msec() }; drop(proc); @@ -85,7 +96,7 @@ impl Syscall<'_> { ); } - let polls = unsafe { proc.vm.check_write_array(ufds, nfds)? }; + let polls = unsafe { self.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); @@ -148,11 +159,11 @@ impl Syscall<'_> { ); let proc = self.process(); - 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 mut read_fds = FdSet::new(&self.vm(), read, nfds)?; + let mut write_fds = FdSet::new(&self.vm(), write, nfds)?; + let mut err_fds = FdSet::new(&self.vm(), err, nfds)?; let timeout_msecs = if !timeout.is_null() { - let timeout = unsafe { proc.vm.check_read_ptr(timeout)? }; + let timeout = unsafe { self.vm().check_read_ptr(timeout)? }; timeout.to_msec() } else { // infinity @@ -203,7 +214,8 @@ impl Syscall<'_> { let current_time_ms = crate::trap::uptime_msec(); // infinity check - if timeout_msecs < (1 << 31) && current_time_ms - begin_time_ms > timeout_msecs as usize { + if timeout_msecs < (1 << 31) && current_time_ms - begin_time_ms > timeout_msecs as usize + { return Ok(0); } @@ -217,7 +229,7 @@ impl Syscall<'_> { fd, iov_ptr, iov_count ); let mut proc = self.process(); - let mut iovs = unsafe { IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, true)? }; + let mut iovs = unsafe { IoVecs::check_and_new(iov_ptr, iov_count, &self.vm(), true)? }; // read all data to a buf let file_like = proc.get_file_like(fd)?; @@ -237,7 +249,7 @@ impl Syscall<'_> { fd, iov_ptr, iov_count ); } - let iovs = unsafe { IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, false)? }; + let iovs = unsafe { IoVecs::check_and_new(iov_ptr, iov_count, &self.vm(), false)? }; let buf = iovs.read_all_to_vec(); let len = buf.len(); @@ -251,9 +263,15 @@ impl Syscall<'_> { self.sys_openat(AT_FDCWD, path, flags, mode) } - pub fn sys_openat(&mut self, dir_fd: usize, path: *const u8, flags: usize, mode: usize) -> SysResult { + pub fn sys_openat( + &mut self, + dir_fd: usize, + path: *const u8, + flags: usize, + mode: usize, + ) -> SysResult { let mut proc = self.process(); - let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; + let path = unsafe { self.vm().check_and_clone_cstr(path)? }; let flags = OpenFlags::from_bits_truncate(flags); info!( "openat: dir_fd: {}, path: {:?}, flags: {:?}, mode: {:#o}", @@ -308,10 +326,16 @@ impl Syscall<'_> { self.sys_faccessat(AT_FDCWD, path, mode, 0) } - pub fn sys_faccessat(&mut self, dirfd: usize, path: *const u8, mode: usize, flags: usize) -> SysResult { + pub fn sys_faccessat( + &mut self, + dirfd: usize, + path: *const u8, + mode: usize, + flags: usize, + ) -> SysResult { // TODO: check permissions based on uid/gid let proc = self.process(); - let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; + let path = unsafe { self.vm().check_and_clone_cstr(path)? }; let flags = AtFlags::from_bits_truncate(flags); if !proc.pid.is_init() { // we trust pid 0 process @@ -320,7 +344,8 @@ impl Syscall<'_> { dirfd as isize, path, mode, flags ); } - let inode = proc.lookup_inode_at(dirfd, &path, !flags.contains(AtFlags::SYMLINK_NOFOLLOW))?; + let inode = + proc.lookup_inode_at(dirfd, &path, !flags.contains(AtFlags::SYMLINK_NOFOLLOW))?; Ok(0) } @@ -330,7 +355,7 @@ impl Syscall<'_> { // we trust pid 0 process info!("getcwd: buf: {:?}, len: {:#x}", buf, len); } - let buf = unsafe { proc.vm.check_write_array(buf, len)? }; + let buf = unsafe { self.vm().check_write_array(buf, len)? }; if proc.cwd.len() + 1 > len { return Err(SysError::ERANGE); } @@ -345,24 +370,31 @@ impl Syscall<'_> { pub fn sys_fstat(&mut self, fd: usize, stat_ptr: *mut Stat) -> SysResult { info!("fstat: fd: {}, stat_ptr: {:?}", fd, stat_ptr); let mut proc = self.process(); - let stat_ref = unsafe { proc.vm.check_write_ptr(stat_ptr)? }; + let stat_ref = unsafe { self.vm().check_write_ptr(stat_ptr)? }; let file = proc.get_file(fd)?; let stat = Stat::from(file.metadata()?); *stat_ref = stat; Ok(0) } - pub fn sys_fstatat(&mut self, dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: usize) -> SysResult { + pub fn sys_fstatat( + &mut self, + dirfd: usize, + path: *const u8, + stat_ptr: *mut Stat, + flags: usize, + ) -> SysResult { let proc = self.process(); - let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; - let stat_ref = unsafe { proc.vm.check_write_ptr(stat_ptr)? }; + let path = unsafe { self.vm().check_and_clone_cstr(path)? }; + let stat_ref = unsafe { self.vm().check_write_ptr(stat_ptr)? }; let flags = AtFlags::from_bits_truncate(flags); info!( "fstatat: dirfd: {}, path: {:?}, stat_ptr: {:?}, flags: {:?}", dirfd as isize, path, stat_ptr, flags ); - let inode = proc.lookup_inode_at(dirfd, &path, !flags.contains(AtFlags::SYMLINK_NOFOLLOW))?; + let inode = + proc.lookup_inode_at(dirfd, &path, !flags.contains(AtFlags::SYMLINK_NOFOLLOW))?; let stat = Stat::from(inode.metadata()?); *stat_ref = stat; Ok(0) @@ -376,10 +408,16 @@ impl Syscall<'_> { self.sys_readlinkat(AT_FDCWD, path, base, len) } - pub fn sys_readlinkat(&mut self, dirfd: usize, path: *const u8, base: *mut u8, len: usize) -> SysResult { + pub fn sys_readlinkat( + &mut self, + dirfd: usize, + path: *const u8, + base: *mut u8, + len: usize, + ) -> SysResult { let proc = self.process(); - let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; - let slice = unsafe { proc.vm.check_write_array(base, len)? }; + let path = unsafe { self.vm().check_and_clone_cstr(path)? }; + let slice = unsafe { self.vm().check_write_array(base, len)? }; info!( "readlinkat: dirfd: {}, path: {:?}, base: {:?}, len: {}", dirfd as isize, path, base, len @@ -424,7 +462,7 @@ impl Syscall<'_> { pub fn sys_truncate(&mut self, path: *const u8, len: usize) -> SysResult { let proc = self.process(); - let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; + let path = unsafe { self.vm().check_and_clone_cstr(path)? }; info!("truncate: path: {:?}, len: {}", path, len); proc.lookup_inode(&path)?.resize(len)?; Ok(0) @@ -436,13 +474,18 @@ impl Syscall<'_> { Ok(0) } - pub fn sys_getdents64(&mut self, fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> SysResult { + pub fn sys_getdents64( + &mut self, + fd: usize, + buf: *mut LinuxDirent64, + buf_size: usize, + ) -> SysResult { info!( "getdents64: fd: {}, ptr: {:?}, buf_size: {}", fd, buf, buf_size ); let mut proc = self.process(); - let buf = unsafe { proc.vm.check_write_array(buf as *mut u8, buf_size)? }; + let buf = unsafe { self.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 { @@ -474,7 +517,14 @@ impl Syscall<'_> { Ok(fd2) } - pub fn sys_ioctl(&mut self, fd: usize, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult { + pub fn sys_ioctl( + &mut self, + fd: usize, + request: usize, + arg1: usize, + arg2: usize, + arg3: usize, + ) -> SysResult { info!( "ioctl: fd: {}, request: {:x}, args: {} {} {}", fd, request, arg1, arg2, arg3 @@ -486,7 +536,7 @@ impl Syscall<'_> { pub fn sys_chdir(&mut self, path: *const u8) -> SysResult { let mut proc = self.process(); - let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; + let path = unsafe { self.vm().check_and_clone_cstr(path)? }; if !proc.pid.is_init() { // we trust pid 0 process info!("chdir: path: {:?}", path); @@ -539,8 +589,8 @@ impl Syscall<'_> { newpath: *const u8, ) -> SysResult { let mut proc = self.process(); - let oldpath = unsafe { proc.vm.check_and_clone_cstr(oldpath)? }; - let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? }; + let oldpath = unsafe { self.vm().check_and_clone_cstr(oldpath)? }; + let newpath = unsafe { self.vm().check_and_clone_cstr(newpath)? }; info!( "renameat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}", olddirfd as isize, oldpath, newdirfd as isize, newpath @@ -560,7 +610,7 @@ impl Syscall<'_> { pub fn sys_mkdirat(&mut self, dirfd: usize, path: *const u8, mode: usize) -> SysResult { let proc = self.process(); - let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; + let path = unsafe { self.vm().check_and_clone_cstr(path)? }; // TODO: check pathname info!( "mkdirat: dirfd: {}, path: {:?}, mode: {:#o}", @@ -578,7 +628,7 @@ impl Syscall<'_> { pub fn sys_rmdir(&mut self, path: *const u8) -> SysResult { let proc = self.process(); - let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; + let path = unsafe { self.vm().check_and_clone_cstr(path)? }; info!("rmdir: path: {:?}", path); let (dir_path, file_name) = split_path(&path); @@ -604,8 +654,8 @@ impl Syscall<'_> { flags: usize, ) -> SysResult { let proc = self.process(); - let oldpath = unsafe { proc.vm.check_and_clone_cstr(oldpath)? }; - let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? }; + let oldpath = unsafe { self.vm().check_and_clone_cstr(oldpath)? }; + let newpath = unsafe { self.vm().check_and_clone_cstr(newpath)? }; let flags = AtFlags::from_bits_truncate(flags); info!( "linkat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}, flags: {:?}", @@ -625,7 +675,7 @@ impl Syscall<'_> { pub fn sys_unlinkat(&mut self, dirfd: usize, path: *const u8, flags: usize) -> SysResult { let proc = self.process(); - let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; + let path = unsafe { self.vm().check_and_clone_cstr(path)? }; let flags = AtFlags::from_bits_truncate(flags); info!( "unlinkat: dirfd: {}, path: {:?}, flags: {:?}", @@ -646,7 +696,7 @@ impl Syscall<'_> { info!("pipe: fds: {:?}", fds); let mut proc = self.process(); - let fds = unsafe { proc.vm.check_write_array(fds, 2)? }; + let fds = unsafe { self.vm().check_write_array(fds, 2)? }; let (read, write) = Pipe::create_pair(); let read_fd = proc.add_file(FileLike::File(FileHandle::new( @@ -701,7 +751,7 @@ impl Syscall<'_> { let mut buffer = [0u8; 1024]; let mut read_offset = if !offset_ptr.is_null() { - unsafe { *(*proc_cell.get()).vm.check_read_ptr(offset_ptr)? } + unsafe { *self.vm().check_read_ptr(offset_ptr)? } } else { in_file.seek(SeekFrom::Current(0))? as usize }; diff --git a/kernel/src/syscall/mem.rs b/kernel/src/syscall/mem.rs index 7195ea9..e066f1c 100644 --- a/kernel/src/syscall/mem.rs +++ b/kernel/src/syscall/mem.rs @@ -35,16 +35,16 @@ impl Syscall<'_> { if flags.contains(MmapFlags::FIXED) { // we have to map it to addr, so remove the old mapping first - proc.vm.pop_with_split(addr, addr + len); + self.vm().pop_with_split(addr, addr + len); } else { - addr = proc.vm.find_free_area(addr, len); + addr = self.vm().find_free_area(addr, len); } if flags.contains(MmapFlags::ANONYMOUS) { if flags.contains(MmapFlags::SHARED) { return Err(SysError::EINVAL); } - proc.vm.push( + self.vm().push( addr, addr + len, prot.to_attr(), @@ -54,7 +54,7 @@ impl Syscall<'_> { return Ok(addr); } else { let inode = proc.get_file(fd)?.inode(); - proc.vm.push( + self.vm().push( addr, addr + len, prot.to_attr(), @@ -83,8 +83,8 @@ impl Syscall<'_> { // FIXME: properly set the attribute of the area // now some mut ptr check is fault - let memory_area = proc - .vm + let vm = self.vm(); + let memory_area = vm .iter() .find(|area| area.is_overlap_with(addr, addr + len)); if memory_area.is_none() { @@ -96,7 +96,7 @@ impl Syscall<'_> { pub fn sys_munmap(&mut self, addr: usize, len: usize) -> SysResult { info!("munmap addr={:#x}, size={:#x}", addr, len); let mut proc = self.process(); - proc.vm.pop_with_split(addr, addr + len); + self.vm().pop_with_split(addr, addr + len); Ok(0) } } diff --git a/kernel/src/syscall/misc.rs b/kernel/src/syscall/misc.rs index 886761b..ddb3918 100644 --- a/kernel/src/syscall/misc.rs +++ b/kernel/src/syscall/misc.rs @@ -24,7 +24,7 @@ impl Syscall<'_> { let offset = 65; let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"]; let proc = self.process(); - let buf = unsafe { proc.vm.check_write_array(buf, strings.len() * offset)? }; + let buf = unsafe { self.vm().check_write_array(buf, strings.len() * offset)? }; for i in 0..strings.len() { unsafe { @@ -40,7 +40,7 @@ impl Syscall<'_> { pid, size, mask ); let proc = self.process(); - let mask = unsafe { proc.vm.check_write_array(mask, size / size_of::())? }; + let mask = unsafe { self.vm().check_write_array(mask, size / size_of::())? }; // we only have 4 cpu at most. // so just set it. @@ -50,14 +50,20 @@ impl Syscall<'_> { pub fn sys_sysinfo(&mut self, sys_info: *mut SysInfo) -> SysResult { let proc = self.process(); - let sys_info = unsafe { proc.vm.check_write_ptr(sys_info)? }; + let sys_info = unsafe { self.vm().check_write_ptr(sys_info)? }; let sysinfo = SysInfo::default(); *sys_info = sysinfo; Ok(0) } - pub fn sys_futex(&mut self, uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> SysResult { + pub fn sys_futex( + &mut self, + uaddr: usize, + op: u32, + val: i32, + timeout: *const TimeSpec, + ) -> SysResult { info!( "futex: [{}] uaddr: {:#x}, op: {:#x}, val: {}, timeout_ptr: {:?}", thread::current().id(), @@ -73,11 +79,11 @@ impl Syscall<'_> { if uaddr % size_of::() != 0 { return Err(SysError::EINVAL); } - let atomic = unsafe { self.process().vm.check_write_ptr(uaddr as *mut AtomicI32)? }; + let atomic = unsafe { self.vm().check_write_ptr(uaddr as *mut AtomicI32)? }; let _timeout = if timeout.is_null() { None } else { - Some(unsafe { *self.process().vm.check_read_ptr(timeout)? }) + Some(unsafe { *self.vm().check_read_ptr(timeout)? }) }; const OP_WAIT: u32 = 0; @@ -132,7 +138,7 @@ impl Syscall<'_> { match resource { RLIMIT_STACK => { if !old_limit.is_null() { - let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? }; + let old_limit = unsafe { self.vm().check_write_ptr(old_limit)? }; *old_limit = RLimit { cur: USER_STACK_SIZE as u64, max: USER_STACK_SIZE as u64, @@ -142,7 +148,7 @@ impl Syscall<'_> { } RLIMIT_NOFILE => { if !old_limit.is_null() { - let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? }; + let old_limit = unsafe { self.vm().check_write_ptr(old_limit)? }; *old_limit = RLimit { cur: 1024, max: 1024, @@ -152,7 +158,7 @@ impl Syscall<'_> { } RLIMIT_RSS | RLIMIT_AS => { if !old_limit.is_null() { - let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? }; + let old_limit = unsafe { self.vm().check_write_ptr(old_limit)? }; // 1GB *old_limit = RLimit { cur: 1024 * 1024 * 1024, @@ -168,7 +174,7 @@ impl Syscall<'_> { pub fn sys_getrandom(&mut self, buf: *mut u8, len: usize, flag: u32) -> SysResult { //info!("getrandom: buf: {:?}, len: {:?}, falg {:?}", buf, len,flag); let mut proc = self.process(); - let slice = unsafe { proc.vm.check_write_array(buf, len)? }; + let slice = unsafe { self.vm().check_write_array(buf, len)? }; let mut i = 0; for elm in slice { unsafe { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index f087690..f637648 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -10,8 +10,9 @@ use rcore_memory::VMError; use crate::arch::cpu; use crate::arch::interrupt::TrapFrame; use crate::arch::syscall::*; +use crate::memory::MemorySet; use crate::process::*; -use crate::sync::{Condvar, SpinNoIrq, MutexGuard}; +use crate::sync::{Condvar, MutexGuard, SpinNoIrq}; use crate::thread; use crate::util; @@ -58,6 +59,11 @@ impl Syscall<'_> { self.thread.proc.lock() } + /// Get current virtual memory + pub fn vm(&self) -> MutexGuard<'_, MemorySet, SpinNoIrq> { + self.thread.vm.lock() + } + /// System call dispatcher // This #[deny(unreachable_patterns)] checks if each match arm is defined // See discussion in https://github.com/oscourse-tsinghua/rcore_plus/commit/17e644e54e494835f1a49b34b80c2c4f15ed0dbe. @@ -83,7 +89,9 @@ impl Syscall<'_> { SYS_OPENAT => self.sys_openat(args[0], args[1] as *const u8, args[2], args[3]), SYS_CLOSE => self.sys_close(args[0]), SYS_FSTAT => self.sys_fstat(args[0], args[1] as *mut Stat), - SYS_NEWFSTATAT => self.sys_fstatat(args[0], args[1] as *const u8, args[2] as *mut Stat, args[3]), + SYS_NEWFSTATAT => { + self.sys_fstatat(args[0], args[1] as *const u8, args[2] as *mut Stat, args[3]) + } SYS_LSEEK => self.sys_lseek(args[0], args[1] as i64, args[2] as u8), SYS_IOCTL => self.sys_ioctl(args[0], args[1], args[2], args[3], args[4]), SYS_PREAD64 => self.sys_pread(args[0], args[1] as *mut u8, args[2], args[3]), @@ -100,7 +108,9 @@ impl Syscall<'_> { SYS_GETDENTS64 => self.sys_getdents64(args[0], args[1] as *mut LinuxDirent64, args[2]), SYS_GETCWD => self.sys_getcwd(args[0] as *mut u8, args[1]), SYS_CHDIR => self.sys_chdir(args[0] as *const u8), - SYS_RENAMEAT => self.sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8), + SYS_RENAMEAT => { + self.sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8) + } SYS_MKDIRAT => self.sys_mkdirat(args[0], args[1] as *const u8, args[2]), SYS_LINKAT => self.sys_linkat( args[0], @@ -124,7 +134,9 @@ impl Syscall<'_> { SYS_UTIMENSAT => self.unimplemented("utimensat", Ok(0)), // io multiplexing - SYS_PPOLL => self.sys_ppoll(args[0] as *mut PollFd, args[1], args[2] as *const TimeSpec), // ignore sigmask + SYS_PPOLL => { + self.sys_ppoll(args[0] as *mut PollFd, args[1], args[2] as *const TimeSpec) + } // ignore sigmask SYS_EPOLL_CREATE1 => self.unimplemented("epoll_create1", Err(SysError::ENOSYS)), // file system @@ -149,7 +161,9 @@ impl Syscall<'_> { // schedule SYS_SCHED_YIELD => self.sys_yield(), - SYS_SCHED_GETAFFINITY => self.sys_sched_getaffinity(args[0], args[1], args[2] as *mut u32), + SYS_SCHED_GETAFFINITY => { + self.sys_sched_getaffinity(args[0], args[1], args[2] as *mut u32) + } // socket SYS_SOCKET => self.sys_socket(args[0], args[1], args[2]), @@ -177,9 +191,15 @@ impl Syscall<'_> { SYS_SHUTDOWN => self.sys_shutdown(args[0], args[1]), SYS_BIND => self.sys_bind(args[0], args[1] as *const SockAddr, args[2]), SYS_LISTEN => self.sys_listen(args[0], args[1]), - SYS_GETSOCKNAME => self.sys_getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), - SYS_GETPEERNAME => self.sys_getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), - SYS_SETSOCKOPT => self.sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]), + SYS_GETSOCKNAME => { + self.sys_getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32) + } + SYS_GETPEERNAME => { + self.sys_getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32) + } + SYS_SETSOCKOPT => { + self.sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]) + } SYS_GETSOCKOPT => self.sys_getsockopt( args[0], args[1], @@ -215,7 +235,9 @@ impl Syscall<'_> { // time SYS_NANOSLEEP => self.sys_nanosleep(args[0] as *const TimeSpec), SYS_SETITIMER => self.unimplemented("setitimer", Ok(0)), - SYS_GETTIMEOFDAY => self.sys_gettimeofday(args[0] as *mut TimeVal, args[1] as *const u8), + SYS_GETTIMEOFDAY => { + self.sys_gettimeofday(args[0] as *mut TimeVal, args[1] as *const u8) + } SYS_CLOCK_GETTIME => self.sys_clock_gettime(args[0], args[1] as *mut TimeSpec), // system @@ -256,9 +278,13 @@ impl Syscall<'_> { // custom SYS_MAP_PCI_DEVICE => self.sys_map_pci_device(args[0], args[1]), - SYS_GET_PADDR => self.sys_get_paddr(args[0] as *const u64, args[1] as *mut u64, args[2]), + SYS_GET_PADDR => { + self.sys_get_paddr(args[0] as *const u64, args[1] as *mut u64, args[2]) + } //SYS_GETRANDOM => self.unimplemented("getrandom", Err(SysError::EINVAL)), - SYS_GETRANDOM => self.sys_getrandom(args[0] as *mut u8, args[1] as usize, args[2] as u32), + SYS_GETRANDOM => { + self.sys_getrandom(args[0] as *mut u8, args[1] as usize, args[2] as u32) + } SYS_TKILL => self.unimplemented("tkill", Ok(0)), _ => { let ret = match () { @@ -306,7 +332,7 @@ impl Syscall<'_> { } #[cfg(target_arch = "mips")] - fn mips_syscall(&mut self, id: usize, args: [usize; 6],) -> Option { + fn mips_syscall(&mut self, id: usize, args: [usize; 6]) -> Option { let ret = match id { SYS_OPEN => self.sys_open(args[0] as *const u8, args[1], args[2]), SYS_POLL => self.sys_poll(args[0] as *mut PollFd, args[1], args[2]), diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index a5183a7..98f978a 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -3,6 +3,7 @@ use super::fs::IoVecs; use super::*; use crate::fs::FileLike; +use crate::memory::MemorySet; use crate::net::{ Endpoint, LinkLevelEndpoint, NetlinkEndpoint, NetlinkSocketState, PacketSocketState, RawSocketState, Socket, TcpSocketState, UdpSocketState, SOCKETS, @@ -12,7 +13,6 @@ use alloc::boxed::Box; use core::cmp::min; use core::mem::size_of; use smoltcp::wire::*; -use crate::memory::MemorySet; impl Syscall<'_> { pub fn sys_socket(&mut self, domain: usize, socket_type: usize, protocol: usize) -> SysResult { @@ -57,7 +57,7 @@ impl Syscall<'_> { fd, level, optname ); let mut proc = self.process(); - let data = unsafe { proc.vm.check_read_array(optval, optlen)? }; + let data = unsafe { self.vm().check_read_array(optval, optlen)? }; let socket = proc.get_socket(fd)?; socket.setsockopt(level, optname, data) } @@ -75,17 +75,17 @@ impl Syscall<'_> { fd, level, optname, optval, optlen ); let proc = self.process(); - let optlen = unsafe { proc.vm.check_write_ptr(optlen)? }; + let optlen = unsafe { self.vm().check_write_ptr(optlen)? }; match level { SOL_SOCKET => match optname { SO_SNDBUF => { - let optval = unsafe { proc.vm.check_write_ptr(optval as *mut u32)? }; + let optval = unsafe { self.vm().check_write_ptr(optval as *mut u32)? }; *optval = crate::net::TCP_SENDBUF as u32; *optlen = 4; Ok(0) } SO_RCVBUF => { - let optval = unsafe { proc.vm.check_write_ptr(optval as *mut u32)? }; + let optval = unsafe { self.vm().check_write_ptr(optval as *mut u32)? }; *optval = crate::net::TCP_RECVBUF as u32; *optlen = 4; Ok(0) @@ -107,7 +107,7 @@ impl Syscall<'_> { ); let mut proc = self.process(); - let endpoint = sockaddr_to_endpoint(&mut proc.vm, addr, addr_len)?; + let endpoint = sockaddr_to_endpoint(&mut self.vm(), addr, addr_len)?; let socket = proc.get_socket(fd)?; socket.connect(endpoint)?; Ok(0) @@ -129,11 +129,11 @@ impl Syscall<'_> { let mut proc = self.process(); - let slice = unsafe { proc.vm.check_read_array(base, len)? }; + let slice = unsafe { self.vm().check_read_array(base, len)? }; let endpoint = if addr.is_null() { None } else { - let endpoint = sockaddr_to_endpoint(&mut proc.vm, addr, addr_len)?; + let endpoint = sockaddr_to_endpoint(&mut self.vm(), addr, addr_len)?; info!("sys_sendto: sending to endpoint {:?}", endpoint); Some(endpoint) }; @@ -157,14 +157,14 @@ impl Syscall<'_> { let mut proc = self.process(); - let mut slice = unsafe { proc.vm.check_write_array(base, len)? }; + let mut slice = unsafe { self.vm().check_write_array(base, len)? }; let socket = proc.get_socket(fd)?; let (result, endpoint) = socket.read(&mut slice); if result.is_ok() && !addr.is_null() { let sockaddr_in = SockAddr::from(endpoint); unsafe { - sockaddr_in.write_to(&mut proc, addr, addr_len)?; + sockaddr_in.write_to(&mut self.vm(), addr, addr_len)?; } } @@ -174,8 +174,9 @@ impl Syscall<'_> { pub fn sys_recvmsg(&mut self, fd: usize, msg: *mut MsgHdr, flags: usize) -> SysResult { info!("recvmsg: fd: {}, msg: {:?}, flags: {}", fd, msg, flags); let mut proc = self.process(); - 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 hdr = unsafe { self.vm().check_write_ptr(msg)? }; + let mut iovs = + unsafe { IoVecs::check_and_new(hdr.msg_iov, hdr.msg_iovlen, &self.vm(), true)? }; let mut buf = iovs.new_buf(true); let socket = proc.get_socket(fd)?; @@ -186,7 +187,7 @@ impl Syscall<'_> { iovs.write_all_from_slice(&buf[..len]); let sockaddr_in = SockAddr::from(endpoint); unsafe { - sockaddr_in.write_to(&mut proc, hdr.msg_name, &mut hdr.msg_namelen as *mut u32)?; + sockaddr_in.write_to(&mut self.vm(), hdr.msg_name, &mut hdr.msg_namelen as *mut u32)?; } } result @@ -196,7 +197,7 @@ impl Syscall<'_> { info!("sys_bind: fd: {} addr: {:?} len: {}", fd, addr, addr_len); let mut proc = self.process(); - let mut endpoint = sockaddr_to_endpoint(&mut proc.vm, addr, addr_len)?; + let mut endpoint = sockaddr_to_endpoint(&mut self.vm(), addr, addr_len)?; info!("sys_bind: fd: {} bind to {:?}", fd, endpoint); let socket = proc.get_socket(fd)?; @@ -238,13 +239,18 @@ impl Syscall<'_> { if !addr.is_null() { let sockaddr_in = SockAddr::from(remote_endpoint); unsafe { - sockaddr_in.write_to(&mut proc, addr, addr_len)?; + sockaddr_in.write_to(&mut self.vm(), addr, addr_len)?; } } Ok(new_fd) } - pub fn sys_getsockname(&mut self, fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult { + pub fn sys_getsockname( + &mut self, + fd: usize, + addr: *mut SockAddr, + addr_len: *mut u32, + ) -> SysResult { info!( "sys_getsockname: fd: {} addr: {:?} addr_len: {:?}", fd, addr, addr_len @@ -260,12 +266,17 @@ impl Syscall<'_> { let endpoint = socket.endpoint().ok_or(SysError::EINVAL)?; let sockaddr_in = SockAddr::from(endpoint); unsafe { - sockaddr_in.write_to(&mut proc, addr, addr_len)?; + sockaddr_in.write_to(&mut self.vm(), addr, addr_len)?; } Ok(0) } - pub fn sys_getpeername(&mut self, fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult { + pub fn sys_getpeername( + &mut self, + fd: usize, + addr: *mut SockAddr, + addr_len: *mut u32, + ) -> SysResult { info!( "sys_getpeername: fd: {} addr: {:?} addr_len: {:?}", fd, addr, addr_len @@ -283,7 +294,7 @@ impl Syscall<'_> { let remote_endpoint = socket.remote_endpoint().ok_or(SysError::EINVAL)?; let sockaddr_in = SockAddr::from(remote_endpoint); unsafe { - sockaddr_in.write_to(&mut proc, addr, addr_len)?; + sockaddr_in.write_to(&mut self.vm(), addr, addr_len)?; } Ok(0) } @@ -405,12 +416,12 @@ fn sockaddr_to_endpoint( return Err(SysError::EINVAL); } let addr = unsafe { vm.check_read_ptr(addr)? }; + if len < addr.len()? { + return Err(SysError::EINVAL); + } unsafe { 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 addr = IpAddress::from(Ipv4Address::from_bytes( &u32::from_be(addr.addr_in.sin_addr).to_be_bytes()[..], @@ -419,17 +430,11 @@ fn sockaddr_to_endpoint( } AddressFamily::Unix => Err(SysError::EINVAL), AddressFamily::Packet => { - if len < size_of::() { - return Err(SysError::EINVAL); - } Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new( addr.addr_ll.sll_ifindex as usize, ))) } AddressFamily::Netlink => { - if len < size_of::() { - return Err(SysError::EINVAL); - } Ok(Endpoint::Netlink(NetlinkEndpoint::new( addr.addr_nl.nl_pid, addr.addr_nl.nl_groups, @@ -441,11 +446,21 @@ fn sockaddr_to_endpoint( } impl SockAddr { + fn len(&self) -> Result { + match AddressFamily::from(unsafe { self.family }) { + AddressFamily::Internet => Ok(size_of::()), + AddressFamily::Packet => Ok(size_of::()), + AddressFamily::Netlink => Ok(size_of::()), + AddressFamily::Unix => Err(SysError::EINVAL), + _ => Err(SysError::EINVAL), + } + } + /// Write to user sockaddr /// Check mutability for user unsafe fn write_to( self, - proc: &mut Process, + vm: &MemorySet, addr: *mut SockAddr, addr_len: *mut u32, ) -> SysResult { @@ -454,19 +469,13 @@ impl SockAddr { return Ok(0); } - let addr_len = unsafe { proc.vm.check_write_ptr(addr_len)? }; + let addr_len = unsafe { 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::(), - AddressFamily::Packet => size_of::(), - AddressFamily::Netlink => size_of::(), - AddressFamily::Unix => return Err(SysError::EINVAL), - _ => return Err(SysError::EINVAL), - }; + let full_len = self.len()?; let written_len = min(max_addr_len, full_len); if written_len > 0 { - let target = unsafe { proc.vm.check_write_array(addr as *mut u8, written_len)? }; + let target = unsafe { 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); target.copy_from_slice(source); } diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index 56b94ee..fbdbc2d 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -49,8 +49,8 @@ impl Syscall<'_> { ); //return Err(SysError::ENOSYS); } - let parent_tid_ref = unsafe { self.process().vm.check_write_ptr(parent_tid)? }; - let child_tid_ref = unsafe { self.process().vm.check_write_ptr(child_tid)? }; + let parent_tid_ref = unsafe { self.vm().check_write_ptr(parent_tid)? }; + let child_tid_ref = unsafe { self.vm().check_write_ptr(child_tid)? }; let new_thread = self .thread .clone(self.tf, newsp, newtls, child_tid as usize); @@ -68,7 +68,7 @@ impl Syscall<'_> { pub fn sys_wait4(&mut self, pid: isize, wstatus: *mut i32) -> SysResult { //info!("wait4: pid: {}, code: {:?}", pid, wstatus); let wstatus = if !wstatus.is_null() { - Some(unsafe { self.process().vm.check_write_ptr(wstatus)? }) + Some(unsafe { self.vm().check_write_ptr(wstatus)? }) } else { None }; @@ -150,9 +150,9 @@ impl Syscall<'_> { path, argv, envp ); let mut proc = self.process(); - 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)? }; + let path = unsafe { self.vm().check_and_clone_cstr(path)? }; + let args = unsafe { self.vm().check_and_clone_cstr_array(argv)? }; + let envs = unsafe { self.vm().check_and_clone_cstr_array(envp)? }; if args.is_empty() { error!("exec: args is null"); @@ -180,9 +180,9 @@ impl Syscall<'_> { Thread::new_user_vm(&inode, &path, args, envs).map_err(|_| SysError::EINVAL)?; // Activate new page table - core::mem::swap(&mut proc.vm, &mut vm); + core::mem::swap(&mut *self.vm(), &mut vm); unsafe { - proc.vm.activate(); + self.vm().activate(); } // Modify exec path @@ -289,7 +289,7 @@ impl Syscall<'_> { let clear_child_tid = self.thread.clear_child_tid as *mut u32; if !clear_child_tid.is_null() { info!("exit: futex {:#?} wake 1", clear_child_tid); - if let Ok(clear_child_tid_ref) = unsafe { proc.vm.check_write_ptr(clear_child_tid) } { + if let Ok(clear_child_tid_ref) = unsafe { self.vm().check_write_ptr(clear_child_tid) } { *clear_child_tid_ref = 0; let queue = proc.get_futex(clear_child_tid as usize); queue.notify_one(); @@ -328,7 +328,7 @@ impl Syscall<'_> { } pub fn sys_nanosleep(&mut self, req: *const TimeSpec) -> SysResult { - let time = unsafe { *self.process().vm.check_read_ptr(req)? }; + let time = unsafe { *self.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 4b99eeb..2471dcc 100644 --- a/kernel/src/syscall/time.rs +++ b/kernel/src/syscall/time.rs @@ -13,7 +13,7 @@ impl Syscall<'_> { } let proc = self.process(); - let tv = unsafe { proc.vm.check_write_ptr(tv)? }; + let tv = unsafe { self.vm().check_write_ptr(tv)? }; let timeval = TimeVal::get_epoch(); *tv = timeval; @@ -24,7 +24,7 @@ impl Syscall<'_> { info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts); let proc = self.process(); - let ts = unsafe { proc.vm.check_write_ptr(ts)? }; + let ts = unsafe { self.vm().check_write_ptr(ts)? }; let timespec = TimeSpec::get_epoch(); *ts = timespec; @@ -35,7 +35,7 @@ impl Syscall<'_> { let sec = get_epoch_usec() / USEC_PER_SEC; if time as usize != 0 { let proc = self.process(); - let time = unsafe { proc.vm.check_write_ptr(time)? }; + let time = unsafe { self.vm().check_write_ptr(time)? }; *time = sec as u64; } Ok(sec as usize) @@ -44,7 +44,7 @@ impl Syscall<'_> { pub fn sys_getrusage(&mut self, who: usize, rusage: *mut RUsage) -> SysResult { info!("getrusage: who: {}, rusage: {:?}", who, rusage); let proc = self.process(); - let rusage = unsafe { proc.vm.check_write_ptr(rusage)? }; + let rusage = unsafe { self.vm().check_write_ptr(rusage)? }; let tick_base = *TICK_BASE; let tick = unsafe { crate::trap::TICK as u64 }; @@ -67,7 +67,7 @@ impl Syscall<'_> { pub fn sys_times(&mut self, buf: *mut Tms) -> SysResult { info!("times: buf: {:?}", buf); let proc = self.process(); - let buf = unsafe { proc.vm.check_write_ptr(buf)? }; + let buf = unsafe { self.vm().check_write_ptr(buf)? }; let tick_base = *TICK_BASE; let tick = unsafe { crate::trap::TICK as u64 };