fix:修复用户态进入,还有一些路径映射问题#258
Merged
Merged
Conversation
根因:fork/clone 未将 exe_path 传给子进程,导致子 shell 的 /proc/self/exe 退化解析为 "/"。busybox 对无 shebang 脚本拿到 ENOEXEC 后会 re-exec /proc/self/exe,于是实际 execve "/"(目录), 返回 EISDIR,表现为 ./xxx.sh 报 "Is a directory"(而 sh xxx.sh 正常)。 - clone:从父进程拷贝 exe_path 到子进程,修复 /proc/self/exe 解析 - exec_ops/exec_loader:execve 目标非普通文件时按真实类型返回 errno, 仅真目录返回 EISDIR,其余(字符/块设备、fifo、socket)返回 EACCES, 新增 ExecImageError::NotRegular 携带 inode 类型 - adapter:stat/statx 的 st_mode 在缺少 S_IFMT 时按 inode_type 补全类型位 - proc:符号链接 inode 的 mode 补上 S_IFLNK 类型位
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces several improvements to process execution, file mode handling, and task cloning. Specifically, it ensures file type bits are correctly set in symlink inodes and stat structures, propagates exe_path during task cloning, refactors error handling for non-regular files during execve using a new NotRegular error variant, and removes a redundant and potentially unsafe write_bytes call on TrapFrame. Feedback on these changes suggests that according to Linux/POSIX standards, calling execve on a directory should return EACCES instead of EISDIR, and recommends updating exec_non_file_errno to return -EACCES for all non-file types.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🐛 Bug 报告:用户态启动与脚本执行修复(PR 含两处修复)
Bug 1:TrapFrame 清零参数越界,导致用户态无法进入
🐞 描述 Bug
构造首个用户任务 /
execve切换上下文时,对TrapFrame做清零的core::ptr::write_bytes误把字节数当作count传入。write_bytes的count以「元素(TrapFrame)个数」为单位,传入size_of::<TrapFrame>()会写
约 280 × 280字节,远超单个 TrapFrame,越界冲掉当前satp指向的页表页,造成静默死循环,内核始终无法切到用户态。
⚙️ 复现步骤
make run)。kernel_execve("/sbin/init")进入用户态。预期行为
清零应只作用于 1 个
TrapFrame;内核能正常切换到用户态并拉起/sbin/init→/bin/sh,串口出现 shell 提示符。实际行为
write_bytes(tf_ptr, 0, size_of::<TrapFrame>())把 count 当字节数,写入
size_of × size_of字节越界,破坏 satp 所指页表,内核静默死循环,始终无法进入用户态。
✅ 修复方案
由于
set_exec_trap_frame_from_layout内部已通过*self = Self::zero_init()做了全量清零,该
write_bytes行在功能上完全冗余,直接删除,消除越界写。涉及文件:
os/src/kernel/task/task_struct.rs🖥️ 环境信息
qemu-system-riscv64 -machine virtnightly-2025-10-2809e6f9a(缺陷存在于此前版本)📝 截图或日志
[kernel_execve] Switching to user mode
... (此后内核静默卡死,无任何用户态输出)
Bug 2:无 shebang 脚本直接执行报 "Is a directory"
🐞 描述 Bug
进入用户态后,直接执行不带 shebang 的脚本
./iperf_testcode.sh报Is a directory(EISDIR),而sh iperf_testcode.sh可正常执行。根因是
fork/clone未把父进程的exe_path传给子进程:子 shell 的/proc/self/exe因exe_path == None退化解析为"/"。busybox 对无shebang 脚本拿到
ENOEXEC后会 re-exec/proc/self/exe,于是实际execve("/")(目录)→ 返回EISDIR,表现为脚本被「识别成目录」。⚙️ 复现步骤
make run,进入用户态 busybox shell。/iperf_testcode.sh为普通文件(inode 122, mode 0644),且无 shebang。./iperf_testcode.sh,看到错误/bin/sh: ./iperf_testcode.sh: Is a directory。sh iperf_testcode.sh,可正常输出#### OS COMP TEST GROUP START iperf ####。预期行为
./iperf_testcode.sh与sh iperf_testcode.sh行为一致:内核对无 shebang非 ELF 文件返回
ENOEXEC,busybox 经/proc/self/exe正确 re-exec 到/bin/sh并把脚本当参数解释执行。实际行为
./iperf_testcode.sh报Is a directory(EISDIR)并直接失败,回退链断在/proc/self/exe→"/"。✅ 修复方案
clone_ops.rs:fork/clone时从父进程拷贝exe_path到子进程,修复
/proc/self/exe解析(根因修复)。exec_ops.rs/exec_loader.rs/task/mod.rs:execve目标非普通文件时按真实 inode 类型返回 errno——仅真目录返回
EISDIR,其余(字符/块设备、fifo、socket)返回
EACCES;新增ExecImageError::NotRegular(InodeType)携带类型信息。adapter.rs:stat/statx的st_mode在缺少S_IFMT类型位时,按
inode_type补全(S_IFREG/S_IFDIR/S_IFLNK/...)。proc/inode.rs:procfs 符号链接 inode 的mode补上S_IFLNK类型位。涉及文件:
clone_ops.rs、exec_ops.rs、exec_loader.rs、syscall/task/mod.rs、vfs/adapter.rs、fs/proc/inode.rs🖥️ 环境信息
qemu-system-riscv64 -machine virtnightly-2025-10-28fs-riscv.img(ext4,busybox 用户态,/proc由 rcS 挂载)59dc7e8(缺陷存在于此前版本)📝 截图或日志
/ # ./iperf_testcode.sh
/bin/sh: ./iperf_testcode.sh: Is a directory
/ # sh iperf_testcode.sh
OS COMP TEST GROUP START iperf
proc/inode.rs中/proc/<pid>/exe动态软链的兜底unwrap_or_else(|| "/".to_string())未改动。exe_path传递修复后正常路径不再触发它,但「未知 exe 兜底成根目录」本身是把 ENOEXEC 放大成 EISDIR 的
诱因,建议后续改为返回空串或让 readlink 报错,避免再指向
/。