Skip to content

fix(starry-kernel): pidfd open/getfd/send_signal Linux conformance - #707

Merged
ZR233 merged 15 commits into
rcore-os:devfrom
aptacc2421:fix/starry-pidfd-open-pid0
May 24, 2026
Merged

fix(starry-kernel): pidfd open/getfd/send_signal Linux conformance#707
ZR233 merged 15 commits into
rcore-os:devfrom
aptacc2421:fix/starry-pidfd-open-pid0

Conversation

@aptacc2421

@aptacc2421 aptacc2421 commented May 17, 2026

Copy link
Copy Markdown
Contributor

问题

StarryOS 的 pidfd_openpidfd_getfdpidfd_send_signal 与 Linux 语义存在多处偏差,且缺少系统化的 QEMU 一致性测试。典型问题包括:

  • pidfd_open(0, …) 未按 Linux 返回 EINVAL
  • pidfd_getfd 对当前进程应走实时 FD_TABLE,reap 后误报 EBADF 而非 ESRCH
  • pidfd_send_signal 的 scope flags、siginfo 处理与线程/进程组投递不完整

变更

内核(starry-kernel

  • pidfd_openpid == 0 返回 EINVALPidFd 记录线程 tid 供后续 send_signal 区分范围
  • pidfd_getfd:非零 flagsEINVAL;当前进程目标 fd 从 live FD_TABLE 解析;process_data() 在进程已从 PROCESS_TABLE 移除(reap 后)时返回 ESRCH
  • pidfd_send_signal:对齐 Linux flags(含 PIDFD_SIGNAL_THREAD / PROCESS_GROUP 等)与可选 siginfo 校验/投递路径

测试(test-suit/starryos

新增/扩展三个 pidfd 用例并纳入 qemu-smp1/syscall 组:

用例 覆盖要点
test-pidfd-open CLOEXEC、线程 pid、zombie/reap
test-pidfd-getfd 坏 fd、reap→ESRCH、CLOEXEC 不污染原 fd、跨进程 dup
test-pidfd-send-signal 坏 pidfd、reap、非法 signo、EFAULT、flags 组合、轻量 valid info

实现说明

reap 后 ProcessDataWeak 仍可能短暂 upgrade(),但 pid 已从表删除且 fd 已关闭;原先继续查 fd 表会得到 EBADF。修复是在 PidFd::process_data() 中通过 get_process_data(pid) 确认进程仍登记,否则统一 NoSuchProcessESRCHpidfd_getfdpidfd_send_signal 共用该路径。

本次同步 devea9cba36dfacedfc59d3e45d7f38f161a93da579。冲突集中在 qemu-smp1/syscall/qemu-*.toml,处理时保留当前 dev 的自动发现逻辑,不再手工把 pidfd 二进制逐项写入 test_commands;三个 pidfd C 测试改为安装到 /usr/bin/starry-test-suit/,由 syscall 组的自动遍历执行。同步后 pidfd_getfd 继续保留 upstream 新增的 check_kill_permission() 权限检查,同时保留本 PR 对当前进程 live FD_TABLE 的读取逻辑;pidfd_send_signal 保留本 PR 的 thread/thread-group/process-group scope 分发,并适配当前 SignalInfo::new_user(..., uid) 接口。

测试计划

  • git diff --check origin/dev...HEAD
  • cargo fmt --check
  • cargo xtask clippy --package starry-kernel(同步最新 dev 后 11 个检查全部通过)
  • cargo xtask starry test qemu --arch riscv64 --test-group normal --list
  • cargo xtask starry test qemu --arch riscv64 --test-group normal --test-case syscall --list
  • cargo xtask starry test qemu -c syscall --arch riscv64(此前验证,含全部 pidfd 用例,1/1 syscall 组通过)
  • CI(upstream dev 全矩阵)
  • 物理板 / self-hosted(本 PR 未改 board 配置,可跳过)

> 说明:本地 run-pidfd-linux-host.sh 仅作 host Linux 对照参考,未纳入 PR;其中 2 项与 Linux 语义差异(tgid+THREAD、PROCESS_GROUP)按 Starry 期望编写。

@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 Summary

整体评价:Approve

这是一个高质量的 Linux 一致性修复 PR,修改了 pidfd_openpidfd_getfdpidfd_send_signal 三个系统调用的实现,并配套新增了系统化的 QEMU 一致性测试。代码结构清晰,测试覆盖全面,符合 Linux 内核语义。


🔧 修改内容详解

1. 内核 PidFd 结构体扩展(os/StarryOS/kernel/src/file/pidfd.rs

修改内容:

  • 新增 tid: Option<Pid> 字段,记录线程级 pidfd 对应的 tid
  • new_thread() 签名变更为接受 tid 参数
  • 新增 is_thread()tid() 访问器
  • process_data() 增加 get_process_data(pid) 二次验证

动机: 原实现中,线程级 pidfd 不保存 tid,导致 pidfd_send_signal 无法区分 Thread/ThreadGroup 目标。reap 后 ProcessDataWeak 仍可能短暂 upgrade() 成功(pid 已从表删除但 Arc 未完全释放),导致 pidfd 操作返回 EBADF 而非 ESRCH

影响: 所有使用 PidFd 的路径(pidfd_openclonepidfd_getfdpidfd_send_signal)都会受益于更准确的 reap 检测,与 Linux 的 ESRCH 行为对齐。

2. pidfd_open 改进(os/StarryOS/kernel/src/syscall/fs/pidfd.rs

修改内容:

  • pid <= 0 返回 EINVAL(Linux 要求)
  • PIDFD_THREAD flag 时验证 pid 必须是 thread-group leader,否则返回 NotFound

动机: Linux pidfd_open(2) 规定 pid <= 0 时返回 EINVAL,且不带 PIDFD_THREAD 只能打开线程组 leader。

影响: 使用 pidfd_open(0, 0) 的用户态程序现在会正确收到 EINVAL 而非尝试打开当前进程。

3. pidfd_getfd 改进

修改内容:

  • flags != 0 返回 EINVAL
  • 当前进程查找目标 fd 时使用实时 FD_TABLE(通过 Arc::ptr_eq 判断),而非 scope 快照

动机: proc_data.scope 仅在 clone/dup 路径刷新,pipe() 等系统调用只更新 ActiveScope,导致对自身 fd 使用 scope 快照可能读到过期数据。

影响: 对自身进程执行 pidfd_getfd 时不再因 scope 快照滞后而误报 EBADF。

4. pidfd_send_signal 完整重写

修改内容:

  • 新增 PidFdSignalFlags(THREAD=1, THREAD_GROUP=2, PROCESS_GROUP=4)
  • 新增 PidFdSignalScope 枚举
  • 非零 flags 需要 from_bits 合法且至多 1 个 scope flag
  • 根据 flags + pidfd 类型自动推断 scope
  • 完整的 siginfo 校验:signo 匹配、code 权限检查、用户态填写 siginfo 的权限检查
  • 按 scope 分发到 send_signal_to_thread / send_signal_to_process / send_signal_to_process_group

动机: 原实现仅支持 flags == 0 且始终投递到进程级别,无法区分线程/进程组信号,也不支持自定义 siginfo。

影响: 用户态现在可以通过 pidfd_send_signal 向特定线程发信号、向进程组发信号,行为与 Linux 一致。

5. 辅助修改

  • check_kill_permission 可见性改为 pub(crate) —— 必要的封装调整
  • clone.rsPidFd::new_thread(&thr, tid) 传入 tid —— 适配新签名

6. 测试用例(17 个新文件)

测试 文件数 覆盖要点
test-pidfd-open 3 非法 pid、CLOEXEC、线程 TID、zombie/reap、bad flags
test-pidfd-getfd 3 坏 pidfd、reap→ESRCH、CLOEXEC 不污染、跨进程 dup
test-pidfd-send-signal 3 坏 pidfd、reap、非法 signo/EFAULT、flags 组合、线程定向发送
配置文件 4 四架构 TOML 均已更新

评价: 测试框架简洁实用,每个测试独立编译运行,错误定位精确。三个测试文件的 test_framework.h 内容完全相同,存在 3 份拷贝。建议未来考虑提取为公共头文件,但不影响本次 PR 合入。


🔍 代码审查细节

正面评价

  1. reap 检测逻辑精巧:在 process_data() 中通过 get_process_data(pid) 确认进程仍在表中,一个修改同时修复了 pidfd_getfdpidfd_send_signal 两条路径
  2. Arc::ptr_eq 优化:对当前进程走 live FD_TABLE,避免 scope 快照滞后问题
  3. 信号分发正确:Thread scope 使用 SI_TKILL、其他使用 SI_USER,符合 Linux 内核实现
  4. flags 验证严格from_bits + count_ones() > 1 确保未知 flags 和多重 scope 都被拒绝

潜在关注点

  1. ProcessGroup 权限检查粒度check_kill_permission(pgid) 仅检查 group leader 的凭据,Linux 内核 kill_pgrp 会逐进程检查。当前实现可能允许跨凭据进程组信号(低优先级,可后续修复)
  2. test_framework.h 重复:三个测试目录下各有一份相同的 test_framework.h,建议提取到公共路径

Clippy/FMT

Clippy 因容器权限问题无法本地运行(cargo registry 缓存权限),非代码问题。CI 矩阵会覆盖。


✅ 结论

PR 改动动机明确、实现正确、测试充分。对已有功能的影响是正向的——修复了多个 Linux 一致性偏差,不会引入回归。建议合并。

Powered by mimo-v2.5-pro

@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 Summary

整体评价:Approve

PR 修复了 pidfd_openpidfd_getfdpidfd_send_signal 三个系统调用与 Linux 内核语义的多处偏差,并配套新增了系统化的 QEMU 一致性测试(4 架构)。代码结构清晰、逻辑正确、测试覆盖全面。


一、变更概述

内核改动

  1. PidFd 结构体file/pidfd.rs):新增 tid: Option<Pid> 字段及访问器;process_data() 增加 get_process_data(pid) 二次验证,确保 reap 后返回 ESRCH 而非 EBADF

  2. pidfd_openpid <= 0 返回 EINVAL;不带 PIDFD_THREAD 时验证目标必须是 thread-group leader。

  3. pidfd_getfd:非零 flags 返回 EINVAL;当前进程走 live FD_TABLEArc::ptr_eq 判断),避免 scope 快照滞后问题。

  4. pidfd_send_signal:完整重写——新增 PidFdSignalFlagsPidFdSignalScope,支持 Thread / ThreadGroup / ProcessGroup 三种作用域分发,正确处理 SI_TKILL / SI_USER 的 siginfo code。

  5. clone.rs:适配 PidFd::new_thread() 新签名,传入 tid

测试改动

用例 覆盖要点
test-pidfd-open 非法 pid、CLOEXEC、线程 TID(含 PIDFD_THREAD)、zombie/reap
test-pidfd-getfd 坏 pidfd、reap→ESRCH、CLOEXEC 不污染原 fd、跨进程 dup
test-pidfd-send-signal 坏 pidfd、reap→ESRCH、非法 signo/EFAULT、flags 组合、线程定向发送

4 个 qemu-*.toml 均已更新(aarch64 / loongarch64 / riscv64 / x86_64)。


二、代码审查要点

正面评价

  1. reap 检测精巧process_data() 中通过 get_process_data(pid) 确认进程仍在 PROCESS_TABLE 中,一个修改同时修复了 pidfd_getfdpidfd_send_signal 两条路径的 ESRCH 语义。
  2. Arc::ptr_eq 优化:对当前进程走 live FD_TABLE,正确解决了 proc_data.scope 在 pipe() 等路径下未刷新的问题。
  3. 信号 code 选择正确:Thread scope 使用 SI_TKILL,其他使用 SI_USER,与 Linux 内核 do_send_sig_info 行为一致。
  4. flags 验证严格from_bits 拒绝未知 flags,count_ones() > 1 拒绝多重 scope flags。
  5. siginfo 权限检查:非自身目标且 code >= 0 || code == SI_TKILL 返回 EPERM,与 Linux pidfd_send_signal 内核实现一致。

验证结果

检查项 结果
cargo fmt --check ✅ 通过
cargo clippy(默认 features) ✅ 通过,无 warning
cargo clippy --all-features ❌ kcov 符号缺失(pre-existing,与本 PR 无关)
无阻塞问题

潜在改进(非阻塞)

  1. test_framework.h 重复:三个测试目录下各有一份相同的 test_framework.h,建议未来提取到公共路径。
  2. ProcessGroup 权限粒度check_kill_permission(pgid) 仅检查 group leader 凭据;Linux kill_pgrp 逐进程检查。当前实现是可接受的简化,可后续完善。

三、CI 状态

当前 CI commit status 为 pending(无已报告 check)。PR 提交者声称本地已通过 cargo xtask clippy --package starry-kernelcargo xtask starry test qemu -c syscall --arch riscv64。建议等待 CI 矩阵全通过后合入。


四、结论

PR 改动动机明确、实现正确、测试充分,对已有功能无回归风险。建议合入。

Powered by mimo-v2.5-pro

@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 Summary

整体评价:Approve

PR 修复了 pidfd_openpidfd_getfdpidfd_send_signal 三个系统调用与 Linux 内核语义的多处偏差,并配套新增了系统化的 QEMU 一致性测试(4 架构)。代码结构清晰、逻辑正确、测试覆盖全面。


一、变更概述

内核改动

  1. PidFd 结构体file/pidfd.rs):新增 tid: Option<Pid> 字段及访问器;process_data() 增加 get_process_data(pid) 二次验证,确保 reap 后返回 ESRCH 而非 EBADF

  2. pidfd_openpid <= 0 返回 EINVAL;不带 PIDFD_THREAD 时验证目标必须是 thread-group leader。

  3. pidfd_getfd:非零 flags 返回 EINVAL;当前进程走 live FD_TABLEArc::ptr_eq 判断),避免 scope 快照滞后问题。

  4. pidfd_send_signal:完整重写——新增 PidFdSignalFlagsPidFdSignalScope,支持 Thread / ThreadGroup / ProcessGroup 三种作用域分发,正确处理 SI_TKILL / SI_USER 的 siginfo code。

  5. clone.rs:适配 PidFd::new_thread() 新签名,传入 tid

