From 132bc629fae698834d450bc0bf442b9216820525 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sat, 2 Mar 2019 17:26:50 +0800 Subject: [PATCH 1/4] fix bad address error code to EFAULT --- kernel/src/syscall/fs.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 4e38c13..d6e8608 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -12,7 +12,7 @@ pub fn sys_read(fd: usize, base: *mut u8, len: usize) -> SysResult { info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len); let mut proc = process(); if !proc.memory_set.check_mut_array(base, len) { - return Err(SysError::EINVAL); + return Err(SysError::EFAULT); } let slice = unsafe { slice::from_raw_parts_mut(base, len) }; let len = proc.get_file(fd)?.read(slice)?; @@ -23,7 +23,7 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult { info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len); let mut proc = process(); if !proc.memory_set.check_array(base, len) { - return Err(SysError::EINVAL); + return Err(SysError::EFAULT); } match proc.files.get(&fd) { Some(FileLike::File(_)) => sys_write_file(&mut proc, fd, base, len), @@ -66,7 +66,7 @@ pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResu pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult { let mut proc = process(); let path = unsafe { proc.memory_set.check_and_clone_cstr(path) } - .ok_or(SysError::EINVAL)?; + .ok_or(SysError::EFAULT)?; let flags = OpenFlags::from_bits_truncate(flags); info!("open: path: {:?}, flags: {:?}, mode: {:#o}", path, flags, mode); @@ -124,7 +124,7 @@ pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult { info!("fstat: fd: {}", fd); let mut proc = process(); if !proc.memory_set.check_mut_ptr(stat_ptr) { - return Err(SysError::EINVAL); + return Err(SysError::EFAULT); } let file = proc.get_file(fd)?; let stat = Stat::from(file.info()?); @@ -136,9 +136,9 @@ pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult { pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult { let mut proc = process(); let path = unsafe { proc.memory_set.check_and_clone_cstr(path) } - .ok_or(SysError::EINVAL)?; + .ok_or(SysError::EFAULT)?; if !proc.memory_set.check_mut_ptr(stat_ptr) { - return Err(SysError::EINVAL); + return Err(SysError::EFAULT); } info!("lstat: path: {}", path); @@ -167,7 +167,7 @@ pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> Sy info!("getdents64: fd: {}, ptr: {:?}, buf_size: {}", fd, buf, buf_size); let mut proc = process(); if !proc.memory_set.check_mut_array(buf as *mut u8, buf_size) { - return Err(SysError::EINVAL); + return Err(SysError::EFAULT); } let file = proc.get_file(fd)?; let info = file.info()?; @@ -466,14 +466,14 @@ struct IoVecs(Vec<&'static mut [u8]>); impl IoVecs { fn check_and_new(iov_ptr: *const IoVec, iov_count: usize, vm: &MemorySet, readv: bool) -> Result { if !vm.check_array(iov_ptr, iov_count) { - return Err(SysError::EINVAL); + return Err(SysError::EFAULT); } let iovs = unsafe { slice::from_raw_parts(iov_ptr, iov_count) }.to_vec(); // check all bufs in iov for iov in iovs.iter() { if readv && !vm.check_mut_array(iov.base, iov.len as usize) || !readv && !vm.check_array(iov.base, iov.len as usize) { - return Err(SysError::EINVAL); + return Err(SysError::EFAULT); } } let slices = iovs.iter().map(|iov| unsafe { slice::from_raw_parts_mut(iov.base, iov.len as usize) }).collect(); From a979b6b5ec35d82d6cfedfc00cc3ac8540110aec Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sat, 2 Mar 2019 19:09:39 +0800 Subject: [PATCH 2/4] impl sys_getppid. fix checking pointer for process syscalls --- crate/thread/src/thread_pool.rs | 3 +++ kernel/src/syscall/mod.rs | 2 +- kernel/src/syscall/proc.rs | 37 +++++++++++++++++++++++---------- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/crate/thread/src/thread_pool.rs b/crate/thread/src/thread_pool.rs index 2f2bacd..3d464a7 100644 --- a/crate/thread/src/thread_pool.rs +++ b/crate/thread/src/thread_pool.rs @@ -198,6 +198,9 @@ impl ThreadPool { pub fn get_children(&self, tid: Tid) -> Vec { self.threads[tid].lock().as_ref().expect("process not exist").children.clone() } + pub fn get_parent(&self, tid: Tid) -> Tid { + self.threads[tid].lock().as_ref().expect("process not exist").parent + } pub fn exit(&self, tid: Tid, code: ExitCode) { // NOTE: if `tid` is running, status change will be deferred. diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 5c31dc2..d04d96f 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -50,7 +50,6 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { // 034 => sys_pause(), 035 => sys_sleep(args[0]), // TODO: nanosleep 039 => sys_getpid(), -// 040 => sys_getppid(), 041 => sys_socket(args[0], args[1], args[2]), 042 => sys_connect(args[0], args[1] as *const u8, args[2]), // 043 => sys_accept(), @@ -82,6 +81,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { 096 => sys_get_time(), // TODO: sys_gettimeofday // 097 => sys_getrlimit(), // 098 => sys_getrusage(), + 110 => sys_getppid(), // 133 => sys_mknod(), 141 => sys_set_priority(args[0]), // 160 => sys_setrlimit(), diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index 8a61025..de43834 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -13,7 +13,9 @@ pub fn sys_fork(tf: &TrapFrame) -> SysResult { /// Wait the process exit. /// Return the PID. Store exit code to `code` if it's not null. pub fn sys_wait(pid: usize, code: *mut i32) -> SysResult { - // TODO: check ptr + if !process().memory_set.check_mut_ptr(code) { + return Err(SysError::EFAULT); + } loop { use alloc::vec; let wait_procs = match pid { @@ -49,19 +51,25 @@ pub fn sys_wait(pid: usize, code: *mut i32) -> SysResult { } pub fn sys_exec(name: *const u8, argc: usize, argv: *const *const u8, tf: &mut TrapFrame) -> SysResult { - // TODO: check ptr - let name = if name.is_null() { "" } else { unsafe { util::from_cstr(name) } }; - info!("exec: {:?}, argc: {}, argv: {:?}", name, argc, argv); - // Copy args to kernel - let args: Vec = unsafe { - slice::from_raw_parts(argv, argc).iter() - .map(|&arg| String::from(util::from_cstr(arg))) - .collect() + let proc = process(); + let name = if name.is_null() { String::from("") } else { + unsafe { proc.memory_set.check_and_clone_cstr(name) } + .ok_or(SysError::EFAULT)? }; - - if args.len() <= 0 { + if argc <= 0 { return Err(SysError::EINVAL); } + // Check and copy args to kernel + let mut args = Vec::new(); + unsafe { + for &ptr in slice::from_raw_parts(argv, argc) { + let arg = proc.memory_set.check_and_clone_cstr(ptr) + .ok_or(SysError::EFAULT)?; + args.push(arg); + } + } + info!("exec: name: {:?}, args: {:?}", name, args); + // Read program file let path = args[0].as_str(); let inode = crate::fs::ROOT_INODE.lookup(path)?; @@ -107,6 +115,13 @@ pub fn sys_getpid() -> SysResult { Ok(thread::current().id() as isize) } +/// Get the parent process id +pub fn sys_getppid() -> SysResult { + let pid = thread::current().id(); + let ppid = processor().manager().get_parent(pid); + Ok(ppid as isize) +} + /// Exit the current process pub fn sys_exit(exit_code: isize) -> ! { let pid = thread::current().id(); From 451fe6b192923b193609c8c7d877e3723ebe75b6 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sat, 2 Mar 2019 21:25:36 +0800 Subject: [PATCH 3/4] impl sys_chdir, sys_rename, sys_mkdir --- kernel/src/syscall/fs.rs | 80 +++++++++++++++++++++++++++++++++++---- kernel/src/syscall/mod.rs | 10 +++-- 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index eb10ecd..58f5ad3 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -72,11 +72,8 @@ pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult { let inode = if flags.contains(OpenFlags::CREATE) { - // FIXME: assume path start from root now - let mut split = path.as_str().rsplitn(2, '/'); - let file_name = split.next().unwrap(); - let dir_path = split.next().unwrap_or("."); - let dir_inode = ROOT_INODE.lookup(dir_path)?; + let (dir_path, file_name) = split_path(&path); + let dir_inode = proc.lookup_inode(dir_path)?; match dir_inode.find(file_name) { Ok(file_inode) => { if flags.contains(OpenFlags::EXCLUSIVE) { @@ -94,7 +91,7 @@ pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult { match path.as_str() { "stdin:" => crate::fs::STDIN.clone() as Arc, "stdout:" => crate::fs::STDOUT.clone() as Arc, - _ => ROOT_INODE.lookup(path.as_str())?, + _ => proc.lookup_inode(&path)?, } }; @@ -157,7 +154,7 @@ pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult { } info!("lstat: path: {}", path); - let inode = ROOT_INODE.lookup(path.as_str())?; + let inode = proc.lookup_inode(&path)?; let stat = Stat::from(inode.metadata()?); unsafe { stat_ptr.write(stat); } Ok(0) @@ -195,7 +192,8 @@ pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> Sy Err(FsError::EntryNotFound) => break, r => r, }?; - let ok = writer.try_write(0, 0, name.as_str()); + // TODO: get ino from dirent + let ok = writer.try_write(0, 0, &name); if !ok { break; } } Ok(writer.written_size as isize) @@ -212,6 +210,59 @@ pub fn sys_dup2(fd1: usize, fd2: usize) -> SysResult { Ok(0) } +pub fn sys_chdir(path: *const u8) -> SysResult { + let mut proc = process(); + let path = unsafe { proc.memory_set.check_and_clone_cstr(path) } + .ok_or(SysError::EFAULT)?; + info!("chdir: path: {:?}", path); + + let inode = proc.lookup_inode(&path)?; + let info = inode.metadata()?; + if info.type_ != FileType::Dir { + return Err(SysError::ENOTDIR); + } + // FIXME: calculate absolute path of new cwd + proc.cwd += &path; + Ok(0) +} + +pub fn sys_rename(oldpath: *const u8, newpath: *const u8) -> SysResult { + let mut proc = process(); + let oldpath = unsafe { proc.memory_set.check_and_clone_cstr(oldpath) } + .ok_or(SysError::EFAULT)?; + let newpath = unsafe { proc.memory_set.check_and_clone_cstr(newpath) } + .ok_or(SysError::EFAULT)?; + info!("rename: oldpath: {:?}, newpath: {:?}", oldpath, newpath); + + let (old_dir_path, old_file_name) = split_path(&oldpath); + let (new_dir_path, new_file_name) = split_path(&newpath); + let old_dir_inode = proc.lookup_inode(old_dir_path)?; + let new_dir_inode = proc.lookup_inode(new_dir_path)?; + // TODO: merge `rename` and `move` in VFS + if Arc::ptr_eq(&old_dir_inode, &new_dir_inode) { + old_dir_inode.rename(old_file_name, new_file_name)?; + } else { + old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?; + } + Ok(0) +} + +pub fn sys_mkdir(path: *const u8, mode: usize) -> SysResult { + let mut proc = process(); + let path = unsafe { proc.memory_set.check_and_clone_cstr(path) } + .ok_or(SysError::EFAULT)?; + // TODO: check pathname + info!("mkdir: path: {:?}, mode: {:#o}", path, mode); + + let (dir_path, file_name) = split_path(&path); + let inode = proc.lookup_inode(dir_path)?; + if inode.find(file_name).is_ok() { + return Err(SysError::EEXIST); + } + inode.create(file_name, FileType::Dir, mode as u32)?; + Ok(0) +} + impl Process { fn get_file(&mut self, fd: usize) -> Result<&mut FileHandle, SysError> { @@ -222,6 +273,19 @@ impl Process { } }) } + fn lookup_inode(&self, path: &str) -> Result, SysError> { + let cwd = self.cwd.split_at(1).1; // skip start '/' + let inode = ROOT_INODE.lookup(cwd)?.lookup(path)?; + Ok(inode) + } +} + +/// Split a `path` str to `(base_path, file_name)` +fn split_path(path: &str) -> (&str, &str) { + let mut split = path.trim_end_matches('/').rsplitn(2, '/'); + let file_name = split.next().unwrap(); + let dir_path = split.next().unwrap_or("."); + (dir_path, file_name) } impl From for SysError { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 1bf6cc9..b082cc1 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -73,9 +73,9 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { // 076 => sys_trunc(), // 077 => sys_ftrunc(), 079 => sys_getcwd(args[0] as *mut u8, args[1]), -// 080 => sys_chdir(), -// 082 => sys_rename(), -// 083 => sys_mkdir(), + 080 => sys_chdir(args[0] as *const u8), + 082 => sys_rename(args[0] as *const u8, args[1] as *const u8), + 083 => sys_mkdir(args[0] as *const u8, args[1]), // 086 => sys_link(), // 087 => sys_unlink(), 096 => sys_get_time(), // TODO: sys_gettimeofday @@ -117,6 +117,10 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { warn!("sys_fcntl is unimplemented"); Ok(0) } + 095 => { + warn!("sys_umask is unimplemented"); + Ok(0o777) + } 102 => { warn!("sys_getuid is unimplemented"); Ok(0) From 0fd24ff92e30f34d19d6161641de7b98214c2106 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sat, 2 Mar 2019 23:16:11 +0800 Subject: [PATCH 4/4] impl sys_f(data)sync, sys_(f)truncate, sys_(un)link --- kernel/src/fs/file.rs | 19 ++++++++++++- kernel/src/syscall/fs.rs | 57 +++++++++++++++++++++++++++++++++++++-- kernel/src/syscall/mod.rs | 11 ++++---- 3 files changed, 79 insertions(+), 8 deletions(-) diff --git a/kernel/src/fs/file.rs b/kernel/src/fs/file.rs index f10a3af..b599911 100644 --- a/kernel/src/fs/file.rs +++ b/kernel/src/fs/file.rs @@ -66,7 +66,24 @@ impl FileHandle { Ok(self.offset) } - pub fn info(&self) -> Result { + pub fn set_len(&mut self, len: u64) -> Result<()> { + if !self.options.write { + return Err(FsError::InvalidParam); // FIXME: => EBADF + } + self.inode.resize(len as usize)?; + Ok(()) + } + + pub fn sync_all(&mut self) -> Result<()> { + self.inode.sync() + } + + pub fn sync_data(&mut self) -> Result<()> { + // TODO: add sync_data to VFS + self.inode.sync() + } + + pub fn metadata(&self) -> Result { self.inode.metadata() } diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 58f5ad3..331a213 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -139,7 +139,7 @@ pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult { return Err(SysError::EFAULT); } let file = proc.get_file(fd)?; - let stat = Stat::from(file.info()?); + let stat = Stat::from(file.metadata()?); // TODO: handle symlink unsafe { stat_ptr.write(stat); } Ok(0) @@ -175,6 +175,33 @@ pub fn sys_lseek(fd: usize, offset: i64, whence: u8) -> SysResult { Ok(offset as isize) } +pub fn sys_fsync(fd: usize) -> SysResult { + info!("fsync: fd: {}", fd); + process().get_file(fd)?.sync_all()?; + Ok(0) +} + +pub fn sys_fdatasync(fd: usize) -> SysResult { + info!("fdatasync: fd: {}", fd); + process().get_file(fd)?.sync_data()?; + Ok(0) +} + +pub fn sys_truncate(path: *const u8, len: usize) -> SysResult { + let mut proc = process(); + let path = unsafe { proc.memory_set.check_and_clone_cstr(path) } + .ok_or(SysError::EFAULT)?; + info!("truncate: path: {:?}, len: {}", path, len); + proc.lookup_inode(&path)?.resize(len)?; + Ok(0) +} + +pub fn sys_ftruncate(fd: usize, len: usize) -> SysResult { + info!("ftruncate: fd: {}, len: {}", fd, len); + process().get_file(fd)?.set_len(len as u64)?; + Ok(0) +} + pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> SysResult { info!("getdents64: fd: {}, ptr: {:?}, buf_size: {}", fd, buf, buf_size); let mut proc = process(); @@ -182,7 +209,7 @@ pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> Sy return Err(SysError::EFAULT); } let file = proc.get_file(fd)?; - let info = file.info()?; + let info = file.metadata()?; if info.type_ != FileType::Dir { return Err(SysError::ENOTDIR); } @@ -263,6 +290,32 @@ pub fn sys_mkdir(path: *const u8, mode: usize) -> SysResult { Ok(0) } +pub fn sys_link(oldpath: *const u8, newpath: *const u8) -> SysResult { + let mut proc = process(); + let oldpath = unsafe { proc.memory_set.check_and_clone_cstr(oldpath) } + .ok_or(SysError::EFAULT)?; + let newpath = unsafe { proc.memory_set.check_and_clone_cstr(newpath) } + .ok_or(SysError::EFAULT)?; + info!("link: oldpath: {:?}, newpath: {:?}", oldpath, newpath); + + let (new_dir_path, new_file_name) = split_path(&newpath); + let inode = proc.lookup_inode(&oldpath)?; + let new_dir_inode = proc.lookup_inode(new_dir_path)?; + new_dir_inode.link(new_file_name, &inode)?; + Ok(0) +} + +pub fn sys_unlink(path: *const u8) -> SysResult { + let mut proc = process(); + let path = unsafe { proc.memory_set.check_and_clone_cstr(path) } + .ok_or(SysError::EFAULT)?; + info!("unlink: path: {:?}", path); + + let (dir_path, file_name) = split_path(&path); + let dir_inode = proc.lookup_inode(dir_path)?; + dir_inode.unlink(file_name)?; + Ok(0) +} impl Process { fn get_file(&mut self, fd: usize) -> Result<&mut FileHandle, SysError> { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index b082cc1..b1a28d9 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -69,15 +69,16 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { 061 => sys_wait(args[0], args[1] as *mut i32), // TODO: wait4 062 => sys_kill(args[0]), // 072 => sys_fcntl(), -// 074 => sys_fsync(), -// 076 => sys_trunc(), -// 077 => sys_ftrunc(), + 074 => sys_fsync(args[0]), + 075 => sys_fdatasync(args[0]), + 076 => sys_truncate(args[0] as *const u8, args[1]), + 077 => sys_ftruncate(args[0], args[1]), 079 => sys_getcwd(args[0] as *mut u8, args[1]), 080 => sys_chdir(args[0] as *const u8), 082 => sys_rename(args[0] as *const u8, args[1] as *const u8), 083 => sys_mkdir(args[0] as *const u8, args[1]), -// 086 => sys_link(), -// 087 => sys_unlink(), + 086 => sys_link(args[0] as *const u8, args[1] as *const u8), + 087 => sys_unlink(args[0] as *const u8), 096 => sys_get_time(), // TODO: sys_gettimeofday // 097 => sys_getrlimit(), // 098 => sys_getrusage(),