From e6dfeeaa55553eddc4cd66b3267093ccf3261a13 Mon Sep 17 00:00:00 2001 From: longjin Date: Sat, 27 Jul 2024 15:25:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/arch/x86_64/process/syscall.rs | 8 +- kernel/src/filesystem/vfs/open.rs | 6 +- kernel/src/filesystem/vfs/syscall.rs | 92 +++++++++++++++++------ kernel/src/init/initial_kthread.rs | 12 +-- kernel/src/process/exec.rs | 27 +++---- kernel/src/process/mod.rs | 5 +- kernel/src/process/syscall.rs | 23 +++--- kernel/src/syscall/mod.rs | 4 +- kernel/src/syscall/user_access.rs | 15 ++-- 9 files changed, 123 insertions(+), 69 deletions(-) diff --git a/kernel/src/arch/x86_64/process/syscall.rs b/kernel/src/arch/x86_64/process/syscall.rs index a356a4531..d2652beb9 100644 --- a/kernel/src/arch/x86_64/process/syscall.rs +++ b/kernel/src/arch/x86_64/process/syscall.rs @@ -1,4 +1,4 @@ -use alloc::{string::String, sync::Arc, vec::Vec}; +use alloc::{ffi::CString, string::String, sync::Arc, vec::Vec}; use system_error::SystemError; use crate::{ @@ -19,14 +19,14 @@ use crate::{ impl Syscall { pub fn do_execve( path: String, - argv: Vec, - envp: Vec, + argv: Vec, + envp: Vec, regs: &mut TrapFrame, ) -> Result<(), SystemError> { // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; let pcb = ProcessManager::current_pcb(); - // crate::debug!( + // log::debug!( // "pid: {:?} do_execve: path: {:?}, argv: {:?}, envp: {:?}\n", // pcb.pid(), // path, diff --git a/kernel/src/filesystem/vfs/open.rs b/kernel/src/filesystem/vfs/open.rs index f94908155..14f31fa10 100644 --- a/kernel/src/filesystem/vfs/open.rs +++ b/kernel/src/filesystem/vfs/open.rs @@ -38,8 +38,9 @@ pub(super) fn do_faccessat( // let follow_symlink = flags & AtFlags::AT_SYMLINK_NOFOLLOW.bits() as u32 == 0; let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = path.to_str().map_err(|_| SystemError::EINVAL)?; - let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?; + let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?; // 如果找不到文件,则返回错误码ENOENT let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; @@ -50,8 +51,9 @@ pub(super) fn do_faccessat( pub fn do_fchmodat(dirfd: i32, path: *const u8, _mode: ModeType) -> Result { let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = path.to_str().map_err(|_| SystemError::EINVAL)?; - let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?; + let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?; // 如果找不到文件,则返回错误码ENOENT let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; diff --git a/kernel/src/filesystem/vfs/syscall.rs b/kernel/src/filesystem/vfs/syscall.rs index 63d90d4bd..e30c48836 100644 --- a/kernel/src/filesystem/vfs/syscall.rs +++ b/kernel/src/filesystem/vfs/syscall.rs @@ -1,7 +1,6 @@ use core::ffi::c_void; use core::mem::size_of; -use alloc::string::ToString; use alloc::{string::String, sync::Arc, vec::Vec}; use log::warn; use system_error::SystemError; @@ -484,7 +483,10 @@ impl Syscall { mode: u32, follow_symlink: bool, ) -> Result { - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; + let open_flags: FileMode = FileMode::from_bits(o_flags).ok_or(SystemError::EINVAL)?; let mode = ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?; return do_sys_open( @@ -503,7 +505,10 @@ impl Syscall { mode: u32, follow_symlink: bool, ) -> Result { - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; + let open_flags: FileMode = FileMode::from_bits(o_flags).ok_or(SystemError::EINVAL)?; let mode = ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?; return do_sys_open(dirfd, &path, open_flags, mode, follow_symlink); @@ -682,7 +687,10 @@ impl Syscall { return Err(SystemError::EFAULT); } - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; + let proc = ProcessManager::current_pcb(); // Copy path to kernel space to avoid some security issues let mut new_path = String::from(""); @@ -786,7 +794,10 @@ impl Syscall { /// /// @return uint64_t 负数错误码 / 0表示成功 pub fn mkdir(path: *const u8, mode: usize) -> Result { - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; + do_mkdir_at( AtFlags::AT_FDCWD.bits(), &path, @@ -861,7 +872,10 @@ impl Syscall { pub fn link(old: *const u8, new: *const u8) -> Result { let get_path = |cstr: *const u8| -> Result { - let res = check_and_clone_cstr(cstr, Some(MAX_PATHLEN))?; + let res = check_and_clone_cstr(cstr, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; + if res.len() >= MAX_PATHLEN { return Err(SystemError::ENAMETOOLONG); } @@ -888,8 +902,12 @@ impl Syscall { new: *const u8, flags: i32, ) -> Result { - let old = check_and_clone_cstr(old, Some(MAX_PATHLEN))?; - let new = check_and_clone_cstr(new, Some(MAX_PATHLEN))?; + let old = check_and_clone_cstr(old, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; + let new = check_and_clone_cstr(new, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; if old.len() >= MAX_PATHLEN || new.len() >= MAX_PATHLEN { return Err(SystemError::ENAMETOOLONG); } @@ -913,7 +931,9 @@ impl Syscall { pub fn unlinkat(dirfd: i32, path: *const u8, flags: u32) -> Result { let flags = AtFlags::from_bits(flags as i32).ok_or(SystemError::EINVAL)?; - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; if flags.contains(AtFlags::AT_REMOVEDIR) { // debug!("rmdir"); @@ -938,12 +958,16 @@ impl Syscall { } pub fn rmdir(path: *const u8) -> Result { - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; return do_remove_dir(AtFlags::AT_FDCWD.bits(), &path).map(|v| v as usize); } pub fn unlink(path: *const u8) -> Result { - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; return do_unlink_at(AtFlags::AT_FDCWD.bits(), &path).map(|v| v as usize); } @@ -970,8 +994,14 @@ impl Syscall { filename_to: *const u8, _flags: u32, ) -> Result { - let filename_from = check_and_clone_cstr(filename_from, Some(MAX_PATHLEN)).unwrap(); - let filename_to = check_and_clone_cstr(filename_to, Some(MAX_PATHLEN)).unwrap(); + let filename_from = check_and_clone_cstr(filename_from, Some(MAX_PATHLEN)) + .unwrap() + .into_string() + .map_err(|_| SystemError::EINVAL)?; + let filename_to = check_and_clone_cstr(filename_to, Some(MAX_PATHLEN)) + .unwrap() + .into_string() + .map_err(|_| SystemError::EINVAL)?; // 文件名过长 if filename_from.len() > MAX_PATHLEN || filename_to.len() > MAX_PATHLEN { return Err(SystemError::ENAMETOOLONG); @@ -1315,7 +1345,10 @@ impl Syscall { ModeType::empty().bits(), true, )?; - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN)).unwrap(); + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN)) + .unwrap() + .into_string() + .map_err(|_| SystemError::EINVAL)?; let pcb = ProcessManager::current_pcb(); let (_inode_begin, remain_path) = user_path_at(&pcb, fd as i32, &path)?; let inode = ROOT_INODE().lookup_follow_symlink(&remain_path, MAX_PATHLEN)?; @@ -1450,7 +1483,9 @@ impl Syscall { mode: ModeType, dev_t: DeviceNumber, ) -> Result { - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; let path = path.as_str().trim(); let inode: Result, SystemError> = @@ -1499,7 +1534,9 @@ impl Syscall { user_buf: *mut u8, buf_size: usize, ) -> Result { - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; let path = path.as_str().trim(); let mut user_buf = UserBufferWriter::new(user_buf, buf_size, true)?; @@ -1601,13 +1638,16 @@ impl Syscall { _mountflags: usize, _data: *const c_void, ) -> Result { - let target = user_access::check_and_clone_cstr(target, Some(MAX_PATHLEN))?; + let target = user_access::check_and_clone_cstr(target, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; - let filesystemtype = user_access::check_and_clone_cstr(filesystemtype, Some(MAX_PATHLEN))?; + let fstype_str = user_access::check_and_clone_cstr(filesystemtype, Some(MAX_PATHLEN))?; + let fstype_str = fstype_str.to_str().map_err(|_| SystemError::EINVAL)?; - let filesystemtype = producefs!(FSMAKER, filesystemtype)?; + let fstype = producefs!(FSMAKER, fstype_str)?; - Vcore::do_mount(filesystemtype, target.to_string().as_str())?; + Vcore::do_mount(fstype, &target)?; return Ok(0); } @@ -1621,7 +1661,9 @@ impl Syscall { /// /// [umount(2) — Linux manual page](https://www.man7.org/linux/man-pages/man2/umount.2.html) pub fn umount2(target: *const u8, flags: i32) -> Result<(), SystemError> { - let target = user_access::check_and_clone_cstr(target, Some(MAX_PATHLEN))?; + let target = user_access::check_and_clone_cstr(target, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; Vcore::do_umount2( AtFlags::AT_FDCWD.bits(), &target, @@ -1639,7 +1681,9 @@ impl Syscall { let pathname = if pathname.is_null() { None } else { - let pathname = check_and_clone_cstr(pathname, Some(MAX_PATHLEN))?; + let pathname = check_and_clone_cstr(pathname, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; Some(pathname) }; let flags = UtimensFlags::from_bits(flags).ok_or(SystemError::EINVAL)?; @@ -1657,7 +1701,9 @@ impl Syscall { pathname: *const u8, times: *const PosixTimeval, ) -> Result { - let pathname = check_and_clone_cstr(pathname, Some(MAX_PATHLEN))?; + let pathname = check_and_clone_cstr(pathname, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; let times = if times.is_null() { None } else { diff --git a/kernel/src/init/initial_kthread.rs b/kernel/src/init/initial_kthread.rs index 839024fca..0f7056a4c 100644 --- a/kernel/src/init/initial_kthread.rs +++ b/kernel/src/init/initial_kthread.rs @@ -2,7 +2,7 @@ use core::sync::atomic::{compiler_fence, Ordering}; -use alloc::string::{String, ToString}; +use alloc::{ffi::CString, string::ToString}; use log::{debug, error}; use system_error::SystemError; @@ -86,7 +86,7 @@ fn switch_to_user() -> ! { } fn try_to_run_init_process(path: &str, trap_frame: &mut TrapFrame) -> Result<(), SystemError> { - if let Err(e) = run_init_process(path.to_string(), trap_frame) { + if let Err(e) = run_init_process(path, trap_frame) { if e != SystemError::ENOENT { error!( "Failed to run init process: {path} exists but couldn't execute it (error {:?})", @@ -98,11 +98,11 @@ fn try_to_run_init_process(path: &str, trap_frame: &mut TrapFrame) -> Result<(), Ok(()) } -fn run_init_process(path: String, trap_frame: &mut TrapFrame) -> Result<(), SystemError> { - let argv = vec![path.clone()]; - let envp = vec![String::from("PATH=/")]; +fn run_init_process(path: &str, trap_frame: &mut TrapFrame) -> Result<(), SystemError> { + let argv = vec![CString::new(path).unwrap()]; + let envp = vec![CString::new("PATH=/").unwrap()]; compiler_fence(Ordering::SeqCst); - Syscall::do_execve(path, argv, envp, trap_frame)?; + Syscall::do_execve(path.to_string(), argv, envp, trap_frame)?; Ok(()) } diff --git a/kernel/src/process/exec.rs b/kernel/src/process/exec.rs index 94e219291..12af4c339 100644 --- a/kernel/src/process/exec.rs +++ b/kernel/src/process/exec.rs @@ -1,6 +1,6 @@ use core::{fmt::Debug, ptr::null}; -use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec}; +use alloc::{collections::BTreeMap, ffi::CString, string::String, sync::Arc, vec::Vec}; use system_error::SystemError; use crate::{ @@ -16,6 +16,8 @@ use crate::{ }, }; +use super::ProcessManager; + /// 系统支持的所有二进制文件加载器的列表 const BINARY_LOADERS: [&'static dyn BinaryLoader; 1] = [&ELF_LOADER]; @@ -125,7 +127,7 @@ impl ExecParam { file, vm, flags, - init_info: ProcInitInfo::new(), + init_info: ProcInitInfo::new(ProcessManager::current_pcb().basic().name()), }) } @@ -195,16 +197,16 @@ pub fn load_binary_file(param: &mut ExecParam) -> Result, - pub envs: Vec, + pub proc_name: CString, + pub args: Vec, + pub envs: Vec, pub auxv: BTreeMap, } impl ProcInitInfo { - pub fn new() -> Self { + pub fn new(proc_name: &str) -> Self { Self { - proc_name: String::new(), + proc_name: CString::new(proc_name).unwrap_or(CString::new("").unwrap()), args: Vec::new(), envs: Vec::new(), auxv: BTreeMap::new(), @@ -229,17 +231,16 @@ impl ProcInitInfo { .envs .iter() .map(|s| { - self.push_str(ustack, s.as_str()).expect("push_str failed"); + self.push_str(ustack, s).expect("push_str failed"); ustack.sp() }) .collect::>(); - // 然后把参数压入栈中 let argps = self .args .iter() .map(|s| { - self.push_str(ustack, s.as_str()).expect("push_str failed"); + self.push_str(ustack, s).expect("push_str failed"); ustack.sp() }) .collect::>(); @@ -280,9 +281,9 @@ impl ProcInitInfo { return Ok(()); } - fn push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError> { - self.push_slice(ustack, &[b"\0"])?; - self.push_slice(ustack, s.as_bytes())?; + fn push_str(&self, ustack: &mut UserStack, s: &CString) -> Result<(), SystemError> { + let bytes = s.as_bytes_with_nul(); + self.push_slice(ustack, bytes)?; return Ok(()); } } diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index f4be134e8..f3d76ee88 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -8,6 +8,7 @@ use core::{ }; use alloc::{ + ffi::CString, string::{String, ToString}, sync::{Arc, Weak}, vec::Vec, @@ -922,11 +923,11 @@ impl ProcessControlBlock { } /// 生成进程的名字 - pub fn generate_name(program_path: &str, args: &Vec) -> String { + pub fn generate_name(program_path: &str, args: &Vec) -> String { let mut name = program_path.to_string(); for arg in args { name.push(' '); - name.push_str(arg); + name.push_str(arg.to_string_lossy().as_ref()); } return name; } diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs index 16f0e2e45..86ffe5dd9 100644 --- a/kernel/src/process/syscall.rs +++ b/kernel/src/process/syscall.rs @@ -1,10 +1,7 @@ use core::ffi::c_void; -use alloc::{ - string::{String, ToString}, - sync::Arc, - vec::Vec, -}; +use alloc::{ffi::CString, string::ToString, sync::Arc, vec::Vec}; +use log::error; use system_error::SystemError; use super::{ @@ -114,16 +111,16 @@ impl Syscall { } let x = || { - let path: String = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; - let argv: Vec = check_and_clone_cstr_array(argv)?; - let envp: Vec = check_and_clone_cstr_array(envp)?; + let path: CString = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let argv: Vec = check_and_clone_cstr_array(argv)?; + let envp: Vec = check_and_clone_cstr_array(envp)?; Ok((path, argv, envp)) }; - let r: Result<(String, Vec, Vec), SystemError> = x(); - if let Err(e) = r { - panic!("Failed to execve: {:?}", e); - } - let (path, argv, envp) = r.unwrap(); + let (path, argv, envp) = x().inspect_err(|e: &SystemError| { + error!("Failed to execve: {:?}", e); + })?; + + let path = path.into_string().map_err(|_| SystemError::EINVAL)?; ProcessManager::current_pcb() .basic_mut() .set_name(ProcessControlBlock::generate_name(&path, &argv)); diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index cca260a03..c8cd45868 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -1150,7 +1150,9 @@ impl Syscall { back_color: u32, ) -> Result { // todo: 删除这个系统调用 - let s = check_and_clone_cstr(s, Some(4096))?; + let s = check_and_clone_cstr(s, Some(4096))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; let fr = (front_color & 0x00ff0000) >> 16; let fg = (front_color & 0x0000ff00) >> 8; let fb = front_color & 0x000000ff; diff --git a/kernel/src/syscall/user_access.rs b/kernel/src/syscall/user_access.rs index c55f75674..18a74764e 100644 --- a/kernel/src/syscall/user_access.rs +++ b/kernel/src/syscall/user_access.rs @@ -2,10 +2,11 @@ use core::{ mem::size_of, + num::NonZero, slice::{from_raw_parts, from_raw_parts_mut}, }; -use alloc::{string::String, vec::Vec}; +use alloc::{ffi::CString, vec::Vec}; use crate::mm::{verify_area, VirtAddr}; @@ -70,10 +71,11 @@ pub unsafe fn copy_from_user(dst: &mut [u8], src: VirtAddr) -> Result, -) -> Result { +) -> Result { if user.is_null() { return Err(SystemError::EFAULT); } @@ -93,9 +95,12 @@ pub fn check_and_clone_cstr( if c[0] == 0 { break; } - buffer.push(c[0]); + buffer.push(NonZero::new(c[0]).ok_or(SystemError::EINVAL)?); } - String::from_utf8(buffer).map_err(|_| SystemError::EFAULT) + + let cstr = CString::from(buffer); + + return Ok(cstr); } /// 检查并从用户态拷贝一个 C 字符串数组 @@ -112,7 +117,7 @@ pub fn check_and_clone_cstr( /// ## 错误 /// /// - `EFAULT`:用户态地址不合法 -pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result, SystemError> { +pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result, SystemError> { if user.is_null() { Ok(Vec::new()) } else {