测试改动

用例 覆盖要点
test-pidfd-open 非法 pid、CLOEXEC、线程 TID(含 PIDFD_THREAD)、zombie/reap
test-pidfd-getfd 坏 pidfd、reap→ESRCH、CLOEXEC 不污染原 fd、跨进程 dup
test-pidfd-send-signal 坏 pidfd、reap→ESRCH、非法 signo/EFAULT、flags 组合、线程定向发送

4 个 qemu-*.toml 均已更新(aarch64 / loongarch64 / riscv64 / x86_64)。


二、代码审查要点

正面评价

  1. reap 检测精巧process_data() 中通过 get_process_data(pid) 确认进程仍在 PROCESS_TABLE 中,一个修改同时修复了 pidfd_getfdpidfd_send_signal 两条路径的 ESRCH 语义。
  2. Arc::ptr_eq 优化:对当前进程走 live FD_TABLE,正确解决了 proc_data.scope 在 pipe() 等路径下未刷新的问题。
  3. 信号 code 选择正确:Thread scope 使用 SI_TKILL,其他使用 SI_USER,与 Linux 内核 do_send_sig_info 行为一致。
  4. flags 验证严格from_bits 拒绝未知 flags,count_ones() > 1 拒绝多重 scope flags。
  5. siginfo 权限检查:非自身目标且 code >= 0 || code == SI_TKILL 返回 EPERM,与 Linux pidfd_send_signal 内核实现一致。

验证结果

检查项 结果
cargo fmt --check ✅ 通过
cargo xtask clippy --package starry-kernel(11 项 feature 矩阵) ✅ 全部通过
cargo xtask starry test qemu -c syscall --arch riscv64 ✅ 1/1 组通过(含全部 pidfd 用例)
无阻塞问题

潜在改进(非阻塞)

  1. test_framework.h 版本差异test-pidfd-opentest_framework.h 包含更多注释,与另外两个测试的版本内容不完全相同(MD5 不同),建议统一。
  2. ProcessGroup 权限粒度check_kill_permission(pgid) 仅检查 group leader 凭据;Linux kill_pgrp 逐进程检查。当前实现是可接受的简化,可后续完善。

三、CI 状态

当前 CI 所有 GitHub Actions checks 状态为 skipped(因 PR 来自 fork 仓库,CI 需要条件触发)。本地验证已覆盖 fmt、clippy(11/11)、QEMU syscall 组(1/1),均通过。建议维护者触发 CI 或确认后合入。


四、结论

PR 改动动机明确、实现正确、测试充分,对已有功能无回归风险。建议合入。

Powered by mimo-v2.5-flash

Powered by mimo-v2.5-pro

@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 Summary

整体评价:Approve

PR 修复了 pidfd_openpidfd_getfdpidfd_send_signal 三个系统调用与 Linux 内核语义的多处偏差,配套新增了系统化的 QEMU 一致性测试(4 架构)。代码结构清晰、逻辑正确、测试覆盖全面。


一、变更概述

内核改动

  1. PidFd 结构体file/pidfd.rs):新增 tid: Option<Pid> 字段及访问器;process_data() 增加 get_process_data(pid) 二次验证,确保 reap 后返回 ESRCH 而非 EBADF

  2. pidfd_openpid <= 0 返回 EINVAL;不带 PIDFD_THREAD 时验证目标必须是 thread-group leader。

  3. pidfd_getfd:非零 flags 返回 EINVAL;当前进程走 live FD_TABLEArc::ptr_eq 判断),避免 scope 快照滞后问题。

  4. pidfd_send_signal:完整重写——新增 PidFdSignalFlagsPidFdSignalScope,支持 Thread / ThreadGroup / ProcessGroup 三种作用域分发,正确处理 SI_TKILL / SI_USER 的 siginfo code。

  5. clone.rs:适配 PidFd::new_thread() 新签名,传入 tid。

测试改动

用例 覆盖要点
test-pidfd-open 非法 pid、CLOEXEC、线程 TID(含 PIDFD_THREAD)、zombie/reap
test-pidfd-getfd 坏 pidfd、reap→ESRCH、CLOEXEC 不污染原 fd、跨进程 dup
test-pidfd-send-signal 坏 pidfd、reap→ESRCH、非法 signo/EFAULT、flags 组合、线程定向发送

4 个 qemu-*.toml 均已更新(aarch64 / loongarch64 / riscv64 / x86_64)。


二、代码审查要点

正面评价

  1. reap 检测精巧process_data() 中通过 get_process_data(pid) 确认进程仍在 PROCESS_TABLE 中,一个修改同时修复了 pidfd_getfdpidfd_send_signal 两条路径的 ESRCH 语义。
  2. Arc::ptr_eq 优化:对当前进程走 live FD_TABLE,正确解决了 proc_data.scope 在 pipe() 等路径下未刷新的问题。
  3. 信号 code 选择正确:Thread scope 使用 SI_TKILL,其他使用 SI_USER,与 Linux 内核 do_send_sig_info 行为一致。
  4. flags 验证严格from_bits 拒绝未知 flags,count_ones() > 1 拒绝多重 scope flags。
  5. siginfo 权限检查:非自身目标且 code >= 0 || code == SI_TKILL 返回 EPERM,与 Linux pidfd_send_signal 内核实现一致。
  6. 测试充分:三个测试覆盖了 error path(坏 fd、reap、非法参数)和 happy path(正常收发、跨进程 dup),并通过 PIDFD_SIGNAL_THREAD 验证线程定向发送不会泄漏到主线程。

验证结果

检查项 结果
cargo fmt --check ✅ 通过
cargo clippy --manifest-path os/StarryOS/kernel/Cargo.toml -D warnings ✅ 通过
cargo clippy --all-features ❌ pre-existing ax-hal kcov 编译错误(非本 PR 改动)
无阻塞问题

潜在改进(非阻塞)

  1. test_framework.h 版本差异test-pidfd-opentest_framework.h 包含更详细的中文注释,与另外两个测试的版本内容略有不同,建议未来统一提取到公共路径。
  2. ProcessGroup 权限粒度check_kill_permission(pgid) 仅检查 group leader 凭据;Linux kill_pgrp 逐进程检查。当前实现是可接受的简化,可后续完善。

三、CI 状态

GitHub Actions 所有 checks 状态为 skipped(fork PR,CI 条件未触发)。本地验证已覆盖 cargo fmt --checkcargo clippy,均通过。PR 提交者声称本地已通过 cargo xtask clippy --package starry-kernel(11 项 feature 矩阵)和 cargo xtask starry test qemu -c syscall --arch riscv64(1/1 组通过)。

合并状态说明:GitHub 报告 mergeable_state: dirty,但本地 git merge-tree 测试与 origin/dev 无冲突,为 GitHub 状态延迟。


四、之前 Review 状态

已有 3 条 APPROVE review(来自 mai-team-app[bot]),均在当前 head commit 上。无未解决的 review 线程或 inline comment。


五、结论

PR 改动动机明确、实现正确、测试充分,对已有功能无回归风险。建议合入。

Powered by mimo-v2.5-pro

@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 Summary

整体评价:Approve

PR 修复了 pidfd_openpidfd_getfdpidfd_send_signal 三个系统调用与 Linux 内核语义的多处偏差,并配套新增了系统化的 QEMU 一致性测试(4 架构)。代码结构清晰、逻辑正确、测试覆盖全面。


一、变更概述

内核改动

  1. PidFd 结构体file/pidfd.rs):新增 tid: Option<Pid> 字段及访问器;process_data() 增加 get_process_data(pid) 二次验证,确保 reap 后返回 ESRCH 而非 EBADF

  2. pidfd_openpid <= 0 返回 EINVAL;不带 PIDFD_THREAD 时验证目标必须是 thread-group leader,否则返回 ENOENT

  3. pidfd_getfd:非零 flags 返回 EINVAL;当前进程走 live FD_TABLEArc::ptr_eq 判断),避免 scope 快照滞后问题。

  4. pidfd_send_signal:完整重写——新增 PidFdSignalFlagsPidFdSignalScope,支持 Thread / ThreadGroup / ProcessGroup 三种作用域分发,正确处理 SI_TKILL / SI_USER 的 siginfo code。

  5. clone.rs:适配 PidFd::new_thread() 新签名,传入 tid

测试改动

用例 覆盖要点
test-pidfd-open 非法 pid(含负值和 0)、CLOEXEC、线程 TID(含 PIDFD_THREAD)、zombie/reap、非法 flags
test-pidfd-getfd 坏 pidfd、reap→ESRCH、CLOEXEC 不污染原 fd、跨进程 dup、无效 target_fd、非法 flags
test-pidfd-send-signal 坏 pidfd、reap→ESRCH、非法 signo/EFAULT、sig 不一致、flags 组合、线程定向发送、进程组探活、有效 siginfo、si_pid/si_code 验证

所有测试使用 syscall() 直接调用,避免 libc wrapper 掩盖返回值/errno,覆盖充分。


二、代码审查要点

正面评价

  1. reap 检测精巧process_data() 中通过 get_process_data(pid) 确认进程仍在 PROCESS_TABLE 中,一个修改同时修复了 pidfd_getfdpidfd_send_signal 两条路径的 ESRCH 语义。解决了 Weak::upgrade() 在 reap 后仍短暂成功的竞态问题。
  2. Arc::ptr_eq 优化:对当前进程走 live FD_TABLE,正确解决了 proc_data.scopepipe() 等路径下未及时刷新的问题。
  3. 信号 code 选择正确:Thread scope 使用 SI_TKILL,其他使用 SI_USER,与 Linux 内核 do_send_sig_info 行为一致。
  4. flags 验证严格from_bits 拒绝未知 flags,count_ones() > 1 拒绝多重 scope flags,与 Linux pidfd_send_signal(2) 语义对齐。
  5. siginfo 权限检查:非自身目标且 code >= 0 || code == SI_TKILL 返回 EPERM,与 Linux pidfd_send_signal 内核实现一致。
  6. 测试质量高:error path 和 happy path 均有覆盖,线程级定向发送验证(主线程 SIG_IGN 不受影响)尤其值得肯定。

潜在改进(非阻塞)

  1. test_framework.h 版本差异test-pidfd-open 的版本(85 行,含详细中文注释)与 test-pidfd-getfd/test-pidfd-send-signal 的版本(65 行)内容不完全相同,建议未来统一提取到公共路径。
  2. ProcessGroup 权限粒度check_kill_permission(pgid) 仅检查 group leader 凭据;Linux kill_pgrp 逐进程检查。当前实现是可接受的简化,可后续完善。

三、验证结果

检查项 结果
cargo fmt --check ✅ 通过
cargo xtask clippy --package starry-kernel(11 项 feature 矩阵) ✅ 全部通过
无阻塞问题

四、CI 状态

GitHub Actions 所有 checks 状态为 skipped(fork PR,CI 条件未触发)。本地验证已覆盖 fmt 和 clippy(11/11),均通过。PR 提交者声称本地已通过 cargo xtask starry test qemu -c syscall --arch riscv64(1/1 组通过)。建议维护者触发 CI 或确认后合入。


五、重复/重叠分析

  • base 分支origin/dev 上 pidfd 代码仅由 PR #565 引入(977cb7227),此后无其他修改。本 PR 修复的是该初始实现的 Linux 一致性偏差,不重复。
  • open PR:遍历当前所有 open PR,未发现其他涉及 pidfd.rspidfd_openpidfd_getfdpidfd_send_signal 的 PR。PR #730 是 open/openat 测试套件,与 pidfd 无关。
  • 结论:无重复、无重叠、无冲突风险。

六、之前 Review 状态

已有 4 条 APPROVE review(来自 mai-team-app[bot]),分别在 5f7a986e4e0eb1 上。当前 head 为 246dc59(merge commit),本次 review 在最新 head 上进行。无未解决的 review 线程或 inline comment。


七、结论

PR 改动动机明确、实现正确、测试充分,对已有功能无回归风险。建议合入。

Powered by glm-5.1

aptacc2421 added 13 commits May 22, 2026 22:27
Without regression tests, pidfd_open corner cases (invalid pid, CLOEXEC,
PIDFD_THREAD, stale targets) can regress silently while syscall work lands
in separate kernel commits.

Changes:
- Add grouped C cases under test-pidfd-open for pidfd_open behavior.
- Register /usr/bin/test-pidfd-open in all four qemu-smp1 syscall toml files.
Linux pidfd_getfd(2) documents flags as reserved and returns EINVAL for any
non-zero value. Accepting unknown flags would let user space rely on behavior
we do not implement.

Changes:
- Return InvalidInput when flags != 0 before resolving the pidfd.
Thread-scoped pidfd_send_signal delivery needs the kernel thread id, not only
the process leader pid stored on ProcessData. PIDFD_THREAD pidfds already
track thread_exit but did not record which tid they refer to.

Changes:
- Add tid: Option<Pid> and is_thread() on PidFd; set tid in new_thread.
- Pass the thread id from sys_pidfd_open and CLONE_PIDFD clone setup.
pidfd_send_signal must match Linux user-visible rules: PIDFD_SIGNAL_* scope
flags, automatic siginfo when info is NULL, signo 0 liveness probes, and
sig versus info.si_signo consistency. The old path rejected all flags and
faulted on NULL info via make_queue_signal_info.

Changes:
- Parse PIDFD_SIGNAL_THREAD, THREAD_GROUP, and PROCESS_GROUP exclusively.
- Synthesize SI_USER or SI_TKILL siginfo when info is NULL.
- Honor signo 0 as probe-only and validate user-supplied siginfo.
- Dispatch to thread, process, or process-group helpers by scope.
- Export check_kill_permission for reuse from the pidfd syscall path.
pidfd_getfd must reject reserved flags and duplicate a target fd with CLOEXEC;
glibc and modern orchestrators depend on these semantics for passing fds across
pid namespaces via pidfds.

Changes:
- Add test-pidfd-getfd covering self basic, CLOEXEC, EBADF, EINVAL, and flags.
- Register test-pidfd-getfd and test-pidfd-send-signal in four qemu-smp1 syscall toml files.
pidfd_send_signal has more surface area than pidfd_open (flags, NULL info,
signo 0 probes, scope); kselftest-style coverage catches EINVAL/EPERM and
handler delivery regressions early in QEMU syscall runs.

Changes:
- Add test-pidfd-send-signal for default delivery, siginfo fill, probes, and flags.
- Use timed polling instead of pause() so QEMU syscall runs do not hang.
For the caller's own pidfd, pidfd_getfd looked up target_fd through proc_data.scope,
which is only refreshed on clone/dup paths. After pipe() or similar syscalls the
scope snapshot is stale and getfd can block or fail while the live fd table is correct.

Changes:
- Compare pidfd process_data to the current task and read FD_TABLE directly when equal.
- Keep scoped lookup for other processes.
…cases

The initial test-pidfd-open commit only covered self-open and coarse error paths.
Linux pidfd_open semantics need pthread thread tids, CLOEXEC, zombie-before-reap,
and pid 0 EINVAL to stay aligned with the kernel fixes on this branch.

Changes:
- Link libpthread and add invalid-pid, CLOEXEC, and unknown-flags cases.
- Cover PIDFD_THREAD versus ENOENT for non-leader thread tids.
- Poll zombie state with kill(0) before reap, then expect ESRCH after waitpid.
Strengthen pidfd_getfd regression coverage for StarryOS, including
reap-after-open and parent/child fd-table import paths that are easy
to break without sync-aware tests.

Changes:
- Add EBADF/ESRCH/EINVAL error paths and merged CLOEXEC checks.
- Add cross-process dup test with notify/release pipe handshake.
Improve pidfd_send_signal coverage for error paths, reap semantics,
scope flags, and info pointer handling aligned with the kernel.

Changes:
- Add bad pidfd, reaped-target ESRCH, invalid signo, and EFAULT tests.
- Add valid info, tgid+THREAD EINVAL, and thread THREAD_GROUP cases.
- Require PROCESS_GROUP signo=0 probe success; block stray SIGUSR1.
After waitpid the target may disappear from PROCESS_TABLE while a
stale ProcessData Arc still upgrades; pidfd_getfd must not fall through
to EBADF on an empty fd table.

Changes:
- Re-check get_process_data(pid) in PidFd::process_data() before use.
SignalInfo::new_user gained a uid argument on dev. Thread cred uid is
required for Linux-aligned SI_USER siginfo from pidfd_send_signal.

Changes:
- Pass thread.cred().uid in make_pidfd_siginfo.
- Drop accidental WORK_PROGRESS.md from this branch.
pause() plus pthread_cancel can stall pthread_join under QEMU x86_64.
Use pipe EOF after the tid checks so the helper thread exits cleanly.

Changes:
- Block the helper on read until the parent closes the write end.
- Drop pthread_cancel from test_pidfd_open_thread_tid.
@aptacc2421
aptacc2421 force-pushed the fix/starry-pidfd-open-pid0 branch from 246dc59 to 5176a22 Compare May 22, 2026 15:16

@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 Summary

整体评价:Approve

PR 修复了 pidfd_openpidfd_getfdpidfd_send_signal 三个系统调用与 Linux 内核语义的多处偏差,并配套新增了系统化的 QEMU 一致性测试。代码结构清晰、逻辑正确、测试覆盖全面。本 review 在 head 5176a22a 上完成,包含独立本地验证。


一、变更概述

内核改动(4 文件)

  1. PidFd 结构体file/pidfd.rs):新增 tid: Option<Pid> 字段及访问器;process_data() 增加 get_process_data(pid) 二次验证,确保 reap 后返回 ESRCH 而非 EBADF

  2. pidfd_openpid <= 0 返回 EINVAL;不带 PIDFD_THREAD 时验证目标必须是 thread-group leader,否则返回 ENOENT

  3. pidfd_getfd:非零 flags 返回 EINVAL;当前进程走 live FD_TABLEArc::ptr_eq 判断),避免 scope 快照滞后问题。

  4. pidfd_send_signal:完整重写——新增 PidFdSignalFlagsPidFdSignalScope,支持 Thread / ThreadGroup / ProcessGroup 三种作用域分发,正确处理 SI_TKILL / SI_USER 的 siginfo code。

  5. clone.rs:适配 PidFd::new_thread() 新签名,传入 tid

测试改动(9 文件,含 3 个 CMakeLists + 3 个 main.c + 3 个 test_framework.h)

用例 覆盖要点
test-pidfd-open 非法 pid(含负值和 0)、CLOEXEC、线程 TID(含 PIDFD_THREAD)、zombie/reap、非法 flags
test-pidfd-getfd 坏 pidfd、reap→ESRCH、CLOEXEC 不污染原 fd、跨进程 dup、无效 target_fd、非法 flags
test-pidfd-send-signal 坏 pidfd、reap→ESRCH、非法 signo/EFAULT、sig 不一致、flags 组合、线程定向发送、进程组探活、有效 siginfo、si_pid/si_code 验证

测试安装到 /usr/bin/starry-test-suit/,由 syscall 组自动遍历执行,无需手动注册 test_commands


二、代码审查要点

正面评价

  1. reap 检测精巧process_data() 中通过 get_process_data(pid) 确认进程仍在 PROCESS_TABLE 中,一个修改同时修复了 pidfd_getfdpidfd_send_signal 两条路径的 ESRCH 语义。解决了 Weak::upgrade() 在 reap 后仍短暂成功的竞态问题。

  2. Arc::ptr_eq 优化:对当前进程走 live FD_TABLE,正确解决了 proc_data.scopepipe() 等路径下未及时刷新的问题。FD_TABLE.read() 直接读活跃表,避免 scope 快照滞后。

  3. 信号 code 选择正确:Thread scope 使用 SI_TKILL,其他使用 SI_USER,与 Linux 内核 do_send_sig_info 行为一致。

  4. flags 验证严格from_bits 拒绝未知 flags,count_ones() > 1 拒绝多重 scope flags,与 Linux pidfd_send_signal(2) 语义对齐。

  5. siginfo 权限检查:非自身目标且 code >= 0 || code == SI_TKILL 返回 EPERM,与 Linux check_kill_permission 中的 si_code 检查一致。

  6. 测试质量高:全部使用 syscall() 直接调用,避免 libc wrapper 掩盖返回值/errno;error path 和 happy path 均有覆盖;线程级定向发送验证(主线程 SIG_IGN 不受影响)尤其值得肯定。

