|
@@ -1,8 +1,9 @@
|
|
-use log::error;
|
|
|
|
|
|
+use alloc::string::String;
|
|
|
|
+use alloc::sync::Arc;
|
|
|
|
|
|
use crate::arch::interrupt::TrapFrame;
|
|
use crate::arch::interrupt::TrapFrame;
|
|
use crate::arch::syscall::nr::SYS_EXECVE;
|
|
use crate::arch::syscall::nr::SYS_EXECVE;
|
|
-use crate::filesystem::vfs::MAX_PATHLEN;
|
|
|
|
|
|
+use crate::filesystem::vfs::{IndexNode, MAX_PATHLEN};
|
|
use crate::mm::page::PAGE_4K_SIZE;
|
|
use crate::mm::page::PAGE_4K_SIZE;
|
|
use crate::mm::{verify_area, VirtAddr};
|
|
use crate::mm::{verify_area, VirtAddr};
|
|
use crate::process::execve::do_execve;
|
|
use crate::process::execve::do_execve;
|
|
@@ -10,6 +11,7 @@ use crate::process::{ProcessControlBlock, ProcessManager};
|
|
use crate::syscall::table::{FormattedSyscallParam, Syscall};
|
|
use crate::syscall::table::{FormattedSyscallParam, Syscall};
|
|
use crate::syscall::user_access::{check_and_clone_cstr, check_and_clone_cstr_array};
|
|
use crate::syscall::user_access::{check_and_clone_cstr, check_and_clone_cstr_array};
|
|
use alloc::{ffi::CString, vec::Vec};
|
|
use alloc::{ffi::CString, vec::Vec};
|
|
|
|
+use log::error;
|
|
use system_error::SystemError;
|
|
use system_error::SystemError;
|
|
|
|
|
|
pub struct SysExecve;
|
|
pub struct SysExecve;
|
|
@@ -26,6 +28,63 @@ impl SysExecve {
|
|
fn env_ptr(args: &[usize]) -> usize {
|
|
fn env_ptr(args: &[usize]) -> usize {
|
|
args[2]
|
|
args[2]
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ pub fn check_args(
|
|
|
|
+ frame: &mut TrapFrame,
|
|
|
|
+ path_ptr: usize,
|
|
|
|
+ argv_ptr: usize,
|
|
|
|
+ env_ptr: usize,
|
|
|
|
+ ) -> Result<(), SystemError> {
|
|
|
|
+ if path_ptr == 0 {
|
|
|
|
+ return Err(SystemError::EINVAL);
|
|
|
|
+ }
|
|
|
|
+ let virt_path_ptr = VirtAddr::new(path_ptr);
|
|
|
|
+ let virt_argv_ptr = VirtAddr::new(argv_ptr);
|
|
|
|
+ let virt_env_ptr = VirtAddr::new(env_ptr);
|
|
|
|
+
|
|
|
|
+ // 权限校验
|
|
|
|
+ if frame.is_from_user()
|
|
|
|
+ && (verify_area(virt_path_ptr, MAX_PATHLEN).is_err()
|
|
|
|
+ || verify_area(virt_argv_ptr, PAGE_4K_SIZE).is_err())
|
|
|
|
+ || verify_area(virt_env_ptr, PAGE_4K_SIZE).is_err()
|
|
|
|
+ {
|
|
|
|
+ return Err(SystemError::EFAULT);
|
|
|
|
+ }
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn basic_args(
|
|
|
|
+ path: *const u8,
|
|
|
|
+ argv: *const *const u8,
|
|
|
|
+ envp: *const *const u8,
|
|
|
|
+ ) -> Result<(CString, Vec<CString>, Vec<CString>), SystemError> {
|
|
|
|
+ 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))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn execve(
|
|
|
|
+ inode: Arc<dyn IndexNode>,
|
|
|
|
+ path: String,
|
|
|
|
+ argv: Vec<CString>,
|
|
|
|
+ envp: Vec<CString>,
|
|
|
|
+ frame: &mut TrapFrame,
|
|
|
|
+ ) -> Result<(), SystemError> {
|
|
|
|
+ ProcessManager::current_pcb()
|
|
|
|
+ .basic_mut()
|
|
|
|
+ .set_name(ProcessControlBlock::generate_name(&path, &argv));
|
|
|
|
+
|
|
|
|
+ do_execve(inode, argv, envp, frame)?;
|
|
|
|
+
|
|
|
|
+ let pcb = ProcessManager::current_pcb();
|
|
|
|
+ // 关闭设置了O_CLOEXEC的文件描述符
|
|
|
|
+ let fd_table = pcb.fd_table();
|
|
|
|
+ fd_table.write().close_on_exec();
|
|
|
|
+
|
|
|
|
+ pcb.set_execute_path(path);
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
impl Syscall for SysExecve {
|
|
impl Syscall for SysExecve {
|
|
@@ -38,52 +97,24 @@ impl Syscall for SysExecve {
|
|
let argv_ptr = Self::argv_ptr(args);
|
|
let argv_ptr = Self::argv_ptr(args);
|
|
let env_ptr = Self::env_ptr(args);
|
|
let env_ptr = Self::env_ptr(args);
|
|
|
|
|
|
- let virt_path_ptr = VirtAddr::new(path_ptr);
|
|
|
|
- let virt_argv_ptr = VirtAddr::new(argv_ptr);
|
|
|
|
- let virt_env_ptr = VirtAddr::new(env_ptr);
|
|
|
|
|
|
+ Self::check_args(frame, path_ptr, argv_ptr, env_ptr)?;
|
|
|
|
|
|
- // 权限校验
|
|
|
|
- if frame.is_from_user()
|
|
|
|
- && (verify_area(virt_path_ptr, MAX_PATHLEN).is_err()
|
|
|
|
- || verify_area(virt_argv_ptr, PAGE_4K_SIZE).is_err())
|
|
|
|
- || verify_area(virt_env_ptr, PAGE_4K_SIZE).is_err()
|
|
|
|
- {
|
|
|
|
- Err(SystemError::EFAULT)
|
|
|
|
- } else {
|
|
|
|
- let path = path_ptr as *const u8;
|
|
|
|
- let argv = argv_ptr as *const *const u8;
|
|
|
|
- let envp = env_ptr as *const *const u8;
|
|
|
|
-
|
|
|
|
- if path.is_null() {
|
|
|
|
- return Err(SystemError::EINVAL);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- let x = || {
|
|
|
|
- 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 (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));
|
|
|
|
-
|
|
|
|
- do_execve(path.clone(), argv, envp, frame)?;
|
|
|
|
-
|
|
|
|
- let pcb = ProcessManager::current_pcb();
|
|
|
|
- // 关闭设置了O_CLOEXEC的文件描述符
|
|
|
|
- let fd_table = pcb.fd_table();
|
|
|
|
- fd_table.write().close_on_exec();
|
|
|
|
-
|
|
|
|
- pcb.set_execute_path(path);
|
|
|
|
-
|
|
|
|
- return Ok(0);
|
|
|
|
- }
|
|
|
|
|
|
+ let (path, argv, envp) = Self::basic_args(
|
|
|
|
+ path_ptr as *const u8,
|
|
|
|
+ argv_ptr as *const *const u8,
|
|
|
|
+ env_ptr as *const *const u8,
|
|
|
|
+ )
|
|
|
|
+ .inspect_err(|e: &SystemError| {
|
|
|
|
+ error!("Failed to execve: {:?}", e);
|
|
|
|
+ })?;
|
|
|
|
+
|
|
|
|
+ let path = path.into_string().map_err(|_| SystemError::EINVAL)?;
|
|
|
|
+
|
|
|
|
+ let pwd = ProcessManager::current_pcb().pwd_inode();
|
|
|
|
+ let inode = pwd.lookup(&path)?;
|
|
|
|
+
|
|
|
|
+ Self::execve(inode, path, argv, envp, frame)?;
|
|
|
|
+ return Ok(0);
|
|
}
|
|
}
|
|
|
|
|
|
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
|
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|