Skip to content

feat(starry-kernel): add PTRACE_SEIZE flow and PTRACE_LISTEN for strace support#1323

Open
WellDown64 wants to merge 4 commits into
rcore-os:devfrom
WellDown64:feat/ptrace-listen
Open

feat(starry-kernel): add PTRACE_SEIZE flow and PTRACE_LISTEN for strace support#1323
WellDown64 wants to merge 4 commits into
rcore-os:devfrom
WellDown64:feat/ptrace-listen

Conversation

@WellDown64

Copy link
Copy Markdown
Contributor

Summary

在 StarryOS 上支持 strace 通过 PTRACE_SEIZE 流程运行,同时补齐 PTRACE_LISTEN
和相关事件机制。

修改要点

  • signal.rs: Continue 类信号(SIGCONT)不产生 ptrace stop。shell 启动前台作业时发送的
    SIGCONT 会先于 strace child 的 kill(SIGSTOP) 被出队,之前会产生一个虚假的 SIGCONT stop
    打乱 strace 初始化。
  • ptrace.rs: 实现 PTRACE_LISTEN (0x4208)。strace 在 SEIZE 流程中将 TE_GROUP_STOP 转为
    job-control stop 时依赖此操作。
  • ptrace.rs: PTRACE_INTERRUPT 发送 SIGSTOP 前设置 PTRACE_EVENT_STOP (128) pending
    event,使 wait status 高 16 位携带 EVENT_STOP 标记。strace 据此区分 group-stop 和普通信号
    stop,走 TE_RESTART 路径。
  • ptrace.rs: PTRACE_SEIZE 通过 data 参数接受 ptrace options(strace 将
    ptrace_setoptions=0x51 作为第 4 参数传入),在 SEIZE 时立即存储。同时将
    PTRACE_O_TRACESECCOMP、PTRACE_O_EXITKILL 加入 SETOPTIONS 的 valid_mask。
  • execve.rs: exec stop 对 PTRACE_ATTACH/PTRACE_SEIZE 的 tracee 同样触发(之前仅限
    PTRACE_TRACEME)。
  • user.rs: exec 时跳过 syscall exit stop,使 exec event 到达时 TCB_INSYSCALL 仍置位。否则
    exit stop 先清除该标志导致 strace 报 "Stray PTRACE_EVENT_EXEC" 并进入错误恢复路径。

测试

在 riscv64 QEMU 上运行 strace -d echo hello,输出完整的系统调用追踪。

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review 总结

变更概述

本 PR 为 StarryOS 内核添加了完整的 PTRACE_SEIZE 流程支持和 PTRACE_LISTEN 实现,使 strace 能够通过 SEIZE 路径正常运行。

实现分析

ptrace.rs (+43/-3):

  • 新增 PTRACE_LISTEN (0x4208) 系统调用实现,正确地将 ptrace-stop 转换为 job-control stop
  • PTRACE_SEIZE 现在通过 data 参数接受 ptrace options,与 Linux 行为一致(strace 将 ptrace_setoptions 作为第 4 参数传入)
  • PTRACE_INTERRUPT 在发送 SIGSTOP 前正确设置 PTRACE_EVENT_STOP (128) pending event,使 wait status 高 16 位携带 EVENT_STOP 标记,strace 据此区分 group-stop 和普通信号 stop
  • SETOPTIONS valid_mask 新增 PTRACE_O_TRACESECCOMPPTRACE_O_EXITKILL

signal.rs (+8/-0):

  • Continue 类信号(SIGCONT)不产生 ptrace-stop,防止 shell 的 SIGCONT 干扰 strace 初始化序列

user.rs (+9/-6):

  • exec 时跳过 syscall exit stop,保持 TCB_INSYSCALL 置位,避免 strace 报 "Stray PTRACE_EVENT_EXEC"