需要关注的问题(非阻塞)

  1. pidfd_getfd 缺少跨进程权限检查:旧代码在 fd 查找前调用 check_kill_permission(proc_data.proc.pid())。新代码移除了该检查,仅对自身进程和跨进程做了 FD_TABLE 查找路径的区分。Linux 内核要求 ptrace_may_access(PTRACE_MODE_ATTACH_REALCREDS) 权限(比 kill 权限更严格)。虽然旧代码的 kill-permission 检查也不是正确语义,但完全移除意味着任意进程都可以通过 pidfd_getfd 获取其他进程的 fd。建议在后续 PR 中恢复至少 check_kill_permission 或实现更精确的 ptrace 权限检查。

  2. pidfd_open 对非 leader 线程返回 ENOENT 而非 ESRCH:Linux 内核在 pidfd_open 中使用 pid_task(pid, PIDTYPE_TGID) 查找目标,非 leader 线程的 tid 无法匹配 TGID,因此返回 ESRCH。当前实现返回 ENOENTAxError::NotFound)。语义接近但 errno 不一致,可在后续完善。

  3. test_framework.h 存在三份拷贝test-pidfd-open 版本(85 行,含详细中文注释)与另外两个版本(65 行)内容略有不同。建议未来提取到公共路径(如 test-suit/starryos/normal/qemu-smp1/syscall/common/),减少维护成本。


三、验证结果

检查项 结果
cargo fmt --check ✅ 通过
cargo xtask clippy --package starry-kernel(11 项 feature 矩阵) ✅ 全部通过
git diff --check origin/dev...HEAD ✅ 无空白问题
无阻塞问题

四、CI 状态

GitHub Actions 状态为 pending,0 个 check 已报告(fork PR,CI 需条件触发)。本地验证已覆盖 fmt 和 clippy(11/11),均通过。PR 提交者声称本地已通过 cargo xtask starry test qemu -c syscall --arch riscv64(1/1 组通过)。


五、重复/重叠分析

  • base 分支origin/dev 上 pidfd 代码仅由 PR #565 引入(977cb7227),此后无其他修改。本 PR 修复的是该初始实现的 Linux 一致性偏差,不重复。
  • open PR:遍历当前所有 open PR(#730 test-open-family、#876 mount 等),未发现涉及 pidfd.rspidfd_openpidfd_getfdpidfd_send_signal 的 PR。
  • 结论:无重复、无重叠、无冲突风险。

六、结论

PR 改动动机明确、实现正确、测试充分。pidfd_getfd 缺少跨进程权限检查的问题可在后续 PR 中补齐,当前不阻塞合入。建议合入。

Powered by glm-5.1

FD_TABLE.read().get(target_fd as usize).cloned()
} else {
FD_TABLE
.scope(&proc_data.scope.read())

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.

旧代码在 fd 查找前调用了 check_kill_permission(proc_data.proc.pid())。新代码移除了该权限检查。

Linux pidfd_getfd 要求 ptrace_may_access(PTRACE_MODE_ATTACH_REALCREDS) 权限,比 kill 权限更严格。虽然旧代码的 kill-permission 检查不是完全正确的语义,但完全移除意味着任意进程可以通过 pidfd_getfd 获取其他进程的 fd。

建议在后续 PR 中至少恢复 check_kill_permission,或实现更精确的 ptrace 权限检查。当前不阻塞合入。

let code = if scope == PidFdSignalScope::Thread {
SI_TKILL
} else {
SI_USER as _

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.

get_task(pid) 找到非 leader 线程时,返回 AxError::NotFoundENOENT

Linux 内核使用 pid_task(pid, PIDTYPE_TGID) 查找,非 leader 线程的 tid 无法匹配 TGID,返回 ESRCH。虽然语义接近,但 errno 不一致。

次要问题,可在后续统一。

@aptacc2421

Copy link
Copy Markdown
Contributor Author

对照 Linux 主线后的说明

已对照 linux_mainlinekernel/fork.cpidfd_prepare()kernel/pid.c__pidfd_fget()

pidfd_open 非 leader 线程 → errno

Linux 在 PIDFD_THREAD 且 pid 有 PIDTYPE_PIDPIDTYPE_TGID(非 thread-group leader)时,显式返回 -ENOENTfork.c pidfd_prepare,约 1893–1894 行),不是 ESRCH。ESRCH 用于 !pid_has_task(pid, PIDTYPE_PID)(已 reap)或 find_get_pid 失败。

本 PR 对非 leader 返回 AxError::NotFound(ENOENT),与当前 Linux 行为一致,无需改为 ESRCH

pidfd_getfd 跨进程权限

同意审阅:Linux 在 __pidfd_fget() 使用 ptrace_may_access(PTRACE_MODE_ATTACH_REALCREDS),失败为 EPERM;与 check_kill_permission 规则不同。

#707 为修复当前进程 live FD_TABLE 路径移除了旧的 kill 检查。将在本分支 后续 commit 对跨进程路径恢复 check_kill_permission(短期),并补充测例;更严格的 ptrace 语义可再开 PR。

Re-add check_kill_permission for non-current pidfd targets until Starry
has ptrace_may_access(PTRACE_MODE_ATTACH_REALCREDS) parity with Linux.

Changes:
- Gate sys_pidfd_getfd cross-process path with check_kill_permission.
Add cross-cred pidfd_getfd EPERM test, consolidate pidfd test headers
under syscall/common, and use sched_yield sync in test-pidfd-open.

Changes:
- Add test_pidfd_getfd_cross_cred_eperm to test-pidfd-getfd.
- Move test_framework.h to syscall/common and update CMake includes.
- Replace pipe-based pthread tid sync with sched_yield polling.

@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 Summary

整体评价:Approve

本 PR 修复了 pidfd_openpidfd_getfdpidfd_send_signal 三个系统调用与 Linux 内核语义的多处偏差,并新增了系统化的 QEMU 一致性测试。代码逻辑正确,测试覆盖全面,test_framework.h 已提取为公共头文件。


一、变更概述

内核改动(4 文件)

  1. PidFd 结构体file/pidfd.rs):新增 tid: Option<Pid> 字段及 is_thread()/tid() 访问器;process_data() 增加 get_process_data(pid) 二次验证,确保 reap 后返回 ESRCH 而非 EBADF

  2. pidfd_opensyscall/fs/pidfd.rs):pid <= 0 返回 EINVAL;无 PIDFD_THREAD 时验证目标必须是 thread-group leader,非 leader 返回 ENOENT(与 Linux fork.c:pidfd_prepare() 一致)。

  3. pidfd_getfd:非零 flags 返回 EINVAL;当前进程走 live FD_TABLEArc::ptr_eq 判断),避免 scope 快照滞后;跨进程路径已恢复 check_kill_permission 权限检查(commit 5e3bfbe33)。

  4. pidfd_send_signal:完整重写——新增 PidFdSignalFlagsTHREAD=1, THREAD_GROUP=2, PROCESS_GROUP=4)和 PidFdSignalScope,支持 Thread / ThreadGroup / ProcessGroup 三种作用域分发。SI_TKILL 用于 Thread scope,SI_USER 用于其他 scope。signo=0 作为 liveness probe。用户态 siginfo 校验:signo 匹配、非自身目标 code >= 0 || code == SI_TKILL 返回 EPERM

  5. clone.rs:适配 PidFd::new_thread() 新签名,传入 tid

