Parcourir la source

fix: 修复由于升级到2024-07-23工具链之后,某些机器上面内核运行一直fault的问题。 (#870)

* fix: 修复由于升级到2024-07-23工具链之后,某些机器上面内核运行一直fault的问题。
LoGin il y a 8 mois
Parent
commit
703ce5a77c

+ 2 - 2
Makefile

@@ -156,14 +156,14 @@ log-monitor:
 .PHONY: update-submodules
 update-submodules:
 	@echo "更新子模块"
-	@git submodule update --recursive
+	@git submodule update --recursive --init
 	@git submodule foreach git pull origin master
 
 .PHONY: update-submodules-by-mirror
 update-submodules-by-mirror:
 	@echo "从镜像更新子模块"
 	@git config --global url."https://git.mirrors.dragonos.org.cn/DragonOS-Community/".insteadOf https://github.com/DragonOS-Community/
-	@$(MAKE) update-submodules
+	@$(MAKE) update-submodules --init
 	@git config --global --unset url."https://git.mirrors.dragonos.org.cn/DragonOS-Community/".insteadOf
 
 help:

+ 2 - 3
kernel/.cargo/config.toml

@@ -6,8 +6,7 @@
 runner = "bootimage runner"
 
 [build]
-# '-Zlinker-features=-lld' 禁用rustlld(20240723),因为它与linkme0.3版本冲突
-rustflags = ["-Zlinker-features=-lld"]
-rustdocflags = ["-Zlinker-features=-lld"]
+rustflags = ["-Clink-args=-znostart-stop-gc"]
+rustdocflags = ["-Clink-args=-znostart-stop-gc"]
 
 [env]

+ 5 - 5
kernel/Makefile

@@ -25,9 +25,9 @@ clean:
 
 .PHONY: fmt
 fmt:
-	@cargo fmt --all $(FMT_CHECK)
+	RUSTFLAGS="$(RUSTFLAGS)" cargo fmt --all $(FMT_CHECK)
 ifeq ($(ARCH), x86_64)
-	@cargo clippy --all-features
+	RUSTFLAGS="$(RUSTFLAGS)" cargo clippy --all-features
 endif
 
 
@@ -36,12 +36,12 @@ check: ECHO
 # @echo "Checking kernel... ARCH=$(ARCH)"
 # @exit 1
 ifeq ($(ARCH), x86_64)
-	@cargo +nightly-2024-07-23 check --workspace $(CARGO_ZBUILD) --message-format=json --target ./src/$(TARGET_JSON)
+	RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2024-07-23 check --workspace $(CARGO_ZBUILD) --message-format=json --target ./src/$(TARGET_JSON)
 else ifeq ($(ARCH), riscv64)
-	@cargo +nightly-2024-07-23 check --workspace $(CARGO_ZBUILD) --message-format=json --target $(TARGET_JSON)
+	RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2024-07-23 check --workspace $(CARGO_ZBUILD) --message-format=json --target $(TARGET_JSON)
 endif
 
 test:
 # 测试内核库
-	@cargo +nightly-2024-07-23 test --workspace --exclude dragonos_kernel
+	RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2024-07-23 test --workspace --exclude dragonos_kernel
 

+ 3 - 0
kernel/env.mk

@@ -42,3 +42,6 @@ endif
 ifeq ($(DEBUG), DEBUG)
 GLOBAL_CFLAGS += -g 
 endif
+
+export RUSTFLAGS := -C link-args=-znostart-stop-gc
+export RUSTDOCFLAGS := -C link-args=-znostart-stop-gc

+ 3 - 3
kernel/src/arch/riscv64/process/syscall.rs

@@ -1,4 +1,4 @@
-use alloc::{string::String, vec::Vec};
+use alloc::{ffi::CString, string::String, vec::Vec};
 use riscv::register::sstatus::{FS, SPP};
 use system_error::SystemError;
 
@@ -16,8 +16,8 @@ use crate::{
 impl Syscall {
     pub fn do_execve(
         path: String,
-        argv: Vec<String>,
-        envp: Vec<String>,
+        argv: Vec<CString>,
+        envp: Vec<CString>,
         regs: &mut TrapFrame,
     ) -> Result<(), SystemError> {
         // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。

+ 4 - 4
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<String>,
-        envp: Vec<String>,
+        argv: Vec<CString>,
+        envp: Vec<CString>,
         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,

+ 4 - 2
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<usize, SystemError> {
     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)?;

+ 69 - 23
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<usize, SystemError> {
-        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<usize, SystemError> {
-        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<usize, SystemError> {
-        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<usize, SystemError> {
         let get_path = |cstr: *const u8| -> Result<String, SystemError> {
-            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<usize, SystemError> {
-        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<usize, SystemError> {
         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<usize, SystemError> {
-        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<usize, SystemError> {
-        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<usize, SystemError> {
-        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<usize, SystemError> {
-        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<Arc<dyn IndexNode>, SystemError> =
@@ -1499,7 +1534,9 @@ impl Syscall {
         user_buf: *mut u8,
         buf_size: usize,
     ) -> Result<usize, SystemError> {
-        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<usize, 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)?;
 
-        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<usize, SystemError> {
-        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 {

+ 6 - 6
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(())
 }

+ 14 - 13
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<BinaryLoaderResult, Sys
 /// 程序初始化信息,这些信息会被压入用户栈中
 #[derive(Debug)]
 pub struct ProcInitInfo {
-    pub proc_name: String,
-    pub args: Vec<String>,
-    pub envs: Vec<String>,
+    pub proc_name: CString,
+    pub args: Vec<CString>,
+    pub envs: Vec<CString>,
     pub auxv: BTreeMap<u8, usize>,
 }
 
 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::<Vec<_>>();
-
         // 然后把参数压入栈中
         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::<Vec<_>>();
@@ -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(());
     }
 }

+ 3 - 2
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>) -> String {
+    pub fn generate_name(program_path: &str, args: &Vec<CString>) -> 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;
     }

+ 10 - 13
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<String> = check_and_clone_cstr_array(argv)?;
-            let envp: Vec<String> = check_and_clone_cstr_array(envp)?;
+            let path: CString = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
+            let argv: Vec<CString> = check_and_clone_cstr_array(argv)?;
+            let envp: Vec<CString> = check_and_clone_cstr_array(envp)?;
             Ok((path, argv, envp))
         };
-        let r: Result<(String, Vec<String>, Vec<String>), 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));

+ 3 - 1
kernel/src/syscall/mod.rs

@@ -1150,7 +1150,9 @@ impl Syscall {
         back_color: u32,
     ) -> Result<usize, SystemError> {
         // 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;

+ 10 - 5
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<usize, Sys
 /// ## 错误
 ///
 /// - `EFAULT`:用户态地址不合法
+/// - `EINVAL`:字符串不是合法的 C 字符串
 pub fn check_and_clone_cstr(
     user: *const u8,
     max_length: Option<usize>,
-) -> Result<String, SystemError> {
+) -> Result<CString, SystemError> {
     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<Vec<String>, SystemError> {
+pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<CString>, SystemError> {
     if user.is_null() {
         Ok(Vec::new())
     } else {