测试用例 (+278/-0):

  • 新增 test-ptrace-listen C 测试,覆盖 3 个场景:非 traced 进程 LISTEN 返回 ESRCH、运行中的 SEIZE'd tracee LISTEN 返回 ESRCH、group-stop 后 LISTEN + SIGCONT 恢复
  • 测试位于 test-suit/starryos/qemu-smp1/system/,由系统 CMake 自动发现并构建,安装到 /usr/bin/starry-test-suit/
  • 仅在 riscv64 架构启用(匹配 starry_arch_filtered_executable

CI 状态

  • Check formatting / run_host: ✅ 通过
  • Run sync-lint / run_container: ✅ 通过
  • Run clippy / run_host: 进行中(尚未发现失败)
  • QEMU 测试(各架构): 进行中
  • 无失败项,run_container 矩阵任务按预期 skip(fork PR)

重复/重叠分析

  • 搜索了相关 open PR,仅有 #1314(x86_64 ptrace GDB 对齐)涉及 ptrace 但范围不同,无重叠
  • 本 PR 专注于 SEIZE/LISTEN/strace 流程,与 GDB 调试路径互补

代码质量

  • 实现逻辑与 Linux ptrace(2) 语义一致
  • ptrace_listen 正确清理 singlestep/syscall_trace 标志后以原始信号恢复执行
  • exec-stop pending 重排序逻辑正确,避免了 syscall exit stop 清除关键状态
  • 测试框架独立、结构清晰,断言精确

结论

无阻塞问题。PR 实现正确、测试覆盖合理、CI 格式/lint 检查通过。

Powered by mimo-v2.5-pro

@ZR233 ZR233 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

当前 head:205f5c98d2e8b60a7c205a0088828554fdd38d6f。

需要先修复编译问题:os/StarryOS/kernel/src/syscall/task/ptrace.rs:461NT_PRSTATUS => ptrace_getregset_prstatus(pid, data) 在 x86_64/aarch64/loongarch64 构建下找不到目标函数。当前 PR 把 ptrace_getregset_prstatus 限定成了 #[cfg(target_arch = "riscv64")],而 fallback 又是 not(any(riscv64, aarch64, loongarch64, x86_64)),所以这些已支持架构没有任何可见定义。

CI 的 Run clippy / run_host 已因此失败;我本地也用 cargo xtask clippy --package starry-kernel 复现,停在 [1/17] starry-kernel (base),报同一个 E0425。请补齐各支持架构的 GETREGSET/NT_PRSTATUS 实现,或调整 dispatcher/cfg 让未支持架构明确返回 Unsupported,然后重新跑 clippy 和相关 test-ptrace-listen qemu 用例。

补充检查:没有未解决 review thread;未发现同名/重复开放 PR;git diff --check origin/dev...HEAD 通过。运行时测试因当前编译失败未继续执行。

…EME path

Three changes so that "strace <command>" runs correctly:

  - signal: skip ptrace-stop for Continue-disposition signals.  SIGCONT
    sent by the shell's job-control to the foreground process group was
    dequeued after PTRACE_TRACEME and created a spurious stop before the
    expected SIGSTOP, confusing strace's startup sequence.

  - ptrace: return EIO (not EPERM) from PTRACE_SEIZE of self.  strace's
    test_ptrace_seize() interprets EPERM as "SEIZE works", enabling the
    full SEIZE attach path, which requires PTRACE_EVENT_STOP,
    LISTEN, and exec-stop plumbing that StarryOS does not yet provide.
    EIO triggers the "doesn't work" fallback to the well-tested TRACEME
    path.

  - user: skip the syscall-exit stop when the exec-stop is pending.
    Otherwise the exit stop clears strace's TCB_INSYSCALL before the
    exec event arrives, causing a "Stray PTRACE_EVENT_EXEC" error and
    permanent state desync in strace's syscall-entry/exit tracking.
  Four changes so that "strace <command>" works on the SEIZE
  attach path, removing the need for the EIO-on-self-seize
  workaround:

  - ptrace: pass the options argument through PTRACE_SEIZE
    (strace uses the 4th "data" parameter, not the 3rd "addr").
    Accept PTRACE_O_TRACESECCOMP / PTRACE_O_EXITKILL in the
    SETOPTIONS valid mask.  Restore EPERM on self-SEIZE.

  - ptrace: tag the stop from PTRACE_INTERRUPT with
    PTRACE_EVENT_STOP (128) so that the tracer sees the event
    in the upper 16 bits of the wait status and handles it as a
    group-stop (TE_GROUP_STOP / TE_RESTART).

  - ptrace: add PTRACE_LISTEN (0x4208).  strace's SEIZE flow
    uses LISTEN to transition a ptrace-stop into a job-control
    stop for TE_GROUP_STOP events.

  - execve: fire the exec-stop for SEIZE/ATTACH'ed tracees too
    (previously only TRACEME), so they receive PTRACE_EVENT_EXEC.

@ZR233 ZR233 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审当前 head edd4caddd00f7385d71356894dad7e191fae8247。这轮已经修掉了之前 GETREGSET/NT_PRSTATUS 在非 riscv64 架构下不可见的问题,但当前 head 还不能合入:GitHub CI 的 Check formatting / run_host 失败,本地也用 cargo fmt --check 复现了同一问题。

具体格式化差异在:os/StarryOS/kernel/src/syscall/task/execve.rsset_ptrace_exec_stop_pending() 后多出空行;os/StarryOS/kernel/src/task/user.rs 中多处函数调用需要按 rustfmt 结果收缩/换行。请先运行 cargo fmt 并重新推送。

补充核验:git diff --check origin/dev...origin/pr/1323 通过;本地 cargo xtask sync-lint 通过;review threads 为空;新增 test-ptrace-listen 放在 test-suit/starryos/qemu-smp1/system/,分类位置合理;未发现同功能重复开放 PR。由于当前格式化检查已阻塞,本轮没有继续把 runtime 行为作为可合入依据。格式修复后请重新跑 cargo xtask clippy --package starry-kernel 和对应 test-ptrace-listen qemu 用例。

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审阅总结

变更概述

本 PR 为 StarryOS 内核添加完整的 PTRACE_SEIZE 流程支持和 PTRACE_LISTEN 实现,使 strace 能通过 SEIZE 路径正常运行。

实现分析

ptrace.rs:

  • 新增 PTRACE_LISTEN (0x4208) 实现,正确将 ptrace-stop 转换为 job-control stop
  • PTRACE_SEIZE 通过 data 参数接受 ptrace options,与 Linux 语义一致
  • PTRACE_INTERRUPT 在发送 SIGSTOP 前正确设置 PTRACE_EVENT_STOP (128) pending event
  • SETOPTIONS valid_mask 新增 PTRACE_O_TRACESECCOMPPTRACE_O_EXITKILL

signal.rs: Continue 类信号(SIGCONT)不产生 ptrace-stop,防止 shell 的 SIGCONT 干扰 strace 初始化。

execve.rs: exec-stop 提前到寄存器重置之前触发,确保 ATTACH/SEIZE 的 tracee 也能收到 PTRACE_EVENT_EXEC。

user.rs: exec-stop 和 syscall-trace 交互逻辑重构,通过 match (exec_pending, syscall_trace) 正确覆盖各路径。

测试用例: test-ptrace-listen 覆盖 3 个场景(非 traced→ESRCH、运行中 SEIZE'd→ESRCH、group-stop 后 LISTEN+SIGCONT),位于 qemu-smp1/system/,仅 riscv64,符合当前验证范围。

重复/重叠分析

搜索了 open PR,未发现与 ptrace SEIZE/LISTEN 功能重叠的 PR。PR #1314 涉及 ptrace GDB 对齐,范围不同,无冲突。

CI 状态

  • Check formatting / run_host:失败
  • Run sync-lint: skipped(fork PR 预期行为)
  • Detect changed paths: ✅ 通过
  • 其余 publish/container 矩阵 job: skipped(fork PR 预期行为)

阻塞问题

CI 格式化检查失败Check formatting / run_host 未通过,本地 cargo fmt --check 复现。需要运行 cargo fmt 后重新推送。

Powered by mimo-v2.5-pro

@WellDown64
WellDown64 force-pushed the feat/ptrace-listen branch from edd4cad to 6dd373a Compare June 25, 2026 07:27

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审总结(head: 6dd373a7

变更概述

为 StarryOS 内核添加完整的 PTRACE_SEIZE 流程支持和 PTRACE_LISTEN 实现,使 strace 能通过 SEIZE 路径运行。变更范围:7 文件,+378/-23。

本地验证结果

  • cargo fmt --check:✅ 通过(之前的格式化问题已修复)
  • cargo clippy --manifest-path os/StarryOS/kernel/Cargo.toml --all-features -- -D warnings:✅ 通过

CI 状态

  • Check formatting / run_host:✅ 通过
  • Run sync-lint / run_container:✅ 通过
  • Test arceos riscv64/aarch64 qemu:✅ 通过
  • Test axvisor riscv64/aarch64 qemu:✅ 通过
  • Test axloader HTTP smoke:✅ 通过
  • Test starry riscv64 qemu / run_container:❌ 失败(Run command 步骤失败)
  • Run clippy / run_host:因上述失败被取消
  • 其他 board/container 测试:因上述失败被取消

代码审查

实现质量:

  1. ptrace.rs:PTRACE_LISTEN 实现正确,正确地将 ptrace-stop 转换为 job-control stop。PTRACE_SEIZE 接受 data 参数存储 ptrace options,与 Linux 语义一致。PTRACE_INTERRUPT 正确设置 PTRACE_EVENT_STOP (128) pending event。SETOPTIONS valid_mask 新增 PTRACE_O_TRACESECCOMPPTRACE_O_EXITKILL,符合 Linux 规范。

  2. signal.rs:Continue 类信号(SIGCONT)不产生 ptrace-stop,正确防止 shell SIGCONT 干扰 strace 初始化。

  3. execve.rs:exec-stop 提前到寄存器重置之前触发,确保所有 ptrace tracees 都能收到 PTRACE_EVENT_EXEC。逻辑合理。

  4. user.rs:exec-stop 和 syscall-trace 交互重构通过 match (exec_pending, syscall_trace) 覆盖各路径,逻辑正确。pre-execve stop 创建在 syscall-trace 未激活时正确触发。

  5. 测试用例test-ptrace-listen 覆盖 3 个场景(ESRCH for non-traced、ESRCH for running seized、group-stop LISTEN + SIGCONT),结构清晰。仅 riscv64 架构启用。

重复/重叠分析

搜索了 open PR,PR #1314 涉及 x86_64 ptrace GDB 对齐,范围不同,无冲突。

阻塞问题

CI Test starry riscv64 qemu 失败。这是运行 StarryOS 完整 QEMU 测试套件的 job,当前失败原因需要进一步调查。可能是 PR 的 ptrace 行为变更影响了其他测试用例,也可能是环境问题。请检查该 CI job 日志确认失败原因。

如果该失败与本 PR 无关(例如是已知的 flaky test 或环境问题),请提供说明;如果是由本 PR 引入的回归,请修复后重新推送。

Powered by mimo-v2.5-pro

| PTRACE_O_TRACEFORK
| PTRACE_O_TRACEVFORK
| PTRACE_O_TRACECLONE
| PTRACE_O_TRACEEXEC

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SEIZE 时存储 options 的 valid_mask 与 SETOPTIONS 中的重复定义。建议提取为常量 SEIZE_VALID_OPTIONS 或类似名称,避免两处维护不一致的风险。当前两者内容一致,暂不阻塞。

Some(Sysno::execve | Sysno::execveat)
)
{
crate::syscall::ptrace_notify_exec(thr.proc_data.proc.pid());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这段 pre-execve stop 逻辑依赖 Sysno::new(saved_sysno) 匹配 execve | execveat,但 saved_sysno 是在 entry 时保存的。如果内核支持其他能触发 exec 的 syscall(如 fexecve 的未来变体),这里需要同步更新。当前范围足够,仅作提示。

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审总结(head: 6dd373a7

变更概述

为 StarryOS 内核添加完整的 PTRACE_SEIZE 流程支持和 PTRACE_LISTEN 实现,使 strace 能通过 SEIZE 路径运行。变更范围:7 文件,+378/-23。

CI 状态

  • Check formatting / run_host:✅ 通过
  • Run sync-lint / run_container:✅ 通过
  • Test arceos riscv64/aarch64 qemu:✅ 通过
  • Test axvisor riscv64/aarch64 qemu:✅ 通过
  • Test axloader HTTP smoke:✅ 通过
  • Test starry riscv64 qemu / run_container:❌ 失败(Run command 步骤)
  • Run clippy / run_host:被取消(因 test 失败触发的 fail-fast)
  • 其他 board/container 测试:被取消

代码审查

实现质量总体良好:

  1. ptrace.rs:PTRACE_LISTEN 正确将 ptrace-stop 转为 job-control stop;PTRACE_SEIZE 接受 data 参数存储 options,与 Linux 语义一致;PTRACE_INTERRUPT 正确设置 PTRACE_EVENT_STOP pending event。valid_mask 在 ptrace_setoptionsptrace_seize 中有重复定义(见下方 inline 建议),但不阻塞。

  2. signal.rs:Continue 类信号不产生 ptrace-stop,正确防止 SIGCONT 干扰 strace 初始化。

  3. execve.rs:exec-stop 提前到寄存器重置之前触发,确保所有 tracee 收到 PTRACE_EVENT_EXEC。逻辑合理。

  4. user.rsmatch (exec_pending, syscall_trace) 正确覆盖各路径——非 execve syscall exit、execve with syscall-trace active、execve after pre-execve stop without syscall-trace 等。pre-execve stop 逻辑在 trace_state != Entry 时正确触发。

  5. 测试用例test-ptrace-listen 覆盖 3 个场景,结构清晰,仅 riscv64 启用。

前序 review 评论

  • ZR233(CHANGES_REQUESTED):编译和格式化问题已修复。
  • mai-team-app inline comments:关于 valid_mask 重复和 fexecve 未来扩展的建议均属合理但非阻塞,可以后续优化。

阻塞问题

CI Test starry riscv64 qemu / run_container 失败。 这是运行 StarryOS 完整 QEMU 测试套件的 job。本 PR 修改了 signal.rs(SIGCONT 不再产生 ptrace-stop)和 user.rs(exec-stop 时序),这些变更直接影响内核信号和 ptrace 行为,极有可能是导致测试失败的原因。

arceos 和 axvisor 的 riscv64/aarch64 测试均已通过,排除了基础设施问题。

请调查该 CI job 失败的具体原因:如果是由本 PR 引入的回归,请修复后重新推送;如果是已知的 flaky test 或 dev 分支已有的问题,请提供说明(例如 dev 分支最近的 CI 运行链接)。

建议(非阻塞)

ptrace_seizeptrace_setoptions 中的 valid_mask 完全一致,建议提取为模块级常量 SEIZE_VALID_OPTIONS 以避免后续维护不一致。

Powered by mimo-v2.5-pro

| PTRACE_O_TRACEFORK
| PTRACE_O_TRACEVFORK
| PTRACE_O_TRACECLONE
| PTRACE_O_TRACEEXEC

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(非阻塞建议)此处 valid_maskptrace_setoptions 中的定义完全一致。建议提取为模块级常量 const SEIZE_VALID_OPTIONS: usize = ...;,两处共享引用,避免后续新增 option 时只改一处遗漏另一处。

@ZR233 ZR233 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复查当前 head 6dd373a7911544524488ab5bbfc872279605b7f1,之前格式化问题已修复,但当前新增的 test-ptrace-listen 本身在 riscv64 QEMU 中失败,和远端 Test starry riscv64 qemu / run_container 红叉一致,因此还不能合入。

本地复现命令:

cargo xtask starry test qemu --arch riscv64 -c qemu-smp1/system/test-ptrace-listen

失败核心输出:

FAIL | .../test-ptrace-listen/src/main.c:116 | sync write to child | errno=9 (Bad file descriptor)
FAIL | .../test-ptrace-listen/src/main.c:134 | PTRACE_LISTEN | expected=0 got=-1 | errno=3 (No such process)
STARRY_SYSTEM_TEST_FAILED: /usr/bin/starry-test-suit/test-ptrace-listen status=1

根因在测试同步逻辑:test_listen_group_stop_then_cont() 只创建了一个 pipe(sync_pipe),但随后把它当成双向管道使用。子进程关闭 sync_pipe[0] 后又从 sync_pipe[1] 读取;父进程关闭 sync_pipe[1] 后又向 sync_pipe[0] 写入,所以第 116 行会稳定得到 EBADF,之后子进程退出,后续 PTRACE_LISTEN/SIGCONT 检查也跟着失真。

请改成两个单向 pipe(child->parent ready,parent->child go),或者使用其他明确的双向同步机制;修复后请重新跑上面的定向 qemu 用例,再跑对应的 riscv64 Starry 测试矩阵。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants