fix page table racing on multi-thread

toolchain_update
WangRunji 6 years ago
parent da58486be5
commit b2de8dc9e6

@ -132,12 +132,8 @@ impl Drop for KernelStack {
pub fn handle_page_fault(addr: usize) -> bool { pub fn handle_page_fault(addr: usize) -> bool {
debug!("page fault @ {:#x}", addr); debug!("page fault @ {:#x}", addr);
// FIXME: fix racing caused by force_unlock let thread = unsafe { current_thread() };
unsafe { thread.vm.lock().handle_page_fault(addr)
let thread = current_thread();
thread.proc.force_unlock();
thread.proc.lock().vm.handle_page_fault(addr)
}
} }
pub fn init_heap() { pub fn init_heap() {

@ -23,13 +23,14 @@ use super::abi::{self, ProcInitInfo};
use core::mem::uninitialized; use core::mem::uninitialized;
use rcore_fs::vfs::INode; use rcore_fs::vfs::INode;
// TODO: avoid pub
pub struct Thread { pub struct Thread {
pub context: Context, context: Context,
pub kstack: KernelStack, kstack: KernelStack,
/// Kernel performs futex wake when thread exits. /// Kernel performs futex wake when thread exits.
/// Ref: [http://man7.org/linux/man-pages/man2/set_tid_address.2.html] /// Ref: [http://man7.org/linux/man-pages/man2/set_tid_address.2.html]
pub clear_child_tid: usize, pub clear_child_tid: usize,
// This is same as `proc.vm`
pub vm: Arc<Mutex<MemorySet>>,
pub proc: Arc<Mutex<Process>>, pub proc: Arc<Mutex<Process>>,
} }
@ -57,7 +58,7 @@ impl fmt::Display for Pid {
pub struct Process { pub struct Process {
// resources // resources
pub vm: MemorySet, pub vm: Arc<Mutex<MemorySet>>,
pub files: BTreeMap<usize, FileLike>, pub files: BTreeMap<usize, FileLike>,
pub cwd: String, pub cwd: String,
pub exec_path: String, pub exec_path: String,
@ -108,11 +109,14 @@ impl Thread {
/// Make a new kernel thread starting from `entry` with `arg` /// Make a new kernel thread starting from `entry` with `arg`
pub fn new_kernel(entry: extern "C" fn(usize) -> !, arg: usize) -> Box<Thread> { pub fn new_kernel(entry: extern "C" fn(usize) -> !, arg: usize) -> Box<Thread> {
let vm = MemorySet::new(); let vm = MemorySet::new();
let vm_token = vm.token();
let vm = Arc::new(Mutex::new(vm));
let kstack = KernelStack::new(); let kstack = KernelStack::new();
Box::new(Thread { 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, kstack,
clear_child_tid: 0, clear_child_tid: 0,
vm: vm.clone(),
// TODO: kernel thread should not have a process // TODO: kernel thread should not have a process
proc: Process { proc: Process {
vm, vm,
@ -243,6 +247,8 @@ impl Thread {
) -> Box<Thread> { ) -> Box<Thread> {
let (vm, entry_addr, ustack_top) = Self::new_user_vm(inode, exec_path, args, envs).unwrap(); 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 kstack = KernelStack::new();
let mut files = BTreeMap::new(); let mut files = BTreeMap::new();
@ -285,10 +291,11 @@ impl Thread {
Box::new(Thread { Box::new(Thread {
context: unsafe { 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, kstack,
clear_child_tid: 0, clear_child_tid: 0,
vm: vm.clone(),
proc: Process { proc: Process {
vm, vm,
files, files,
@ -308,12 +315,15 @@ impl Thread {
/// Fork a new process from current one /// Fork a new process from current one
pub fn fork(&self, tf: &TrapFrame) -> Box<Thread> { pub fn fork(&self, tf: &TrapFrame) -> Box<Thread> {
let mut proc = self.proc.lock();
let kstack = KernelStack::new(); let kstack = KernelStack::new();
let vm = proc.vm.clone(); let vm = self.vm.lock().clone();
let context = unsafe { Context::new_fork(tf, kstack.top(), vm.token()) }; 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 { let new_proc = Process {
vm, vm: vm.clone(),
files: proc.files.clone(), files: proc.files.clone(),
cwd: proc.cwd.clone(), cwd: proc.cwd.clone(),
exec_path: proc.exec_path.clone(), exec_path: proc.exec_path.clone(),
@ -333,6 +343,7 @@ impl Thread {
context, context,
kstack, kstack,
clear_child_tid: 0, clear_child_tid: 0,
vm,
proc: new_proc, proc: new_proc,
}) })
} }
@ -346,11 +357,12 @@ impl Thread {
clear_child_tid: usize, clear_child_tid: usize,
) -> Box<Thread> { ) -> Box<Thread> {
let kstack = KernelStack::new(); let kstack = KernelStack::new();
let token = self.proc.lock().vm.token(); let vm_token = self.vm.lock().token();
Box::new(Thread { 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, kstack,
clear_child_tid, clear_child_tid,
vm: self.vm.clone(),
proc: self.proc.clone(), proc: self.proc.clone(),
}) })
} }

@ -23,9 +23,9 @@ impl Syscall<'_> {
let (base, len) = pci::get_bar0_mem(tag).ok_or(SysError::ENOENT)?; let (base, len) = pci::get_bar0_mem(tag).ok_or(SysError::ENOENT)?;
let mut proc = self.process(); 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(); let attr = MemoryAttr::default().user();
proc.vm.push( self.vm().push(
virt_addr, virt_addr,
virt_addr + len, virt_addr + len,
attr, attr,
@ -42,12 +42,17 @@ impl Syscall<'_> {
/// Get start physical addresses of frames /// Get start physical addresses of frames
/// mapped to a list of virtual addresses. /// 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 mut proc = self.process();
let vaddrs = unsafe { proc.vm.check_read_array(vaddrs, count)? }; let vaddrs = unsafe { self.vm().check_read_array(vaddrs, count)? };
let paddrs = unsafe { proc.vm.check_write_array(paddrs, count)? }; let paddrs = unsafe { self.vm().check_write_array(paddrs, count)? };
for i in 0..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; paddrs[i] = paddr as u64;
} }
Ok(0) Ok(0)

@ -22,7 +22,7 @@ impl Syscall<'_> {
// we trust pid 0 process // we trust pid 0 process
info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len); 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 file_like = proc.get_file_like(fd)?;
let len = file_like.read(slice)?; let len = file_like.read(slice)?;
Ok(len) Ok(len)
@ -34,7 +34,7 @@ impl Syscall<'_> {
// we trust pid 0 process // we trust pid 0 process
info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len); 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 file_like = proc.get_file_like(fd)?;
let len = file_like.write(slice)?; let len = file_like.write(slice)?;
Ok(len) Ok(len)
@ -46,28 +46,39 @@ impl Syscall<'_> {
fd, base, len, offset fd, base, len, offset
); );
let mut proc = self.process(); 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)?; let len = proc.get_file(fd)?.read_at(offset, slice)?;
Ok(len) 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!( info!(
"pwrite: fd: {}, base: {:?}, len: {}, offset: {}", "pwrite: fd: {}, base: {:?}, len: {}, offset: {}",
fd, base, len, offset fd, base, len, offset
); );
let mut proc = self.process(); 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)?; let len = proc.get_file(fd)?.write_at(offset, slice)?;
Ok(len) 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 proc = self.process();
let timeout_msecs = if timeout.is_null() { let timeout_msecs = if timeout.is_null() {
1 << 31 // infinity 1 << 31 // infinity
} else { } else {
let timeout = unsafe { proc.vm.check_read_ptr(timeout)? }; let timeout = unsafe { self.vm().check_read_ptr(timeout)? };
timeout.to_msec() timeout.to_msec()
}; };
drop(proc); 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() { for poll in polls.iter() {
if proc.files.get(&(poll.fd as usize)).is_none() { if proc.files.get(&(poll.fd as usize)).is_none() {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
@ -148,11 +159,11 @@ impl Syscall<'_> {
); );
let proc = self.process(); let proc = self.process();
let mut read_fds = FdSet::new(&proc.vm, read, nfds)?; let mut read_fds = FdSet::new(&self.vm(), read, nfds)?;
let mut write_fds = FdSet::new(&proc.vm, write, nfds)?; let mut write_fds = FdSet::new(&self.vm(), write, nfds)?;
let mut err_fds = FdSet::new(&proc.vm, err, nfds)?; let mut err_fds = FdSet::new(&self.vm(), err, nfds)?;
let timeout_msecs = if !timeout.is_null() { 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() timeout.to_msec()
} else { } else {
// infinity // infinity
@ -203,7 +214,8 @@ impl Syscall<'_> {
let current_time_ms = crate::trap::uptime_msec(); let current_time_ms = crate::trap::uptime_msec();
// infinity check // 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); return Ok(0);
} }
@ -217,7 +229,7 @@ impl Syscall<'_> {
fd, iov_ptr, iov_count fd, iov_ptr, iov_count
); );
let mut proc = self.process(); 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 // read all data to a buf
let file_like = proc.get_file_like(fd)?; let file_like = proc.get_file_like(fd)?;
@ -237,7 +249,7 @@ impl Syscall<'_> {
fd, iov_ptr, iov_count 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 buf = iovs.read_all_to_vec();
let len = buf.len(); let len = buf.len();
@ -251,9 +263,15 @@ impl Syscall<'_> {
self.sys_openat(AT_FDCWD, path, flags, mode) 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 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); let flags = OpenFlags::from_bits_truncate(flags);
info!( info!(
"openat: dir_fd: {}, path: {:?}, flags: {:?}, mode: {:#o}", "openat: dir_fd: {}, path: {:?}, flags: {:?}, mode: {:#o}",
@ -308,10 +326,16 @@ impl Syscall<'_> {
self.sys_faccessat(AT_FDCWD, path, mode, 0) 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 // TODO: check permissions based on uid/gid
let proc = self.process(); 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); let flags = AtFlags::from_bits_truncate(flags);
if !proc.pid.is_init() { if !proc.pid.is_init() {
// we trust pid 0 process // we trust pid 0 process
@ -320,7 +344,8 @@ impl Syscall<'_> {
dirfd as isize, path, mode, flags 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) Ok(0)
} }
@ -330,7 +355,7 @@ impl Syscall<'_> {
// we trust pid 0 process // we trust pid 0 process
info!("getcwd: buf: {:?}, len: {:#x}", buf, len); 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 { if proc.cwd.len() + 1 > len {
return Err(SysError::ERANGE); return Err(SysError::ERANGE);
} }
@ -345,24 +370,31 @@ impl Syscall<'_> {
pub fn sys_fstat(&mut self, fd: usize, stat_ptr: *mut Stat) -> SysResult { pub fn sys_fstat(&mut self, fd: usize, stat_ptr: *mut Stat) -> SysResult {
info!("fstat: fd: {}, stat_ptr: {:?}", fd, stat_ptr); info!("fstat: fd: {}, stat_ptr: {:?}", fd, stat_ptr);
let mut proc = self.process(); 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 file = proc.get_file(fd)?;
let stat = Stat::from(file.metadata()?); let stat = Stat::from(file.metadata()?);
*stat_ref = stat; *stat_ref = stat;
Ok(0) 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 proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; let path = unsafe { self.vm().check_and_clone_cstr(path)? };
let stat_ref = unsafe { proc.vm.check_write_ptr(stat_ptr)? }; let stat_ref = unsafe { self.vm().check_write_ptr(stat_ptr)? };
let flags = AtFlags::from_bits_truncate(flags); let flags = AtFlags::from_bits_truncate(flags);
info!( info!(
"fstatat: dirfd: {}, path: {:?}, stat_ptr: {:?}, flags: {:?}", "fstatat: dirfd: {}, path: {:?}, stat_ptr: {:?}, flags: {:?}",
dirfd as isize, 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()?); let stat = Stat::from(inode.metadata()?);
*stat_ref = stat; *stat_ref = stat;
Ok(0) Ok(0)
@ -376,10 +408,16 @@ impl Syscall<'_> {
self.sys_readlinkat(AT_FDCWD, path, base, len) 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 proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; let path = unsafe { self.vm().check_and_clone_cstr(path)? };
let slice = unsafe { proc.vm.check_write_array(base, len)? }; let slice = unsafe { self.vm().check_write_array(base, len)? };
info!( info!(
"readlinkat: dirfd: {}, path: {:?}, base: {:?}, len: {}", "readlinkat: dirfd: {}, path: {:?}, base: {:?}, len: {}",
dirfd as isize, 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 { pub fn sys_truncate(&mut self, path: *const u8, len: usize) -> SysResult {
let proc = self.process(); 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); info!("truncate: path: {:?}, len: {}", path, len);
proc.lookup_inode(&path)?.resize(len)?; proc.lookup_inode(&path)?.resize(len)?;
Ok(0) Ok(0)
@ -436,13 +474,18 @@ impl Syscall<'_> {
Ok(0) 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!( info!(
"getdents64: fd: {}, ptr: {:?}, buf_size: {}", "getdents64: fd: {}, ptr: {:?}, buf_size: {}",
fd, buf, buf_size fd, buf, buf_size
); );
let mut proc = self.process(); 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 file = proc.get_file(fd)?;
let info = file.metadata()?; let info = file.metadata()?;
if info.type_ != FileType::Dir { if info.type_ != FileType::Dir {
@ -474,7 +517,14 @@ impl Syscall<'_> {
Ok(fd2) 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!( info!(
"ioctl: fd: {}, request: {:x}, args: {} {} {}", "ioctl: fd: {}, request: {:x}, args: {} {} {}",
fd, request, arg1, arg2, arg3 fd, request, arg1, arg2, arg3
@ -486,7 +536,7 @@ impl Syscall<'_> {
pub fn sys_chdir(&mut self, path: *const u8) -> SysResult { pub fn sys_chdir(&mut self, path: *const u8) -> SysResult {
let mut proc = self.process(); 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() { if !proc.pid.is_init() {
// we trust pid 0 process // we trust pid 0 process
info!("chdir: path: {:?}", path); info!("chdir: path: {:?}", path);
@ -539,8 +589,8 @@ impl Syscall<'_> {
newpath: *const u8, newpath: *const u8,
) -> SysResult { ) -> SysResult {
let mut proc = self.process(); let mut proc = self.process();
let oldpath = unsafe { proc.vm.check_and_clone_cstr(oldpath)? }; let oldpath = unsafe { self.vm().check_and_clone_cstr(oldpath)? };
let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? }; let newpath = unsafe { self.vm().check_and_clone_cstr(newpath)? };
info!( info!(
"renameat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}", "renameat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}",
olddirfd as isize, oldpath, newdirfd as isize, 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 { pub fn sys_mkdirat(&mut self, dirfd: usize, path: *const u8, mode: usize) -> SysResult {
let proc = self.process(); 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 // TODO: check pathname
info!( info!(
"mkdirat: dirfd: {}, path: {:?}, mode: {:#o}", "mkdirat: dirfd: {}, path: {:?}, mode: {:#o}",
@ -578,7 +628,7 @@ impl Syscall<'_> {
pub fn sys_rmdir(&mut self, path: *const u8) -> SysResult { pub fn sys_rmdir(&mut self, path: *const u8) -> SysResult {
let proc = self.process(); 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); info!("rmdir: path: {:?}", path);
let (dir_path, file_name) = split_path(&path); let (dir_path, file_name) = split_path(&path);
@ -604,8 +654,8 @@ impl Syscall<'_> {
flags: usize, flags: usize,
) -> SysResult { ) -> SysResult {
let proc = self.process(); let proc = self.process();
let oldpath = unsafe { proc.vm.check_and_clone_cstr(oldpath)? }; let oldpath = unsafe { self.vm().check_and_clone_cstr(oldpath)? };
let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? }; let newpath = unsafe { self.vm().check_and_clone_cstr(newpath)? };
let flags = AtFlags::from_bits_truncate(flags); let flags = AtFlags::from_bits_truncate(flags);
info!( info!(
"linkat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}, flags: {:?}", "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 { pub fn sys_unlinkat(&mut self, dirfd: usize, path: *const u8, flags: usize) -> SysResult {
let proc = self.process(); 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); let flags = AtFlags::from_bits_truncate(flags);
info!( info!(
"unlinkat: dirfd: {}, path: {:?}, flags: {:?}", "unlinkat: dirfd: {}, path: {:?}, flags: {:?}",
@ -646,7 +696,7 @@ impl Syscall<'_> {
info!("pipe: fds: {:?}", fds); info!("pipe: fds: {:?}", fds);
let mut proc = self.process(); 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, write) = Pipe::create_pair();
let read_fd = proc.add_file(FileLike::File(FileHandle::new( let read_fd = proc.add_file(FileLike::File(FileHandle::new(
@ -701,7 +751,7 @@ impl Syscall<'_> {
let mut buffer = [0u8; 1024]; let mut buffer = [0u8; 1024];
let mut read_offset = if !offset_ptr.is_null() { 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 { } else {
in_file.seek(SeekFrom::Current(0))? as usize in_file.seek(SeekFrom::Current(0))? as usize
}; };

@ -35,16 +35,16 @@ impl Syscall<'_> {
if flags.contains(MmapFlags::FIXED) { if flags.contains(MmapFlags::FIXED) {
// we have to map it to addr, so remove the old mapping first // 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 { } 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::ANONYMOUS) {
if flags.contains(MmapFlags::SHARED) { if flags.contains(MmapFlags::SHARED) {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
proc.vm.push( self.vm().push(
addr, addr,
addr + len, addr + len,
prot.to_attr(), prot.to_attr(),
@ -54,7 +54,7 @@ impl Syscall<'_> {
return Ok(addr); return Ok(addr);
} else { } else {
let inode = proc.get_file(fd)?.inode(); let inode = proc.get_file(fd)?.inode();
proc.vm.push( self.vm().push(
addr, addr,
addr + len, addr + len,
prot.to_attr(), prot.to_attr(),
@ -83,8 +83,8 @@ impl Syscall<'_> {
// FIXME: properly set the attribute of the area // FIXME: properly set the attribute of the area
// now some mut ptr check is fault // now some mut ptr check is fault
let memory_area = proc let vm = self.vm();
.vm let memory_area = vm
.iter() .iter()
.find(|area| area.is_overlap_with(addr, addr + len)); .find(|area| area.is_overlap_with(addr, addr + len));
if memory_area.is_none() { if memory_area.is_none() {
@ -96,7 +96,7 @@ impl Syscall<'_> {
pub fn sys_munmap(&mut self, addr: usize, len: usize) -> SysResult { pub fn sys_munmap(&mut self, addr: usize, len: usize) -> SysResult {
info!("munmap addr={:#x}, size={:#x}", addr, len); info!("munmap addr={:#x}, size={:#x}", addr, len);
let mut proc = self.process(); let mut proc = self.process();
proc.vm.pop_with_split(addr, addr + len); self.vm().pop_with_split(addr, addr + len);
Ok(0) Ok(0)
} }
} }

@ -24,7 +24,7 @@ impl Syscall<'_> {
let offset = 65; let offset = 65;
let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"]; let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"];
let proc = self.process(); 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() { for i in 0..strings.len() {
unsafe { unsafe {
@ -40,7 +40,7 @@ impl Syscall<'_> {
pid, size, mask pid, size, mask
); );
let proc = self.process(); let proc = self.process();
let mask = unsafe { proc.vm.check_write_array(mask, size / size_of::<u32>())? }; let mask = unsafe { self.vm().check_write_array(mask, size / size_of::<u32>())? };
// we only have 4 cpu at most. // we only have 4 cpu at most.
// so just set it. // so just set it.
@ -50,14 +50,20 @@ impl Syscall<'_> {
pub fn sys_sysinfo(&mut self, sys_info: *mut SysInfo) -> SysResult { pub fn sys_sysinfo(&mut self, sys_info: *mut SysInfo) -> SysResult {
let proc = self.process(); 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(); let sysinfo = SysInfo::default();
*sys_info = sysinfo; *sys_info = sysinfo;
Ok(0) 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!( info!(
"futex: [{}] uaddr: {:#x}, op: {:#x}, val: {}, timeout_ptr: {:?}", "futex: [{}] uaddr: {:#x}, op: {:#x}, val: {}, timeout_ptr: {:?}",
thread::current().id(), thread::current().id(),
@ -73,11 +79,11 @@ impl Syscall<'_> {
if uaddr % size_of::<u32>() != 0 { if uaddr % size_of::<u32>() != 0 {
return Err(SysError::EINVAL); 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() { let _timeout = if timeout.is_null() {
None None
} else { } else {
Some(unsafe { *self.process().vm.check_read_ptr(timeout)? }) Some(unsafe { *self.vm().check_read_ptr(timeout)? })
}; };
const OP_WAIT: u32 = 0; const OP_WAIT: u32 = 0;
@ -132,7 +138,7 @@ impl Syscall<'_> {
match resource { match resource {
RLIMIT_STACK => { RLIMIT_STACK => {
if !old_limit.is_null() { 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 { *old_limit = RLimit {
cur: USER_STACK_SIZE as u64, cur: USER_STACK_SIZE as u64,
max: USER_STACK_SIZE as u64, max: USER_STACK_SIZE as u64,
@ -142,7 +148,7 @@ impl Syscall<'_> {
} }
RLIMIT_NOFILE => { RLIMIT_NOFILE => {
if !old_limit.is_null() { 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 { *old_limit = RLimit {
cur: 1024, cur: 1024,
max: 1024, max: 1024,
@ -152,7 +158,7 @@ impl Syscall<'_> {
} }
RLIMIT_RSS | RLIMIT_AS => { RLIMIT_RSS | RLIMIT_AS => {
if !old_limit.is_null() { 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 // 1GB
*old_limit = RLimit { *old_limit = RLimit {
cur: 1024 * 1024 * 1024, cur: 1024 * 1024 * 1024,
@ -168,7 +174,7 @@ impl Syscall<'_> {
pub fn sys_getrandom(&mut self, buf: *mut u8, len: usize, flag: u32) -> SysResult { pub fn sys_getrandom(&mut self, buf: *mut u8, len: usize, flag: u32) -> SysResult {
//info!("getrandom: buf: {:?}, len: {:?}, falg {:?}", buf, len,flag); //info!("getrandom: buf: {:?}, len: {:?}, falg {:?}", buf, len,flag);
let mut proc = self.process(); 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; let mut i = 0;
for elm in slice { for elm in slice {
unsafe { unsafe {

@ -10,8 +10,9 @@ use rcore_memory::VMError;
use crate::arch::cpu; use crate::arch::cpu;
use crate::arch::interrupt::TrapFrame; use crate::arch::interrupt::TrapFrame;
use crate::arch::syscall::*; use crate::arch::syscall::*;
use crate::memory::MemorySet;
use crate::process::*; use crate::process::*;
use crate::sync::{Condvar, SpinNoIrq, MutexGuard}; use crate::sync::{Condvar, MutexGuard, SpinNoIrq};
use crate::thread; use crate::thread;
use crate::util; use crate::util;
@ -58,6 +59,11 @@ impl Syscall<'_> {
self.thread.proc.lock() self.thread.proc.lock()
} }
/// Get current virtual memory
pub fn vm(&self) -> MutexGuard<'_, MemorySet, SpinNoIrq> {
self.thread.vm.lock()
}
/// System call dispatcher /// System call dispatcher
// This #[deny(unreachable_patterns)] checks if each match arm is defined // This #[deny(unreachable_patterns)] checks if each match arm is defined
// See discussion in https://github.com/oscourse-tsinghua/rcore_plus/commit/17e644e54e494835f1a49b34b80c2c4f15ed0dbe. // 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_OPENAT => self.sys_openat(args[0], args[1] as *const u8, args[2], args[3]),
SYS_CLOSE => self.sys_close(args[0]), SYS_CLOSE => self.sys_close(args[0]),
SYS_FSTAT => self.sys_fstat(args[0], args[1] as *mut Stat), 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_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_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]), 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_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_GETCWD => self.sys_getcwd(args[0] as *mut u8, args[1]),
SYS_CHDIR => self.sys_chdir(args[0] as *const u8), 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_MKDIRAT => self.sys_mkdirat(args[0], args[1] as *const u8, args[2]),
SYS_LINKAT => self.sys_linkat( SYS_LINKAT => self.sys_linkat(
args[0], args[0],
@ -124,7 +134,9 @@ impl Syscall<'_> {
SYS_UTIMENSAT => self.unimplemented("utimensat", Ok(0)), SYS_UTIMENSAT => self.unimplemented("utimensat", Ok(0)),
// io multiplexing // 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)), SYS_EPOLL_CREATE1 => self.unimplemented("epoll_create1", Err(SysError::ENOSYS)),
// file system // file system
@ -149,7 +161,9 @@ impl Syscall<'_> {
// schedule // schedule
SYS_SCHED_YIELD => self.sys_yield(), 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 // socket
SYS_SOCKET => self.sys_socket(args[0], args[1], args[2]), 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_SHUTDOWN => self.sys_shutdown(args[0], args[1]),
SYS_BIND => self.sys_bind(args[0], args[1] as *const SockAddr, args[2]), SYS_BIND => self.sys_bind(args[0], args[1] as *const SockAddr, args[2]),
SYS_LISTEN => self.sys_listen(args[0], args[1]), 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_GETSOCKNAME => {
SYS_GETPEERNAME => self.sys_getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), self.sys_getsockname(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_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( SYS_GETSOCKOPT => self.sys_getsockopt(
args[0], args[0],
args[1], args[1],
@ -215,7 +235,9 @@ impl Syscall<'_> {
// time // time
SYS_NANOSLEEP => self.sys_nanosleep(args[0] as *const TimeSpec), SYS_NANOSLEEP => self.sys_nanosleep(args[0] as *const TimeSpec),
SYS_SETITIMER => self.unimplemented("setitimer", Ok(0)), 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), SYS_CLOCK_GETTIME => self.sys_clock_gettime(args[0], args[1] as *mut TimeSpec),
// system // system
@ -256,9 +278,13 @@ impl Syscall<'_> {
// custom // custom
SYS_MAP_PCI_DEVICE => self.sys_map_pci_device(args[0], args[1]), 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.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)), SYS_TKILL => self.unimplemented("tkill", Ok(0)),
_ => { _ => {
let ret = match () { let ret = match () {
@ -306,7 +332,7 @@ impl Syscall<'_> {
} }
#[cfg(target_arch = "mips")] #[cfg(target_arch = "mips")]
fn mips_syscall(&mut self, id: usize, args: [usize; 6],) -> Option<SysResult> { fn mips_syscall(&mut self, id: usize, args: [usize; 6]) -> Option<SysResult> {
let ret = match id { let ret = match id {
SYS_OPEN => self.sys_open(args[0] as *const u8, args[1], args[2]), 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]), SYS_POLL => self.sys_poll(args[0] as *mut PollFd, args[1], args[2]),

@ -3,6 +3,7 @@
use super::fs::IoVecs; use super::fs::IoVecs;
use super::*; use super::*;
use crate::fs::FileLike; use crate::fs::FileLike;
use crate::memory::MemorySet;
use crate::net::{ use crate::net::{
Endpoint, LinkLevelEndpoint, NetlinkEndpoint, NetlinkSocketState, PacketSocketState, Endpoint, LinkLevelEndpoint, NetlinkEndpoint, NetlinkSocketState, PacketSocketState,
RawSocketState, Socket, TcpSocketState, UdpSocketState, SOCKETS, RawSocketState, Socket, TcpSocketState, UdpSocketState, SOCKETS,
@ -12,7 +13,6 @@ use alloc::boxed::Box;
use core::cmp::min; use core::cmp::min;
use core::mem::size_of; use core::mem::size_of;
use smoltcp::wire::*; use smoltcp::wire::*;
use crate::memory::MemorySet;
impl Syscall<'_> { impl Syscall<'_> {
pub fn sys_socket(&mut self, domain: usize, socket_type: usize, protocol: usize) -> SysResult { pub fn sys_socket(&mut self, domain: usize, socket_type: usize, protocol: usize) -> SysResult {
@ -57,7 +57,7 @@ impl Syscall<'_> {
fd, level, optname fd, level, optname
); );
let mut proc = self.process(); 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)?; let socket = proc.get_socket(fd)?;
socket.setsockopt(level, optname, data) socket.setsockopt(level, optname, data)
} }
@ -75,17 +75,17 @@ impl Syscall<'_> {
fd, level, optname, optval, optlen fd, level, optname, optval, optlen
); );
let proc = self.process(); let proc = self.process();
let optlen = unsafe { proc.vm.check_write_ptr(optlen)? }; let optlen = unsafe { self.vm().check_write_ptr(optlen)? };
match level { match level {
SOL_SOCKET => match optname { SOL_SOCKET => match optname {
SO_SNDBUF => { 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; *optval = crate::net::TCP_SENDBUF as u32;
*optlen = 4; *optlen = 4;
Ok(0) Ok(0)
} }
SO_RCVBUF => { 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; *optval = crate::net::TCP_RECVBUF as u32;
*optlen = 4; *optlen = 4;
Ok(0) Ok(0)
@ -107,7 +107,7 @@ impl Syscall<'_> {
); );
let mut proc = self.process(); 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)?; let socket = proc.get_socket(fd)?;
socket.connect(endpoint)?; socket.connect(endpoint)?;
Ok(0) Ok(0)
@ -129,11 +129,11 @@ impl Syscall<'_> {
let mut proc = self.process(); 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() { let endpoint = if addr.is_null() {
None None
} else { } 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); info!("sys_sendto: sending to endpoint {:?}", endpoint);
Some(endpoint) Some(endpoint)
}; };
@ -157,14 +157,14 @@ impl Syscall<'_> {
let mut proc = self.process(); 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 socket = proc.get_socket(fd)?;
let (result, endpoint) = socket.read(&mut slice); let (result, endpoint) = socket.read(&mut slice);
if result.is_ok() && !addr.is_null() { if result.is_ok() && !addr.is_null() {
let sockaddr_in = SockAddr::from(endpoint); let sockaddr_in = SockAddr::from(endpoint);
unsafe { 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 { pub fn sys_recvmsg(&mut self, fd: usize, msg: *mut MsgHdr, flags: usize) -> SysResult {
info!("recvmsg: fd: {}, msg: {:?}, flags: {}", fd, msg, flags); info!("recvmsg: fd: {}, msg: {:?}, flags: {}", fd, msg, flags);
let mut proc = self.process(); let mut proc = self.process();
let hdr = unsafe { proc.vm.check_write_ptr(msg)? }; let hdr = unsafe { self.vm().check_write_ptr(msg)? };
let mut iovs = unsafe { IoVecs::check_and_new(hdr.msg_iov, hdr.msg_iovlen, &proc.vm, true)? }; 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 mut buf = iovs.new_buf(true);
let socket = proc.get_socket(fd)?; let socket = proc.get_socket(fd)?;
@ -186,7 +187,7 @@ impl Syscall<'_> {
iovs.write_all_from_slice(&buf[..len]); iovs.write_all_from_slice(&buf[..len]);
let sockaddr_in = SockAddr::from(endpoint); let sockaddr_in = SockAddr::from(endpoint);
unsafe { 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 result
@ -196,7 +197,7 @@ impl Syscall<'_> {
info!("sys_bind: fd: {} addr: {:?} len: {}", fd, addr, addr_len); info!("sys_bind: fd: {} addr: {:?} len: {}", fd, addr, addr_len);
let mut proc = self.process(); 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); info!("sys_bind: fd: {} bind to {:?}", fd, endpoint);
let socket = proc.get_socket(fd)?; let socket = proc.get_socket(fd)?;
@ -238,13 +239,18 @@ impl Syscall<'_> {
if !addr.is_null() { if !addr.is_null() {
let sockaddr_in = SockAddr::from(remote_endpoint); let sockaddr_in = SockAddr::from(remote_endpoint);
unsafe { unsafe {
sockaddr_in.write_to(&mut proc, addr, addr_len)?; sockaddr_in.write_to(&mut self.vm(), addr, addr_len)?;
} }
} }
Ok(new_fd) 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!( info!(
"sys_getsockname: fd: {} addr: {:?} addr_len: {:?}", "sys_getsockname: fd: {} addr: {:?} addr_len: {:?}",
fd, addr, addr_len fd, addr, addr_len
@ -260,12 +266,17 @@ impl Syscall<'_> {
let endpoint = socket.endpoint().ok_or(SysError::EINVAL)?; let endpoint = socket.endpoint().ok_or(SysError::EINVAL)?;
let sockaddr_in = SockAddr::from(endpoint); let sockaddr_in = SockAddr::from(endpoint);
unsafe { unsafe {
sockaddr_in.write_to(&mut proc, addr, addr_len)?; sockaddr_in.write_to(&mut self.vm(), addr, addr_len)?;
} }
Ok(0) 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!( info!(
"sys_getpeername: fd: {} addr: {:?} addr_len: {:?}", "sys_getpeername: fd: {} addr: {:?} addr_len: {:?}",
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 remote_endpoint = socket.remote_endpoint().ok_or(SysError::EINVAL)?;
let sockaddr_in = SockAddr::from(remote_endpoint); let sockaddr_in = SockAddr::from(remote_endpoint);
unsafe { unsafe {
sockaddr_in.write_to(&mut proc, addr, addr_len)?; sockaddr_in.write_to(&mut self.vm(), addr, addr_len)?;
} }
Ok(0) Ok(0)
} }
@ -405,12 +416,12 @@ fn sockaddr_to_endpoint(
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
let addr = unsafe { vm.check_read_ptr(addr)? }; let addr = unsafe { vm.check_read_ptr(addr)? };
if len < addr.len()? {
return Err(SysError::EINVAL);
}
unsafe { unsafe {
match AddressFamily::from(addr.family) { match AddressFamily::from(addr.family) {
AddressFamily::Internet => { AddressFamily::Internet => {
if len < size_of::<SockAddrIn>() {
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( 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()[..],
@ -419,17 +430,11 @@ fn sockaddr_to_endpoint(
} }
AddressFamily::Unix => Err(SysError::EINVAL), AddressFamily::Unix => Err(SysError::EINVAL),
AddressFamily::Packet => { AddressFamily::Packet => {
if len < size_of::<SockAddrLl>() {
return Err(SysError::EINVAL);
}
Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new( Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new(
addr.addr_ll.sll_ifindex as usize, addr.addr_ll.sll_ifindex as usize,
))) )))
} }
AddressFamily::Netlink => { AddressFamily::Netlink => {
if len < size_of::<SockAddrNl>() {
return Err(SysError::EINVAL);
}
Ok(Endpoint::Netlink(NetlinkEndpoint::new( Ok(Endpoint::Netlink(NetlinkEndpoint::new(
addr.addr_nl.nl_pid, addr.addr_nl.nl_pid,
addr.addr_nl.nl_groups, addr.addr_nl.nl_groups,
@ -441,11 +446,21 @@ fn sockaddr_to_endpoint(
} }
impl SockAddr { impl SockAddr {
fn len(&self) -> Result<usize, SysError> {
match AddressFamily::from(unsafe { self.family }) {
AddressFamily::Internet => Ok(size_of::<SockAddrIn>()),
AddressFamily::Packet => Ok(size_of::<SockAddrLl>()),
AddressFamily::Netlink => Ok(size_of::<SockAddrNl>()),
AddressFamily::Unix => Err(SysError::EINVAL),
_ => Err(SysError::EINVAL),
}
}
/// Write to user sockaddr /// Write to user sockaddr
/// Check mutability for user /// Check mutability for user
unsafe fn write_to( unsafe fn write_to(
self, self,
proc: &mut Process, vm: &MemorySet,
addr: *mut SockAddr, addr: *mut SockAddr,
addr_len: *mut u32, addr_len: *mut u32,
) -> SysResult { ) -> SysResult {
@ -454,19 +469,13 @@ impl SockAddr {
return Ok(0); 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 max_addr_len = *addr_len as usize;
let full_len = match AddressFamily::from(self.family) { let full_len = self.len()?;
AddressFamily::Internet => size_of::<SockAddrIn>(),
AddressFamily::Packet => size_of::<SockAddrLl>(),
AddressFamily::Netlink => size_of::<SockAddrNl>(),
AddressFamily::Unix => return Err(SysError::EINVAL),
_ => return Err(SysError::EINVAL),
};
let written_len = min(max_addr_len, full_len); let written_len = min(max_addr_len, full_len);
if written_len > 0 { 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); let source = slice::from_raw_parts(&self as *const SockAddr as *const u8, written_len);
target.copy_from_slice(source); target.copy_from_slice(source);
} }

@ -49,8 +49,8 @@ impl Syscall<'_> {
); );
//return Err(SysError::ENOSYS); //return Err(SysError::ENOSYS);
} }
let parent_tid_ref = unsafe { self.process().vm.check_write_ptr(parent_tid)? }; let parent_tid_ref = unsafe { self.vm().check_write_ptr(parent_tid)? };
let child_tid_ref = unsafe { self.process().vm.check_write_ptr(child_tid)? }; let child_tid_ref = unsafe { self.vm().check_write_ptr(child_tid)? };
let new_thread = self let new_thread = self
.thread .thread
.clone(self.tf, newsp, newtls, child_tid as usize); .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 { pub fn sys_wait4(&mut self, pid: isize, wstatus: *mut i32) -> SysResult {
//info!("wait4: pid: {}, code: {:?}", pid, wstatus); //info!("wait4: pid: {}, code: {:?}", pid, wstatus);
let wstatus = if !wstatus.is_null() { let wstatus = if !wstatus.is_null() {
Some(unsafe { self.process().vm.check_write_ptr(wstatus)? }) Some(unsafe { self.vm().check_write_ptr(wstatus)? })
} else { } else {
None None
}; };
@ -150,9 +150,9 @@ impl Syscall<'_> {
path, argv, envp path, argv, envp
); );
let mut proc = self.process(); 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 args = unsafe { proc.vm.check_and_clone_cstr_array(argv)? }; let args = unsafe { self.vm().check_and_clone_cstr_array(argv)? };
let envs = unsafe { proc.vm.check_and_clone_cstr_array(envp)? }; let envs = unsafe { self.vm().check_and_clone_cstr_array(envp)? };
if args.is_empty() { if args.is_empty() {
error!("exec: args is null"); error!("exec: args is null");
@ -180,9 +180,9 @@ impl Syscall<'_> {
Thread::new_user_vm(&inode, &path, args, envs).map_err(|_| SysError::EINVAL)?; Thread::new_user_vm(&inode, &path, args, envs).map_err(|_| SysError::EINVAL)?;
// Activate new page table // Activate new page table
core::mem::swap(&mut proc.vm, &mut vm); core::mem::swap(&mut *self.vm(), &mut vm);
unsafe { unsafe {
proc.vm.activate(); self.vm().activate();
} }
// Modify exec path // Modify exec path
@ -289,7 +289,7 @@ impl Syscall<'_> {
let clear_child_tid = self.thread.clear_child_tid as *mut u32; let clear_child_tid = self.thread.clear_child_tid as *mut u32;
if !clear_child_tid.is_null() { if !clear_child_tid.is_null() {
info!("exit: futex {:#?} wake 1", clear_child_tid); 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; *clear_child_tid_ref = 0;
let queue = proc.get_futex(clear_child_tid as usize); let queue = proc.get_futex(clear_child_tid as usize);
queue.notify_one(); queue.notify_one();
@ -328,7 +328,7 @@ impl Syscall<'_> {
} }
pub fn sys_nanosleep(&mut self, req: *const TimeSpec) -> SysResult { 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); info!("nanosleep: time: {:#?}", time);
// TODO: handle spurious wakeup // TODO: handle spurious wakeup
thread::sleep(time.to_duration()); thread::sleep(time.to_duration());

@ -13,7 +13,7 @@ impl Syscall<'_> {
} }
let proc = self.process(); 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(); let timeval = TimeVal::get_epoch();
*tv = timeval; *tv = timeval;
@ -24,7 +24,7 @@ impl Syscall<'_> {
info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts); info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts);
let proc = self.process(); 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(); let timespec = TimeSpec::get_epoch();
*ts = timespec; *ts = timespec;
@ -35,7 +35,7 @@ impl Syscall<'_> {
let sec = get_epoch_usec() / USEC_PER_SEC; let sec = get_epoch_usec() / USEC_PER_SEC;
if time as usize != 0 { if time as usize != 0 {
let proc = self.process(); 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; *time = sec as u64;
} }
Ok(sec as usize) Ok(sec as usize)
@ -44,7 +44,7 @@ impl Syscall<'_> {
pub fn sys_getrusage(&mut self, who: usize, rusage: *mut RUsage) -> SysResult { pub fn sys_getrusage(&mut self, who: usize, rusage: *mut RUsage) -> SysResult {
info!("getrusage: who: {}, rusage: {:?}", who, rusage); info!("getrusage: who: {}, rusage: {:?}", who, rusage);
let proc = self.process(); 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_base = *TICK_BASE;
let tick = unsafe { crate::trap::TICK as u64 }; let tick = unsafe { crate::trap::TICK as u64 };
@ -67,7 +67,7 @@ impl Syscall<'_> {
pub fn sys_times(&mut self, buf: *mut Tms) -> SysResult { pub fn sys_times(&mut self, buf: *mut Tms) -> SysResult {
info!("times: buf: {:?}", buf); info!("times: buf: {:?}", buf);
let proc = self.process(); 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_base = *TICK_BASE;
let tick = unsafe { crate::trap::TICK as u64 }; let tick = unsafe { crate::trap::TICK as u64 };

Loading…
Cancel
Save