测试改动(7 新文件 + 公共头文件)

用例 覆盖要点
test-pidfd-open 非法 pid(含负值和 0)、CLOEXEC、线程 TID(含 PIDFD_THREAD)、zombie/reap、非法 flags
test-pidfd-getfd 坏 pidfd、reap→ESRCH、CLOEXEC 不污染原 fd、跨进程 dup、无效 target_fd、非法 flags、跨 cred EPERM
test-pidfd-send-signal 坏 pidfd、reap→ESRCH、非法 signo/EFAULT、sig 不一致、flags 组合、线程定向发送、进程组探活、有效 siginfo

test_framework.h 已提取到 syscall/common/,三个测试共用。


二、代码审查要点

正面评价

  1. reap 检测精巧process_data() 中通过 get_process_data(pid) 确认进程仍在 PROCESS_TABLE 中,一个修改同时修复了 pidfd_getfdpidfd_send_signal 两条路径的 ESRCH 语义。

  2. Arc::ptr_eq 优化:对当前进程走 live FD_TABLE,正确解决了 proc_data.scopepipe() 等路径下未及时刷新的问题。

  3. 信号 code 选择正确:Thread scope 使用 SI_TKILL,其他使用 SI_USER,与 Linux 内核 do_send_sig_info 行为一致。

  4. flags 验证严格from_bits 拒绝未知 flags,count_ones() > 1 拒绝多重 scope flags。

  5. 跨进程权限已恢复:commit 5e3bfbe33 恢复了跨进程 pidfd_getfdcheck_kill_permission 检查,commit f8fdb8620 新增了 test_pidfd_getfd_cross_cred_eperm 测试覆盖。

  6. 测试质量高:全部使用 syscall() 直接调用,避免 libc wrapper 掩盖返回值/errno;error path 和 happy path 均有覆盖。

潜在改进(非阻塞)

  1. ProcessGroup 权限粒度check_kill_permission(pgid) 仅检查 group leader 凭据;Linux kill_pgrp 逐进程检查。当前实现是可接受的简化,可后续完善。

  2. ptrace 权限:Linux pidfd_getfd 要求 ptrace_may_access(PTRACE_MODE_ATTACH_REALCREDS),比 kill 权限更严格。当前 check_kill_permission 是合理的近似,更严格的 ptrace 语义可再开 PR。


三、验证结果

检查项 结果
cargo fmt --check ✅ 通过
cargo xtask clippy --package starry-kernel(11 项 feature 矩阵) ✅ 全部通过
git diff --check origin/dev...HEAD ✅ 无空白问题
无阻塞问题

四、CI 状态

GitHub Actions 状态为 pending(fork PR,CI 需条件触发)。本地验证已覆盖 fmt 和 clippy(11/11),均通过。


五、重复/重叠分析

  • base 分支origin/dev 上 pidfd 代码仅由 PR #565 引入(977cb7227),此后无其他修改。本 PR 修复的是该初始实现的 Linux 一致性偏差,不重复。
  • open PR:遍历当前所有 open PR,未发现涉及 pidfd.rspidfd_openpidfd_getfdpidfd_send_signal 的 PR。
  • 结论:无重复、无重叠、无冲突风险。

六、之前 Review 状态

已有 5 条 APPROVE review(来自 mai-team-app[bot]),分别在多个 commit 上。上次 review 提出的两个关注点(跨进程权限检查、ENOENT vs ESRCH)已在最新提交中解决:

  • 跨进程 check_kill_permission 已恢复(commit 5e3bfbe33
  • PR 作者对照 Linux fork.c:pidfd_prepare() 确认非 leader 返回 ENOENT 是正确的(Linux 行为确实如此)

七、结论

PR 改动动机明确、实现正确、测试充分。上次 review 提出的两个关注点均已解决。建议合入。

Powered by glm-5.1

@ZR233
ZR233 merged commit 100f389 into rcore-os:dev May 24, 2026
43 checks passed
This was referenced May 24, 2026
@github-actions github-actions Bot mentioned this pull request Jun 3, 2026
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