Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions os/src/fs/proc/inode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl ProcInode {
metadata: SpinLock::new(InodeMetadata {
inode_no,
inode_type: InodeType::Symlink,
mode: FileMode::from_bits_truncate(0o777),
mode: FileMode::from_bits_truncate(0o777 | FileMode::S_IFLNK.bits()),
uid: 0,
gid: 0,
size: target.len(),
Expand Down Expand Up @@ -211,7 +211,7 @@ impl ProcInode {
metadata: SpinLock::new(InodeMetadata {
inode_no,
inode_type: InodeType::Symlink,
mode: FileMode::from_bits_truncate(0o777),
mode: FileMode::from_bits_truncate(0o777 | FileMode::S_IFLNK.bits()),
uid: 0,
gid: 0,
size: 0, // 动态链接的大小未知
Expand Down
3 changes: 3 additions & 0 deletions os/src/kernel/syscall/task/clone_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub fn clone(
fs,
uts,
rlimit,
exe_path,
) = {
let _guard = crate::sync::PreemptGuard::new();
let cpu = current_cpu();
Expand All @@ -66,6 +67,7 @@ pub fn clone(
task.fs.clone(),
task.uts_namespace.clone(),
task.rlimit.clone(),
task.exe_path.clone(),
)
};
let exit_signal = requested_flags.get_exit_signal();
Expand Down Expand Up @@ -132,6 +134,7 @@ pub fn clone(
fd_table,
fs,
);
child_task.exe_path = exe_path;

if requested_flags.contains(CloneFlags::CHILD_SETTID) {
unsafe {
Expand Down
12 changes: 11 additions & 1 deletion os/src/kernel/syscall/task/exec_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub fn execve(
Err(_) => return -EIO,
};
if meta.inode_type != crate::vfs::InodeType::File {
return -EISDIR;
return exec_non_file_errno(meta.inode_type);
}

let prefix_len = core::cmp::min(meta.size, 256);
Expand Down Expand Up @@ -173,6 +173,13 @@ fn parse_hashbang(data: &[u8]) -> Result<(&str, Option<&str>), HashbangError> {
Ok((interpreter_path, interpreter_arg))
}

// 按 POSIX/Linux 语义:对非普通文件(含目录)调用 execve 一律返回 EACCES。
// 真实内核 may_open() 对 S_IFDIR + MAY_EXEC 返回 -EACCES;EISDIR 仅用于写目录等场景。
// busybox/bash 拿到 EACCES 后会自行处理(bash 会 stat 后输出 "Is a directory")。
fn exec_non_file_errno(_inode_type: crate::vfs::InodeType) -> c_int {
-EACCES
}

/// 执行一个新程序(execve)的准备阶段:解析 ELF 并创建新的地址空间
fn do_execve_prepare(
path: &str,
Expand All @@ -181,6 +188,9 @@ fn do_execve_prepare(
Ok(p) => p,
Err(crate::kernel::task::ExecImageError::Fs(FsError::NotFound)) => return Err(-ENOENT),
Err(crate::kernel::task::ExecImageError::Fs(FsError::IsDirectory)) => return Err(-EISDIR),
Err(crate::kernel::task::ExecImageError::NotRegular(inode_type)) => {
return Err(exec_non_file_errno(inode_type));
}
Err(crate::kernel::task::ExecImageError::Fs(_)) => return Err(-EIO),
Err(crate::kernel::task::ExecImageError::Paging(
crate::mm::page_table::PagingError::OutOfMemory,
Expand Down
4 changes: 2 additions & 2 deletions os/src/kernel/syscall/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ use crate::{
sync::SpinLock,
uapi::{
errno::{
EAGAIN, EFAULT, EINTR, EINVAL, EIO, EISDIR, ENOENT, ENOEXEC, ENOMEM, ENOSYS, EPERM,
ESRCH, ETIMEDOUT,
EACCES, EAGAIN, EFAULT, EINTR, EINVAL, EIO, EISDIR, ENOENT, ENOEXEC, ENOMEM, ENOSYS,
EPERM, ESRCH, ETIMEDOUT,
},
futex::{FUTEX_CLOCK_REALTIME, FUTEX_PRIVATE, FUTEX_WAIT, FUTEX_WAKE, RobustListHead},
resource::{RLIM_NLIMITS, Rlimit, Rusage},
Expand Down
5 changes: 3 additions & 2 deletions os/src/kernel/task/exec_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::vfs::{FsError, Inode, InodeType};
pub enum ExecImageError {
Fs(FsError),
InvalidElf,
NotRegular(InodeType),
Paging(PagingError),
}

Expand Down Expand Up @@ -429,7 +430,7 @@ pub fn prepare_exec_image_from_path(path: &str) -> Result<PreparedExecImage, Exe
let inode = dentry.inode.clone();
let meta = inode.metadata().map_err(ExecImageError::from)?;
if meta.inode_type != InodeType::File {
return Err(ExecImageError::Fs(FsError::IsDirectory));
return Err(ExecImageError::NotRegular(meta.inode_type));
}

let eh = parse_elf_header(inode.as_ref())?;
Expand Down Expand Up @@ -479,7 +480,7 @@ pub fn prepare_exec_image_from_path(path: &str) -> Result<PreparedExecImage, Exe
let interp_inode = interp_dentry.inode.clone();
let interp_meta = interp_inode.metadata().map_err(ExecImageError::from)?;
if interp_meta.inode_type != InodeType::File {
return Err(ExecImageError::InvalidElf);
return Err(ExecImageError::NotRegular(interp_meta.inode_type));
}

let interp_eh = parse_elf_header(interp_inode.as_ref())?;
Expand Down
15 changes: 8 additions & 7 deletions os/src/kernel/task/task_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
//!
//! 包含任务的核心信息,如上下文、状态、内存空间等
#![allow(dead_code)]
use core::{
mem::size_of,
sync::atomic::{AtomicPtr, Ordering},
};
use core::sync::atomic::{AtomicPtr, Ordering};

use alloc::{string::String, sync::Arc, vec::Vec};

Expand All @@ -20,7 +17,7 @@ use crate::{
task::{forkret, task_state::TaskState},
},
mm::{
address::{ConvertablePA, PageNum, UA, VA},
address::{ConvertablePA, PageNum, UA, UsizeConvert, VA},
frame_allocator::{FrameRangeTracker, FrameTracker},
memory_space::MemorySpace,
},
Expand Down Expand Up @@ -309,8 +306,12 @@ impl Task {
// 4. 配置 TrapFrame (新的上下文)
// SAFETY: tfptr 指向的内存已经被分配且可写,并由 task 拥有
unsafe {
// 清零整个 TrapFrame,避免旧值泄漏到用户态
core::ptr::write_bytes(tf_ptr, 0, size_of::<TrapFrame>());
// 原先:清零整个 TrapFrame,避免旧值泄漏到用户态。
// 注意:write_bytes 的 count 以 TrapFrame 为单位(非字节),
// 这里只清零 1 个 TrapFrame。若误传 size_of::<TrapFrame>(),
// 会写 280*280 字节、越界冲掉当前 satp 指向的页表,导致静默死循环。
// 由于 set_exec_trap_frame 内部已 *self = Self::zero_init() 全量清零,
// 这行 write_bytes 在功能上完全冗余,故直接删除
<TrapFrame as HwTrapFrame>::set_exec_trap_frame_from_layout(
&mut *tf_ptr,
initial_pc.as_usize(),
Expand Down
21 changes: 19 additions & 2 deletions os/src/vfs/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl Stat {
Self {
st_dev: 0, // TODO: 需要从文件系统获取设备号
st_ino: meta.inode_no as u64,
st_mode: meta.mode.bits(),
st_mode: mode_with_type(meta),
st_nlink: meta.nlinks as u32,
st_uid: meta.uid,
st_gid: meta.gid,
Expand Down Expand Up @@ -50,7 +50,7 @@ impl Statx {
stx_nlink: meta.nlinks as u32,
stx_uid: meta.uid,
stx_gid: meta.gid,
stx_mode: meta.mode.bits() as u16,
stx_mode: mode_with_type(meta) as u16,
__spare0: [0; 1],
stx_ino: meta.inode_no as u64,
stx_size: meta.size as u64,
Expand All @@ -72,6 +72,23 @@ impl Statx {
}
}

fn mode_with_type(meta: &InodeMetadata) -> u32 {
let mode = meta.mode.bits();
if mode & crate::vfs::FileMode::S_IFMT.bits() != 0 {
return mode;
}

mode | match meta.inode_type {
InodeType::File => crate::vfs::FileMode::S_IFREG.bits(),
InodeType::Directory => crate::vfs::FileMode::S_IFDIR.bits(),
InodeType::Symlink => crate::vfs::FileMode::S_IFLNK.bits(),
InodeType::CharDevice => crate::vfs::FileMode::S_IFCHR.bits(),
InodeType::BlockDevice => crate::vfs::FileMode::S_IFBLK.bits(),
InodeType::Fifo => crate::vfs::FileMode::S_IFIFO.bits(),
InodeType::Socket => crate::vfs::FileMode::S_IFSOCK.bits(),
}
}

/// 将InodeType转换为d_type值
pub fn inode_type_to_d_type(t: InodeType) -> u8 {
match t {
Expand Down
Loading