feat(starry-kernel): eBPF kernel runtime (tracepoint / kprobe / perf)#886
Conversation
There was a problem hiding this comment.
概要
本 PR (PR-D) 将 Starry-OS/StarryOS:ebpf-kmod 的 7 个 aya 用户态 eBPF 程序移植到 tgoskits,配合 PR-A (#850) 的内核侧 eBPF 运行时,形成完整的"内核 + 用户" eBPF 栈。同时新增 cargo xtask starry user-ebpf 子命令替代源仓的 Makefile。
变更范围
- 用户态程序 (
os/StarryOS/user/ebpf/): 7 个独立 workspace (kret, rawtp, mytrace, syscall_ebpf, upb, upb2, async_test),字节级移植自源仓user/musl/,aya 三件套结构保持 - xtask 子命令 (
scripts/axbuild/src/starry/user_ebpf.rs):cargo xtask starry user-ebpf {list, build}替代 Makefile - 根 Cargo.toml:
[workspace] exclude摘出 7 个嵌套 workspace +[patch.crates-io] printf-compat临时 patch (来自 PR-A) - 内核侧代码 (来自 PR-A #850 的 stacked commits): ebpf/, perf/, tracepoint/, kprobe/, kallsyms 等 ~3370 行增量
验证
本地已验证:
cargo test -p axbuild starry::user_ebpf— 5/5 通过cargo check -p axbuild— 编译通过cargo metadata --no-deps— 主 workspace 正确 exclude 7 个嵌套 workspace
发现
1. 格式化问题 (阻塞)
cargo fmt --check 发现 scripts/axbuild/src/starry/user_ebpf.rs:115 有格式偏差:bail!() 宏的 match 臂数组被 rustfmt 要求加大括号。PR 声明 cargo fmt --all -- --check 通过,但实际在主 workspace 级别检查存在偏差。需要 cargo fmt 后重新提交。
2. 合并冲突 (阻塞)
当前 mergeable_state = DIRTY,与 dev 分支存在冲突。PR 依赖于 PR-A (#850) 先合入。这个在 PR 描述中有记录,属于预期情况。
3. 构建验证受限 (非阻塞)
由于本环境缺少 bpf-linker、*-linux-musl-cc 交叉编译器和 musl target,无法实际构建 aya 程序。async_test 可以 cargo check 但也需要 nightly feature (breakpoint)。PR 描述对此有明确记录,需要 CI Linux runner 完成验证。
重复/重叠分析
- PR-A (#850): 内核侧 eBPF 运行时。本 PR (PR-D) 的 stacked parent,包含所有 kernel 变更。不重复。
- PR #673: tracepoint 基础设施。已包含在本 PR 的 stacked base 中。不重复。
- PR #805: kallsyms + kprobe + bpf stub。已被 PR-A 替换。不重复。
- base 分支 (
origin/dev) 无os/StarryOS/user/ebpf/目录,无重复实现。
代码质量
- xtask 实现清晰: clap 参数处理、arch 映射、程序白名单校验、
--program/--all互斥逻辑全部有单元测试覆盖 - 用户态程序是源仓的字节级移植,结构完整 (aya 三件套 + Cargo.lock 入库)
- README.md 详细记录了落点决策、构建方法、前置环境、已知限制
exclude而非members的选择正确 — cargo 不允许嵌套 workspace[patch.crates-io] printf-compat注释充分说明了临时性质和删除条件
限制 (已知)
upb/upb2依赖 PR-A 的 uprobe 真正接通,目前返回 Unsupported- 安装路径未定,需后续 PR 处理 rootfs hook
建议修复格式化问题后,等 PR-A (#850) 合入 dev 后 rebase 解决冲突,即可合入。
Powered by glm-5.1
0394d57 to
c8023f4
Compare
There was a problem hiding this comment.
概要
本 PR (PR-D) 将 Starry-OS/StarryOS:ebpf-kmod 的 7 个 aya 用户态 eBPF 程序移植到 tgoskits,配合 PR-A (#850) 的内核侧 eBPF 运行时,形成完整的「内核 + 用户」 eBPF 栈。同时新增 cargo xtask starry user-ebpf 子命令替代源仓的 Makefile。
变更范围
PR-D 特有的变更集中在以下区域(不含 PR-A stacked commits 的内核侧代码):
- 用户态程序 (
os/StarryOS/user/ebpf/): 7 个独立 workspace (kret, rawtp, mytrace, syscall_ebpf, upb, upb2, async_test),aya 三件套结构保持完整 - xtask 子命令 (
scripts/axbuild/src/starry/user_ebpf.rs): 237 行,list/build子命令,clap 参数处理清晰 - 根 Cargo.toml:
[workspace] exclude正确摘出 7 个嵌套 workspace .cargo/config.toml: 四架构 musl linker + target-feature 配置- README.md: 详尽的落点决策记录、内核依赖矩阵、构建指引、已知限制
验证结果
cargo test -p axbuild starry::user_ebpf → 5/5 通过
cargo fmt --check → 干净(前次 review 的 fmt 偏差已在 commit 21951c92c 修复)
本环境缺少 bpf-linker / *-linux-musl-cc / musl target,无法实际构建 aya 程序。PR 描述对此有明确记录,需要 CI Linux runner 完成验证。
代码质量
- xtask 实现清晰:clap 参数处理、arch 映射、程序白名单校验、
--program/--all互斥逻辑全部有单元测试覆盖 (5/5) exclude而非members的选择正确 — cargo 不允许嵌套 workspace- aya git deps 无个人 fork patch,与 crate-fork-audit 规则一致
- README 详细记录了落点决策、构建方法、前置环境、已知限制
- 用户态程序是源仓的字节级移植,aya 三件套结构 + Cargo.lock 入库保证 CI 复现
前次 review 反馈
前次 review (mai-team-app, REQUEST_CHANGES) 指出的格式化问题已在后续 commit 21951c92c style(starry-xtask): rustfmt user_ebpf.rs match arm 中修复,当前 cargo fmt --check 全 workspace 通过。
合并状态
mergeable_state = blocked — 预期行为,本 PR 依赖于 PR-A (#850) 先合入 dev。PR 描述已记录 rebase 计划。
重复/重叠分析
- PR-A (#850): 内核侧 eBPF 运行时。本 PR 的 stacked parent,不重复。
- PR #847 (kprobe)、PR #805 (kallsyms+kprobe+bpf stub)、PR #673 (tracepoint): 均在 stacked base 中,不属于本 PR 变更。
- dev 分支: 无
os/StarryOS/user/ebpf/目录,无已有用户态 eBPF 程序或 xtask user-ebpf 子命令。无重复。 - 无其他 open PR 涉及 eBPF 用户态程序移植。
限制(已知,非阻塞)
upb/upb2依赖 PR-A 的 uprobe 接通,目前返回 Unsupported- 安装路径未定,需后续 PR 处理 rootfs hook
- 实际构建验证受限,需 CI runner
结论
PR-D 特有的代码(用户态程序 + xtask 子命令)质量良好,结构正确,测试覆盖充分,文档完整。前次 review 反馈已修复。唯一阻塞因素是 PR-A (#850) 先合入 dev,属于工作流正常依赖。推荐等 PR-A 合入后 rebase 再合入。
Powered by glm-5.1
615b715 to
d9ff12a
Compare
There was a problem hiding this comment.
本轮审查覆盖当前 head 613583f3b4d13d178a792d38e6e2e92e2bf91235。
变更范围:本 PR 不只是把 os/StarryOS/user/ebpf/ 下的 aya 用户态程序和 cargo xtask starry user-ebpf 接进来,还包含 sched tracepoint、mmap(perf_fd) ringbuf、eBPF demo QEMU case/CI workflow,以及与 #880 高度重叠的 kmod/hello/kebpf 模块改动。因此它会影响 StarryOS 的 bpf(2)/perf_event_open(2)、mmap 设备映射生命周期、调度 tracepoint fast path、test-suit 打包和 axbuild 行为,不是纯用户态示例的隔离变更。
CI/本地验证:GitHub Actions 当前 check suite 为 success。 本地验证了 cargo fmt --check、git diff --check、主 workspace 与 9 个 eBPF 子 workspace 的 cargo metadata --no-deps、cargo test -p axbuild starry::user_ebpf、cargo check -p axbuild、cargo clippy -p axbuild --lib -- -D warnings、cargo check -p async_test --manifest-path os/StarryOS/user/ebpf/async_test/Cargo.toml 均通过。额外尝试 cargo clippy -p axbuild --all-targets -- -D warnings 会在未改动的 scripts/axbuild/src/arceos/cbuild.rs 触发既有 items_after_test_module,不作为本 PR 判断依据。完整 user-ebpf build/QEMU eBPF demo 未在本容器跑完:当前环境仍缺 bpf-linker/musl 交叉工具链;不过下面的生命周期问题可以静态确认,且会影响新增 sched_trace perf ringbuf 路径。
历史评论:之前 bot 指出的 rustfmt 问题已修复;Godones 关于 tracepoint 定义位置的两条组织性建议仍未从代码形态上采纳,本轮不把它作为 correctness blocker。重复/重叠分析:base 分支已有 #850 的内核 eBPF runtime,但没有这些用户态 aya workspace;开放 PR #880 与本 PR 中的 kmod/hello/kebpf/module-build 提交存在明显重叠/stack 风险,合并前建议明确依赖/取舍或 rebase 到最终的 #880 状态,避免两个 PR 互相覆盖。
仍有一个阻塞问题:mmap(perf_fd) 返回的物理映射没有把 backing pages 的所有权锚到 VMA,关闭 fd 后会释放仍被用户地址空间映射的页,存在 use-after-free/内存破坏风险。请先修复后再合并。
Powered by gpt-5.5
There was a problem hiding this comment.
审查总结
本轮审查覆盖当前 head d97ab01afadd408e9f8e5afd3bd9088391b67b3c。
变更范围
本 PR 包含 PR-D 用户态 eBPF 程序 + PR-A 内核侧 tracepoint/perf 改动,以及 kmod 模块、eBPF QEMU test-suit 和 CI workflow。关键变更:
- 用户态 eBPF 程序 (
os/StarryOS/user/ebpf/):9 个独立 workspace(kret, rawtp, mytrace, syscall_ebpf, upb, upb2, async_test, sched_trace, profile),aya 三件套结构完整 - xtask 子命令 (
scripts/axbuild/src/starry/user_ebpf.rs):241 行,list/build 子命令,5/5 测试通过 - perf mmap 修复 (
kernel/src/perf/{mod,bpf}.rs):DeviceMmap::Physical(range, Some(anchor))用Arc<GlobalPage>保证 ringbuf 页生命周期不短于用户 VMA - sched tracepoint (
kernel/src/tracepoint/sched.rs,syscall/task/clone.rs,task/ops.rs):sched_switch/sched_process_fork/sched_process_exit,定义紧邻发射点 KernelExtTracePoint从Mutex改SpinNoPreempt:在 atomic context(switch_to、IRQ off)中 fire tracepoint 必须用非睡眠锁- kmod 模块 + test-suit:hello/kebpf 加载模块、
kmod-modulesQEMU 测例 - eBPF QEMU test-suit:syscall_count / sched_trace / profile 三组,反 fallback 断言设计合理
前次 review 反馈处理
前次 review(mai-team-app[bot], REQUEST_CHANGES, 6/4)指出 mmap(perf_fd) 返回的物理映射没有锚到 VMA,存在 use-after-free。已修复:
BpfPerfEventWrapper::device_mmap返回(PhysAddr, Arc<GlobalPage>)PerfEvent::device_mmap线程 anchor 到DeviceMmap::Physical(range, Some(anchor))- 字段声明顺序(
inner在pages之前)保证 drop 顺序正确 - 注释完备,解释了 refcount 语义和生命周期保证
之前 bot 指出的 rustfmt 问题已在 commit 21951c92c 修复。
本地验证
cargo fmt --all -- --check → 干净 ✅
cargo test -p axbuild starry::user_ebpf → 5/5 通过 ✅
cargo check -p axbuild → 编译通过 ✅
cargo metadata --no-deps → 主 workspace 218 packages,9 个 eBPF 程序正确 exclude ✅
cargo metadata --manifest-path os/StarryOS/user/ebpf/<prog>/Cargo.toml (9/9) → 全部 OK ✅
完整 user-ebpf build / QEMU eBPF demo 未在本容器跑完:缺 bpf-linker / musl 交叉工具链。但 mmap 修复可通过静态分析确认正确性,xtask 子命令测试覆盖充分。
CI 状态
GitHub Actions 当前 head SHA 的 check suite:
Detect changed paths→ successCheck formatting / {run_host, run_container}→ skipped(path-filtered)Run sync-lint / {run_host, run_container}→ skipped/queuedRun clippy / run_container→ skipped- 大量
Test */Publish *→ skipped(path-filtered,PR 改动面不影响这些 job)
CI skipped 均为 path-filter 预期行为,不构成阻塞。本 PR 改动面集中在 eBPF/kernel/xtask/test-suit,不影响 axvisor/starry 常规 CI 路径。
重复/重叠分析
- PR-A (#850):内核侧 eBPF 运行时,本 PR stacked parent。不重复。
- PR #880(feat/starry-modules: hello + kebpf):与本 PR 存在明显重叠——
os/StarryOS/modules/{hello,kebpf}(6 文件 387 行)、kmod.rs重构、kmod-modules测例在两个 PR 中均出现。同一作者的 stacking 策略导致此重叠,建议明确合并顺序:先合 #880 再 rebase #886,或关闭 #880 合入本 PR。 - dev 分支:无
os/StarryOS/user/ebpf/目录,无重复。无其他 open PR 涉及 eBPF 用户态程序移植。 - 无
[patch.crates-io]引入,aya deps 均为 git(aya 未发 crates.io),与项目规范一致。
代码质量
- xtask 实现清晰:arch 映射、程序白名单、
--program/--all互斥逻辑均有单元测试覆盖 exclude而非members的选择正确——cargo 不允许嵌套 workspace- tracepoint 定义紧邻发射点(clone.rs、task/ops.rs),注册通过 link section,位置不影响发现
SpinNoPreempt替代Mutex有充分注释说明原因- perf mmap 修复的 Arc anchor 机制设计合理,SAFETY 注释完整
- QEMU test-suit 脚本采用反 fallback 设计:
getpid_spin驱动确定性 workload,HashMap 计数断言有明确下限(≥100/500) - OwnedEbpfVm 中
register_allowed_memory(0..u64::MAX)的 TODO 为既有问题,不在本 PR 范围内
结论
前次 review 的阻塞问题(mmap UAF)已正确修复。PR-D 特有代码(用户态程序 + xtask + tracepoint + perf 修复 + test-suit)质量良好,测试覆盖充分,文档完整。#880 重叠属于同一作者的 stacking 策略,不影响本 PR 代码正确性。建议合入。
Powered by mimo-v2.5-pro
There was a problem hiding this comment.
审查总结
本轮审查覆盖当前 head 56e1d812ac(PR-A #850 stacked commits + PR-D 用户态程序 + kmod 模块 + eBPF QEMU 测例 + CI workflow)。
变更范围
- 用户态 eBPF 程序(
os/StarryOS/user/ebpf/):9 个独立 workspace(async_test, kret, rawtp, mytrace, syscall_ebpf, sched_trace, profile, upb, upb2),aya 三件套结构完整 - xtask 子命令(
scripts/axbuild/src/starry/user_ebpf.rs):241 行,list/build 子命令,5/5 测试通过 - perf mmap 生命周期修复(
kernel/src/perf/{mod,bpf}.rs):DeviceMmap::Physical(range, Some(anchor))用Arc<GlobalPage>保证 ringbuf 页生命周期不短于用户 VMA - sched tracepoint(
kernel/src/tracepoint/sched.rs、syscall/task/clone.rs、task/ops.rs):sched_switch / sched_process_fork / sched_process_exit - kmod 模块 + test-suit:hello/kebpf 加载模块、
kmod-modulesQEMU 测例 - eBPF QEMU test-suit:syscall_count / sched_trace / profile 三组
- CI workflow(
starry-ebpf.yml):定时/手动触发的 eBPF demo 构建
前次 review 反馈处理
- mmap UAF(前次 REQUEST_CHANGES):已正确修复。
BpfPerfEventWrapper::device_mmap返回(PhysAddr, Arc<GlobalPage>),PerfEvent::device_mmap线程 anchor 到DeviceMmap::Physical(range, Some(anchor))。字段声明顺序(inner在pages之前)保证 drop 顺序正确。 - rustfmt 偏差(更早 REQUEST_CHANGES):已在 commit
21951c92c修复。 - Godones 关于 tracepoint 定义位置的建议:组织性建议,tracepoint 用 link section 注册,物理位置不影响发现,不作为阻塞项。
本地验证
git diff --check → 干净 ✅
cargo test -p axbuild starry::user_ebpf → 5/5 通过 ✅
cargo metadata --no-deps → 218 packages,9 个 eBPF 程序正确 exclude ✅
grep [patch.crates-io] Cargo.toml → 无 ✅
完整 user-ebpf build / QEMU eBPF demo 未在本容器跑完:缺 bpf-linker / musl 交叉工具链。PR 描述对此有明确记录,需 CI Linux runner 完成。
CI 状态
GitHub Actions 对 head 56e1d812a 的 check suite:大部分 job 为 skipped,属于 path-filter 预期行为(eBPF 改动面不影响 axvisor/starry 标准 CI 路径)。无 failure 结论。新增的 starry-ebpf.yml 为 schedule/workflow_dispatch 触发,不在 PR check 中体现。
重复/重叠分析
- PR-A (#850):内核侧 eBPF 运行时,本 PR stacked parent。不重复。
- PR #880(feat/starry-modules: hello + kebpf):与本 PR 存在 partial-overlap ——
os/StarryOS/modules/{hello,kebpf}、kmod.rs、kmod-modules测例在两个 PR 中均出现。同一作者的 stacking 策略,#886 是 superset。建议合并顺序:先合 #880 再 rebase #886,或关闭 #880 直接合入本 PR。 - dev 分支:无
os/StarryOS/user/ebpf/目录,无重复。无其他 open PR 涉及 eBPF 用户态程序移植。 - 无
[patch.crates-io]引入,aya deps 均为 git(aya 未发 crates.io),与项目规范一致。
代码质量
- xtask 实现清晰:arch 映射、程序白名单、
--program/--all互斥逻辑均有单元测试覆盖 exclude而非members的选择正确——cargo 不允许嵌套 workspace- tracepoint 定义紧邻发射点(clone.rs、task/ops.rs),注册通过 link section
- perf mmap 的 Arc anchor 机制设计合理,注释完整解释了 refcount 语义
- QEMU test-suit 脚本采用反 fallback 设计:getpid_spin 驱动确定性 workload,HashMap 计数断言有明确下限(≥100/500)
- STARRY_KMOD 构建模式的 codegen flags 隔离设计合理:通过 build config
[env]表局部启用,不影响其他测例
合并状态
mergeable_state = blocked — 预期行为,依赖 PR-A (#850) 先合入 dev。PR 描述已记录 rebase 计划。
结论
前次 review 的阻塞问题(mmap UAF)已正确修复。PR-D 特有代码质量良好,测试覆盖充分,文档完整。建议合入(在 PR-A #850 合入 dev 并 rebase 后)。
Powered by mimo-v2.5-pro
ZR233
left a comment
There was a problem hiding this comment.
复审当前 head 56e1d812ac25fb6567d00513a4be7d4d9cda087d,本轮结论为 REQUEST_CHANGES。主要原因不是代码风格,而是这个 PR 现在已经加入了 test-suit/starryos/ebpf 的 QEMU 用例和 eBPF demo workflow,但当前 head 没有一条可追溯的通过路径能证明这些新增用例真的可运行。
阻塞点:
- 新增 eBPF QEMU 用例没有当前 head 的可复现通过证据。我运行了实际用例路径:
cargo xtask starry test qemu --test-group ebpf --arch x86_64 -c syscall_count
它在进入 guest 前失败:test-suit/starryos/ebpf/qemu-smp1/syscall_count/c/CMakeLists.txt 调用 cargo xtask starry user-ebpf build --program syscall_ebpf --arch x86_64,随后 syscall_ebpf-ebpf/build.rs 因找不到 bpf-linker panic,错误为 CannotFindBinaryPath,最终摘要是 FAIL syscall_count / 0/1 case(s) passed。本地环境确实缺 bpf-linker,但这个 PR 新增的 .github/workflows/starry-ebpf.yml 目前只有 schedule 和 workflow_dispatch,不在当前 PR check 中运行;gh run list --branch feat/starry-ebpf-userspace 只看到常规 CI workflow,且该新 workflow 还不能作为默认分支上的命名 workflow 查询。因此 merge 前需要把 eBPF demo suite 接入可见的 PR 校验,或提供当前 head 上可追溯的 workflow/run artifact,证明至少 cargo xtask starry test qemu --arch x86_64 -g ebpf 通过。
- PR 描述已经明显落后于当前 diff。正文仍写“7 个程序”和
7/7 program workspace,但当前代码里scripts/axbuild/src/starry/user_ebpf.rs的PROGRAMS是 9 个(新增/包含sched_trace、profile),并且当前 PR 还包含 kmod modules、kmod-modulesnormal QEMU case、三组 eBPF QEMU cases、perf/tracepoint runtime 修改和starry-ebpf.yml。请同步 PR 描述和验证清单,否则 review/merge 依据会和实际变更不一致。
本轮已通过的本地检查:
git diff --check origin/dev...HEAD
audited clean
cargo fmt --check
cargo test -p axbuild starry::user_ebpf
cargo check -p axbuild
cargo xtask clippy --package axbuild
cargo metadata --format-version=1 --no-deps
9 个 eBPF nested workspace 的 cargo metadata
cargo xtask clippy --package starry-kernel
cargo xtask starry user-ebpf list
cargo xtask starry user-ebpf build --program async_test --arch x86_64
cargo xtask starry test qemu --test-group normal --arch x86_64 -c kmod-modules
cargo xtask starry user-ebpf build --program kret --arch x86_64 也因缺 bpf-linker 失败,和上面的 eBPF QEMU case 失败原因一致。
CI 状态:当前 head 仍是 56e1d812ac25fb6567d00513a4be7d4d9cda087d;常规 CI 暂未看到 failure,但查询时仍有 Run clippy / run_host、Test starry riscv64 qemu / run_host、Test starry aarch64 qemu / run_host、Test arceos riscv64 qemu / run_host pending。常规 CI 没有覆盖新增的 starry-ebpf.yml eBPF demo suite。
重复/重叠检查:dev 上没有 os/StarryOS/user/ebpf/;open PR 中 #880 与本 PR 在 os/StarryOS/modules/{hello,kebpf}、scripts/axbuild/src/starry/kmod.rs、kmod-modules test-suit 上存在 partial overlap,#886 更像 superset。建议明确 merge 顺序:先合 #880 后 rebase #886,或关闭 #880 并以 #886 承载这部分内容。
已处理的 review threads:已确认并 resolve 前次 bot 的 rustfmt 和 perf mmap retain/UAF 两个 fixed threads;Godones 关于 tracepoint 定义位置的 thread 保持打开,交给对应领域维护者判断。
Kernel-side eBPF runtime, split out of rcore-os#886 (its userspace programs and the `kebpf` loadable module move to separate PRs): - perf ringbuf: `mmap(perf_fd)` maps the `BpfPerfEvent` ringbuf pages, anchored to the mmap VMA to prevent a use-after-free; `FileLike::device_mmap` gains a `length` parameter (all impls updated). - sched tracepoints: `sched_switch` / `process_fork` / `process_exit` emitted via ax-feat `tracepoint-hooks`. - kprobe on x86_64: `handle_syscall` / `sys_getpid` are `#[inline(never)]` so a kprobe planted on their symbols actually fires. - raw tracepoint attach/detach made atomic-safe. - mm: `write_kernel_text` acquires the kernel-aspace lock inside `stop_machine` to keep IRQ-save guards LIFO (no leaked IRQ-disabled state on probe detach). - ebpf/transform + perf + sysfs surface supporting the above. `bpf(2)` remains served by the kernel's built-in eBPF runtime. The syscall registry that lets a loadable module (`kebpf`) take over `bpf(2)` is a separate follow-up PR (avoids a `syscall/mod.rs` conflict with this PR).
56e1d81 to
6113957
Compare
ZR233
left a comment
There was a problem hiding this comment.
上次审查后作者新增了 4 个 commit:
- uprobe 实现:新增
uprobe/mod.rs,支持用户态动态探针。设计合理:- 每进程独立的 uprobe manager(用户地址空间隔离)
- 异常上下文使用 try_lock()(IRQ 禁用,不能睡眠)
- 复用 kprobe 基础设施做指令解码和 out-of-line 单步执行
- 端到端连接:将 uprobe 接入 kretprobe/tracepoint attach 路径
- perf ringbuf mmap 修复:非直连路径保持 side-effect-free
- clippy 修复:将 uprobe 异常处理分支折叠为 match guards
变更 12 个文件,+447/-79。CI 全部通过(clippy、fmt、sync-lint 均成功)。
uprobe 实现质量高:文档注释解释了设计决策(为什么 try_lock、为什么 per-process manager),复用了现有 kprobe 架构。此 PR 也修复了阻塞依赖 PR #1132 的 clippy 错误。
审查通过。
There was a problem hiding this comment.
审查总结
本轮审查覆盖当前 head bf1276a9b(纯内核侧 eBPF 运行时,34 文件 +827/-91)。
变更范围
- perf ringbuf mmap 生命周期 (
perf/bpf.rs、perf/mod.rs):BpfPerfEventWrapper::device_mmap使用Arc<GlobalPage>将 ringbuf 物理页锚定到 VMA,Weak保证 fd 关闭后页仍存活。字段声明顺序(inner在pages前)保证 drop 顺序正确。 device_mmap调用时序 (syscall/mm/mmap.rs):仅在MAP_SHARED时探测device_mmap,MAP_PRIVATE永远走 file_mmap/CoW 路径。修复了前次 review 指出的副作用时序问题。write_kernel_textLIFO 锁嵌套 (mm/access.rs):kernel_aspace锁移入stop_machine闭包内部,保持 IRQ-save guard LIFO 嵌套。- sched tracepoint (
tracepoint/sched.rs、syscall/task/clone.rs、task/ops.rs、arceos/modules/axtask/):通过ax-crate-interface实现跨 cratesched_switch/sched_process_fork/sched_process_exit,tracepoint 定义紧邻发射点。 - uprobe 支持 (
uprobe/mod.rs、kprobe.rs、perf/kprobe.rs):per-process uprobe manager,通过 direct-map alias 访问用户页。 #[inline(never)](ebpf/transform.rs、ebpf/map.rs、ebpf/prog.rs):保证符号在 release 构建中不被内联消去,为可加载模块.kallsyms重定位做准备。- sysfs event_source (
pseudofs/sysfs.rs):aya 需要读取/sys/bus/event_source/devices/{kprobe,uprobe,tracepoint}/type。 bpf_probe_read_kernelhelper 别名 (ebpf/mod.rs):helper id 113 别名到 4,匹配 aya 的 probe read 调用。FileLike::device_mmap签名:增加length参数,所有现有实现同步更新。
前次 review 反馈处理
- mmap UAF(早期 REQUEST_CHANGES):已正确修复。
Arc<GlobalPage>+DeviceMmap::Physical(.., Some(anchor))设计合理。 - device_mmap 副作用时序(ZR233 REQUEST_CHANGES):已修复。
sys_mmap中仅MAP_SHARED才调用device_mmap,MAP_PRIVATE不触发 ringbuf 分配。 - ZR233 要求拆分 eBPF QEMU 用例:用户态程序和 eBPF QEMU 测试已移至 #1132,本 PR 不再包含。✅
- Godones 建议移除
#[inline(never)]:组织性建议。注释和#[inline(never)]有实际作用(可加载模块符号重定位),不作为阻塞项。
本地验证
cargo fmt --check → 干净 ✅
git diff --check → 干净 ✅
cargo xtask clippy --package starry-kernel → 13/13 通过 ✅
grep [patch.crates-io] Cargo.toml → 无 ✅
CI 状态
当前 head 的所有 GitHub Actions check 均为 skipped(path-filter 预期行为:内核 eBPF 改动面不影响 axvisor/starry 标准 CI 路径)。无 failure 结论。
重复/重叠分析
- PR-A (#850):内核侧 eBPF 运行时基础,本 PR 的 stacked parent。不重复。
- PR #880(feat/starry-modules):本 PR 已拆分移除 kmod 模块,不再与 #880 重叠。
- PR #1132:用户态 eBPF 程序(从本 PR 拆出),stacked on 本 PR。不重复。
- dev 分支:无 eBPF 内核运行时代码。无重复。
- 无
[patch.crates-io]引入。
代码质量
- perf mmap 的 Arc/Weak 所有权模型设计合理,SAFETY 注释完整
write_kernel_textLIFO 锁嵌套修复注释详尽,解释了 IRQ 状态泄漏根因- sched tracepoint 的
def_interface/impl_interface跨 crate 设计干净 - uprobe 的
try_lock()在异常上下文中使用合理(IRQs disabled,arm 在 syscall 上下文) - kprobe 的
copy_memory通过 direct-map alias 访问用户页避免了 IRQ-off 时的 faultable 路径 bpf_probe_read_kernel别名(113→4)与 Linux 内核 helper 表一致
结论
前次 review 的阻塞问题均已正确修复。PR 已按要求拆分为纯内核侧运行时。代码质量良好,注释充分,无安全/正确性/性能问题。建议合入。
Powered by mimo-v2.5-pro
…+ drop kebpf inline-never) 按 @Godones 复审意见处理: - syscall/mod.rs:抽出 `#[inline(never)] sysno()` 作为 kprobe 挂载点, 其第一个参数寄存器直接持有 syscall id(demo 可直接读取); `handle_syscall` 去掉 `#[inline(never)]`,改为转调 `sysno()`。 - ebpf/{map,prog,transform}.rs:移除面向 kebpf 可加载模块的全部 `#[inline(never)]` 及相关注释(内核与 kmod 同步内联即无符号依赖, 当前不需关注 kebpf)。 - ebpf/mod.rs:删除 `handle_prog_load` 中仅用于 kebpf 单态化的描述 与无用的 `_verifier_info` 绑定。 - kprobe.rs:`copy_memory` 取不到目标任务时直接 `.expect`(return 后 续 uprobe 设置仍会崩溃);导入 `MappingFlags`/`PageSize`,去掉过长路径。 本机 `cargo xtask starry build --arch x86_64` 通过,`cargo fmt` 干净。
|
已按 @Godones 本轮意见全部处理(head 1. 2. 移除面向 kebpf 的
3. 4. 5. sched tracepoint 就近定义(上一轮) 本机验证: |
Move the aya eBPF userspace programs out of os/StarryOS/user/ebpf into apps/starry/ebpf so they sit alongside the other operator-facing Starry app cases (per review on rcore-os#886), instead of the test-suit / user-ebpf xtask path. Per-case wiring (prebuild.sh / init.sh / qemu+build toml) lands in follow-up commits. - Dedup: drop `rawtp` (its raw-tracepoint path is covered by `sched_trace`) and `async_test` (a tokio breakpoint smoke, not an eBPF program). - Rename `syscall_ebpf` -> `syscall_count` (the three crates, the eBPF program function, and the loader's `program_mut` lookup) to match the demo name. Kept: syscall_count, profile, sched_trace, kret, mytrace, upb, upb2.
There was a problem hiding this comment.
审查总结
本轮审查覆盖当前 head c8f3d94a5e725b47d374fb0846e0adea6eba3cf7。PR 已按 @Godones 要求拆分为纯内核侧 eBPF 运行时(25+ 文件,净增 792 行),不再包含用户态 aya 程序或 kebpf 模块。
变更范围
- perf ringbuf mmap 生命周期修复(
perf/bpf.rs、perf/mod.rs):BpfPerfEventWrapper使用Weak<GlobalPage>/Arc<GlobalPage>所有权模型。VMA 持有强引用,wrapper 持有弱引用。device_mmap仅在MAP_SHARED时调用(mmap.rs),避免MAP_PRIVATE路径的副作用消耗 ringbuf 槽位。 - kprobe/uprobe 支持(
kprobe.rs、uprobe/mod.rs):实现 uprobe 的copy_memory、set_writeable_for_address、alloc_user_exec_memory、free_user_exec_memory,通过内核 direct-map 别名读写用户页。每个进程有自己的uprobe_manager(ProcessData)。 - sched tracepoint(
tracepoint/sched.rs、syscall/task/clone.rs、task/ops.rs、axtask/):通过ax_crate_interface跨 crate 的sched_switch/sched_process_fork/sched_process_exit。 write_kernel_textLIFO 锁嵌套修复(mm/access.rs):将kernel_aspace锁获取移入stop_machine闭包内。device_mmap签名变更:增加length参数,所有FileLike实现同步更新。sysno()函数(syscall/mod.rs):#[inline(never)]使 kprobe 符号可达,第一参数寄存器直接持有 syscall id。- sysfs event_source(
pseudofs/sysfs.rs):kprobe/uprobe/tracepoint perf type 节点。 - raw/tracepoint double downcast 修复(
perf/raw_tracepoint.rs、perf/tracepoint.rs)。
前次 review 反馈处理
- mmap UAF(REQUEST_CHANGES):已正确修复 ✅。
Arc<GlobalPage>+DeviceMmap::Physical(.., Some(anchor))+Weak所有权模型设计合理。 device_mmap副作用时序(ZR233 REQUEST_CHANGES):已修复 ✅。仅在MAP_SHARED时才调用device_mmap,MAP_PRIVATE走 file_mmap/CoW 路径。#[inline(never)]/ kebpf 相关注释(Godones):已全部移除 ✅。sysno()函数(Godones 建议):已按建议实现 ✅。kprobe.rs.expect()/ 短导入路径(Godones):已修复 ✅。- tracepoint 定义就近(Godones):
sched_process_fork在clone.rs,sched_process_exit在ops.rs✅。
所有未解决的 review thread 已在本轮 resolve。
本地验证
cargo fmt --check → 干净 ✅
cargo xtask clippy --package starry-kernel → 13/13 通过 ✅
git diff --check origin/dev...HEAD → 干净 ✅
grep [patch.crates-io] Cargo.toml → 无 ✅
CI 状态
GitHub Actions 对 head c8f3d94a5:
Detect changed paths→ success ✅- 其余 ~20 个 Test/Publish/Check job → skipped(path-filter 预期行为,eBPF 改动面不影响标准 CI 路径)
- 无 failure 结论
- skipped 为 path-filter 预期行为,不构成阻塞
重复/重叠分析
- #850(内核侧 eBPF 运行时):已在 dev 合并。本 PR 为增量不重复。
- #880(feat/starry-modules: hello + kebpf):本 PR 现已完全移除 kmod 模块相关改动,不再与 #880 重叠。
- dev 分支:无 eBPF 内核运行时代码。无其他 open PR 涉及相同的内核 eBPF 运行时功能。
- 无
[patch.crates-io]引入。
代码质量评估
- perf mmap 的
Arc/Weak所有权模型设计合理:VMA 持有强引用保证页存活到 munmap/exit;弱引用使得 mmap 被放弃后 fd 可重新 mmap,对齐 Linux 语义。 write_kernel_text的 LIFO 锁嵌套修复有详尽注释。- uprobe 的 per-process manager 使用 sleeping
Mutex(arm/disarm 需要地址空间操作),exception handler 用try_lock()(IRQ context 安全,单 CAS)。 task/user.rs中 uprobe 路由优先于 ptrace 处理,符合 Linux 行为。
结论
前次所有阻塞问题已正确修复。代码质量良好,注释充分,无安全/正确性/性能问题。建议合入。
Powered by mimo-v2.5-pro
| // mapping. Probe lazily here, then commit it in the MAP_SHARED arm. | ||
| let mut device_mmap_top = if matches!(map_type, MmapFlags::SHARED) { | ||
| file.as_ref() | ||
| .map(|fl| fl.device_mmap(offset as u64, length as u64)) |
There was a problem hiding this comment.
确认:当前代码仅在 MAP_SHARED 时调用 device_mmap,MAP_PRIVATE 永远走 file_mmap/CoW 路径。ZR233 指出的副作用时序问题已正确修复。
| // Ringbuf not yet mapped by userland; drop the sample silently | ||
| // — Linux behavior on EINVAL would alarm libbpf-style readers. | ||
| if !self.is_mapped() { | ||
| return Ok(()); |
There was a problem hiding this comment.
is_mapped() 检查 strong_count() > 0 和实际 write_event 之间存在极小的 TOCTOU 窗口(SpinNoPreempt 下另一 CPU 可能 munmap 掉最后的强引用)。实际风险极低(需 allocator lock + 跨 CPU 竞争),与 Linux perf ringbuf 模式一致。建议未来考虑在 write_event 中 upgrade() 临时持有强引用以彻底消除竞态。非阻塞。
| let mut manager = curr.as_thread().proc_data.uprobe_manager.try_lock()?; | ||
| let mut pt_regs = trapframe_to_ptregs(tf); | ||
| let res = kprobe::uprobe_handler_from_break(&mut manager, &mut pt_regs); | ||
| ptregs_write_back(&pt_regs, tf); |
There was a problem hiding this comment.
try_lock() 在 exception context 中使用合理:arm/disarm 在 syscall context(同一任务),fire 在 exception context,锁在此时无竞争。注释充分。
Move the aya eBPF userspace programs out of os/StarryOS/user/ebpf into apps/starry/ebpf so they sit alongside the other operator-facing Starry app cases (per review on rcore-os#886), instead of the test-suit / user-ebpf xtask path. Per-case wiring (prebuild.sh / init.sh / qemu+build toml) lands in follow-up commits. - Dedup: drop `rawtp` (its raw-tracepoint path is covered by `sched_trace`) and `async_test` (a tokio breakpoint smoke, not an eBPF program). - Rename `syscall_ebpf` -> `syscall_count` (the three crates, the eBPF program function, and the loader's `program_mut` lookup) to match the demo name. Kept: syscall_count, profile, sched_trace, kret, mytrace, upb, upb2.
…umber + fix ebpf clippy borrows 解决 ZR233 review 的两个阻塞点: 1) 多架构 syscall 号读取错误:syscall_count / profile 原先 deref handle_syscall 的 arg0(&UserContext)取首个 u64 当 syscall 号,仅 x86_64(rax 为 TrapFrame 首字段)成立,riscv64(a7)/aarch64(x8)/ loongarch64 都会读错(riscv64 实测 getpid count=0 → FAIL)。改为把 kprobe 挂到内核 rcore-os#886 预留的 #[inline(never)] syscall::sysno(id: usize), 直接读 ctx.arg(0):无 deref、无 per-arch 偏移;aya 的 arg(0) 映射到各 架构第一个参数寄存器,单份 BPF 字节码在四个架构都正确。loader 符号解析 改为 contains("syscall") && contains("sysno") 唯一定位该符号。 2) clippy needless_borrows_for_generic_args:6 个 *-ebpf crate 的 HashMap::get/insert 与 PerfEventArray::output 形参是 impl Borrow<…>, 对 Copy 值多余加 &。去掉 & 直接按值传,不使用 allow。 验证:6 个 demo + 2 个 loader cargo fmt --check 通过;6 个 *-ebpf 在 x86_64 与 riscv64 上 targeted clippy -D warnings 全绿。QEMU runtime 因本地 缺 bpf-linker 与嵌套模拟无法自验,交由 nightly / reviewer 复跑。
…/kprobe/kretprobe/tracepoint) (#1132) * feat(starry-apps): relocate eBPF userspace programs to apps/starry/ebpf Move the aya eBPF userspace programs out of os/StarryOS/user/ebpf into apps/starry/ebpf so they sit alongside the other operator-facing Starry app cases (per review on #886), instead of the test-suit / user-ebpf xtask path. Per-case wiring (prebuild.sh / init.sh / qemu+build toml) lands in follow-up commits. - Dedup: drop `rawtp` (its raw-tracepoint path is covered by `sched_trace`) and `async_test` (a tokio breakpoint smoke, not an eBPF program). - Rename `syscall_ebpf` -> `syscall_count` (the three crates, the eBPF program function, and the loader's `program_mut` lookup) to match the demo name. Kept: syscall_count, profile, sched_trace, kret, mytrace, upb, upb2. * fix(starry-apps): update upb loader to aya UProbe::attach(UProbeScope) API The vendored aya git HEAD changed UProbe::attach from (point, target, Some(pid), cookie) to (point, target, scope: UProbeScope). Use UProbeScope::CallingProcess (== attach to this process, the old Some(std::process::id())). Lets the upb uprobe demo build against current aya. * feat(starry-apps): self-contained eBPF demos with per-app QEMU run harness Turn each apps/starry/ebpf demo into a directly runnable StarryOS app (`cargo xtask starry app qemu -t ebpf/<demo>`): a prebuild.sh builds the aya loader + embedded bytecode as a static musl binary into the rootfs overlay, and qemu-x86_64.toml drives it and asserts on a printed PASS token. Each loader is rewritten to be self-contained (no tokio / aya_log): it attaches, drives a deterministic workload, reads results back from a BPF map, and prints <DEMO>_PASS / _FAIL. - syscall_count: deref arg0 (&UserContext) with bpf_probe_read to read the real syscall number (it was counting the pointer value, hence the bogus huge keys), attach to handle_syscall, assert getpid count. - upb: count uprobe hits in a HashMap the loader reads back (aya_log's perf-ringbuf does not surface on StarryOS); pass current_exe() as the uprobe target and warm up the page before attach. - kret/mytrace: drop aya_log, count kretprobe / sys_enter_openat tracepoint hits via a HashMap and assert. - profile/sched_trace: self-contained workload + assertion. Verified end-to-end in x86_64 QEMU: all six demos PASS. * chore(starry-apps): remove leftover upb2 eBPF demo (duplicate of upb) upb2 是 uprobe demo 清理前的遗留副本:仍依赖 tokio/aya_log、使用旧的 4 参数 program.attach API,且缺少 prebuild.sh / qemu-x86_64.toml / build-x86_64-unknown-none.toml,无法通过 cargo xtask starry app qemu 运行, 与 PR “所有 loader 改写为自包含” 的描述矛盾。功能已由自包含的 upb 完全覆盖, 直接删除。 * fix(starry-apps): clear clippy collapsible_if/manual_flatten in ebpf loaders Address ZR233 review on #1132: the nested-workspace clippy run flagged collapsible_if and manual_flatten in the syscall_count/profile/upb/kret loaders. Collapse the kallsyms `if let " + "if name.contains` guards into edition-2024 let-chains and replace the `for x { if let Ok(..) }` map-iter patterns with `.flatten()`. No behavior change. * feat(starry-apps): add aarch64/riscv64/loongarch64 run configs for ebpf demos Address Godones review on #1132: extend the kprobe/tracepoint demos (syscall_count, profile, kret, mytrace, sched_trace) to the other three QEMU arches so `starry app qemu --all --arch <arch>` exercises them in the nightly Starry Apps matrix. Each gains qemu-<arch>.toml + the matching build-<triple>.toml, mirroring the proven per-arch platform/driver setup (aarch64/riscv64 dynamic, loongarch64 static). upb (uprobe) stays x86_64-only: the kernel uprobe out-of-line single-step completion (debug_uprobe_handler) is #[cfg(target_arch = "x86_64")], so the demo cannot run on the other arches yet. * fix(starry-apps): probe syscall::sysno for arch-independent syscall number + fix ebpf clippy borrows 解决 ZR233 review 的两个阻塞点: 1) 多架构 syscall 号读取错误:syscall_count / profile 原先 deref handle_syscall 的 arg0(&UserContext)取首个 u64 当 syscall 号,仅 x86_64(rax 为 TrapFrame 首字段)成立,riscv64(a7)/aarch64(x8)/ loongarch64 都会读错(riscv64 实测 getpid count=0 → FAIL)。改为把 kprobe 挂到内核 #886 预留的 #[inline(never)] syscall::sysno(id: usize), 直接读 ctx.arg(0):无 deref、无 per-arch 偏移;aya 的 arg(0) 映射到各 架构第一个参数寄存器,单份 BPF 字节码在四个架构都正确。loader 符号解析 改为 contains("syscall") && contains("sysno") 唯一定位该符号。 2) clippy needless_borrows_for_generic_args:6 个 *-ebpf crate 的 HashMap::get/insert 与 PerfEventArray::output 形参是 impl Borrow<…>, 对 Copy 值多余加 &。去掉 & 直接按值传,不使用 allow。 验证:6 个 demo + 2 个 loader cargo fmt --check 通过;6 个 *-ebpf 在 x86_64 与 riscv64 上 targeted clippy -D warnings 全绿。QEMU runtime 因本地 缺 bpf-linker 与嵌套模拟无法自验,交由 nightly / reviewer 复跑。
…rcore-os#886) * feat(starry-kernel): eBPF kernel runtime for tracepoint/kprobe/perf Kernel-side eBPF runtime, split out of rcore-os#886 (its userspace programs and the `kebpf` loadable module move to separate PRs): - perf ringbuf: `mmap(perf_fd)` maps the `BpfPerfEvent` ringbuf pages, anchored to the mmap VMA to prevent a use-after-free; `FileLike::device_mmap` gains a `length` parameter (all impls updated). - sched tracepoints: `sched_switch` / `process_fork` / `process_exit` emitted via ax-feat `tracepoint-hooks`. - kprobe on x86_64: `handle_syscall` / `sys_getpid` are `#[inline(never)]` so a kprobe planted on their symbols actually fires. - raw tracepoint attach/detach made atomic-safe. - mm: `write_kernel_text` acquires the kernel-aspace lock inside `stop_machine` to keep IRQ-save guards LIFO (no leaked IRQ-disabled state on probe detach). - ebpf/transform + perf + sysfs surface supporting the above. `bpf(2)` remains served by the kernel's built-in eBPF runtime. The syscall registry that lets a loadable module (`kebpf`) take over `bpf(2)` is a separate follow-up PR (avoids a `syscall/mod.rs` conflict with this PR). * feat(starry-kernel): implement uprobe (user-space dynamic probes) Land kernel-side uprobe support so `perf_event_open(PERF_TYPE_UPROBE)` can plant a breakpoint in a user process' text and run an attached eBPF program on hit (replaces the previous `Unsupported` placeholder). Ported from the upstream `ebpf-kmod` design, adapted to tgoskits' memory/task APIs. - `task::ProcessData`: per-process `uprobe_manager` / `uprobe_point_list` (user addresses are only meaningful within one address space, unlike the global kprobe manager). - `kprobe`: implement the user-mode `KprobeAuxiliaryOps` paths — `int3` insertion via the kernel direct-map alias of the target page's physical frame (user PTE flags untouched), and an out-of-line single-step page allocated with `Backend::new_alloc` (USER|EXEC). `handle_breakpoint`/`handle_debug` fall through to the per-process uprobe handlers. - `uprobe`: new module — `register/unregister_uprobe` + break/debug dispatch on the current process' manager. - `perf::uprobe`: resolve the target ELF's mapped base by matching a VMA's file backing (`Backend::file_info().path`), then register on `base + offset`. - `perf::kprobe`: `ProbeTy::Uprobe` variant (enable/disable/callback/drop). uretprobe (`config == 1`) is still unsupported (as upstream). Verified to compile for x86_64; runtime e2e via the `upb` aya demo. * fix(starry-kernel): wire uprobe end-to-end and enable kretprobe/tracepoint attach The committed uprobe support compiled but panicked at runtime; make it actually fire, and close the gaps that blocked kretprobe and cooked tracepoint programs from attaching/running: - kprobe::copy_memory: read the target process' text for a uprobe through the kernel direct-map alias of its physical frame instead of the faultable user path (which asserts IRQs-enabled, but arm runs under the per-process manager lock). - ProcessData uprobe_manager/uprobe_point_list: SpinNoIrq -> sleeping Mutex, because arm/disarm needs the sleeping address-space lock; the exception-context handlers now take it with try_lock() (a single CAS, safe in atomic context). - task::user: route user-mode #BP/#DB exceptions to the per-process uprobe manager before signal handling, so a planted int3 fires the uprobe instead of becoming SIGTRAP. This was the missing dispatch. - perf::tracepoint: a cooked tracepoint callback receives its payload as Box<dyn Any>, so downcast through the box first (same as raw_tracepoint), fixing a "Ctx mismatch" panic when the tracepoint fires. - sysfs: expose /sys/bus/event_source/devices/{kprobe,uprobe}/format/retprobe so aya can resolve the retprobe config bit for kretprobe/uretprobe attach. - ebpf: alias helper id 113 (bpf_probe_read_kernel, emitted by aya's TracePointContext::read_at) onto the existing bpf_probe_read. Verified end-to-end in x86_64 QEMU: uprobe, kprobe, kretprobe, raw tracepoint and cooked tracepoint eBPF programs all attach and fire. * fix(starry-kernel): keep perf ringbuf mmap side-effect-free on non-direct paths A failed or non-direct mmap of a perf fd must not consume its single ringbuf slot. Two fixes: - sys_mmap only probes device_mmap for MAP_SHARED; MAP_PRIVATE never uses the result, so calling it would needlessly allocate the perf ringbuf and leave the fd un-mmap-able for the later real MAP_SHARED mapping. - BpfPerfEventWrapper now keeps only a Weak to the ringbuf pages; the sole strong ref is owned by the user VMA. An mmap abandoned or failed before a VMA adopts the anchor (permission/address error, aspace.map failure) frees the pages and leaves the fd mmap-able again, and a re-mmap after munmap is now allowed (matching Linux) instead of returning ResourceBusy forever. UAF safety is unchanged: the VMA's strong ref keeps the pages alive past close(perf_fd). RingPage has no destructor and is only dereferenced while is_mapped() holds, so a dangling pointer after free is never accessed. * fix(starry-kernel): collapse uprobe exception arms into match guards clippy collapsible_match flagged the per-exception uprobe routing where each arm body was a single `if handler(..).is_some() { break 'exc }`. Fold the condition into the arm guard; behavior is identical (handler called once, falls through to ptrace handling on None). * refactor(starry-kernel): address PR rcore-os#886 review (probe point + drop kebpf inline-never) 按 @Godones 复审意见处理: - syscall/mod.rs:抽出 `#[inline(never)] sysno()` 作为 kprobe 挂载点, 其第一个参数寄存器直接持有 syscall id(demo 可直接读取); `handle_syscall` 去掉 `#[inline(never)]`,改为转调 `sysno()`。 - ebpf/{map,prog,transform}.rs:移除面向 kebpf 可加载模块的全部 `#[inline(never)]` 及相关注释(内核与 kmod 同步内联即无符号依赖, 当前不需关注 kebpf)。 - ebpf/mod.rs:删除 `handle_prog_load` 中仅用于 kebpf 单态化的描述 与无用的 `_verifier_info` 绑定。 - kprobe.rs:`copy_memory` 取不到目标任务时直接 `.expect`(return 后 续 uprobe 设置仍会崩溃);导入 `MappingFlags`/`PageSize`,去掉过长路径。 本机 `cargo xtask starry build --arch x86_64` 通过,`cargo fmt` 干净。
…/kprobe/kretprobe/tracepoint) (rcore-os#1132) * feat(starry-apps): relocate eBPF userspace programs to apps/starry/ebpf Move the aya eBPF userspace programs out of os/StarryOS/user/ebpf into apps/starry/ebpf so they sit alongside the other operator-facing Starry app cases (per review on rcore-os#886), instead of the test-suit / user-ebpf xtask path. Per-case wiring (prebuild.sh / init.sh / qemu+build toml) lands in follow-up commits. - Dedup: drop `rawtp` (its raw-tracepoint path is covered by `sched_trace`) and `async_test` (a tokio breakpoint smoke, not an eBPF program). - Rename `syscall_ebpf` -> `syscall_count` (the three crates, the eBPF program function, and the loader's `program_mut` lookup) to match the demo name. Kept: syscall_count, profile, sched_trace, kret, mytrace, upb, upb2. * fix(starry-apps): update upb loader to aya UProbe::attach(UProbeScope) API The vendored aya git HEAD changed UProbe::attach from (point, target, Some(pid), cookie) to (point, target, scope: UProbeScope). Use UProbeScope::CallingProcess (== attach to this process, the old Some(std::process::id())). Lets the upb uprobe demo build against current aya. * feat(starry-apps): self-contained eBPF demos with per-app QEMU run harness Turn each apps/starry/ebpf demo into a directly runnable StarryOS app (`cargo xtask starry app qemu -t ebpf/<demo>`): a prebuild.sh builds the aya loader + embedded bytecode as a static musl binary into the rootfs overlay, and qemu-x86_64.toml drives it and asserts on a printed PASS token. Each loader is rewritten to be self-contained (no tokio / aya_log): it attaches, drives a deterministic workload, reads results back from a BPF map, and prints <DEMO>_PASS / _FAIL. - syscall_count: deref arg0 (&UserContext) with bpf_probe_read to read the real syscall number (it was counting the pointer value, hence the bogus huge keys), attach to handle_syscall, assert getpid count. - upb: count uprobe hits in a HashMap the loader reads back (aya_log's perf-ringbuf does not surface on StarryOS); pass current_exe() as the uprobe target and warm up the page before attach. - kret/mytrace: drop aya_log, count kretprobe / sys_enter_openat tracepoint hits via a HashMap and assert. - profile/sched_trace: self-contained workload + assertion. Verified end-to-end in x86_64 QEMU: all six demos PASS. * chore(starry-apps): remove leftover upb2 eBPF demo (duplicate of upb) upb2 是 uprobe demo 清理前的遗留副本:仍依赖 tokio/aya_log、使用旧的 4 参数 program.attach API,且缺少 prebuild.sh / qemu-x86_64.toml / build-x86_64-unknown-none.toml,无法通过 cargo xtask starry app qemu 运行, 与 PR “所有 loader 改写为自包含” 的描述矛盾。功能已由自包含的 upb 完全覆盖, 直接删除。 * fix(starry-apps): clear clippy collapsible_if/manual_flatten in ebpf loaders Address ZR233 review on rcore-os#1132: the nested-workspace clippy run flagged collapsible_if and manual_flatten in the syscall_count/profile/upb/kret loaders. Collapse the kallsyms `if let " + "if name.contains` guards into edition-2024 let-chains and replace the `for x { if let Ok(..) }` map-iter patterns with `.flatten()`. No behavior change. * feat(starry-apps): add aarch64/riscv64/loongarch64 run configs for ebpf demos Address Godones review on rcore-os#1132: extend the kprobe/tracepoint demos (syscall_count, profile, kret, mytrace, sched_trace) to the other three QEMU arches so `starry app qemu --all --arch <arch>` exercises them in the nightly Starry Apps matrix. Each gains qemu-<arch>.toml + the matching build-<triple>.toml, mirroring the proven per-arch platform/driver setup (aarch64/riscv64 dynamic, loongarch64 static). upb (uprobe) stays x86_64-only: the kernel uprobe out-of-line single-step completion (debug_uprobe_handler) is #[cfg(target_arch = "x86_64")], so the demo cannot run on the other arches yet. * fix(starry-apps): probe syscall::sysno for arch-independent syscall number + fix ebpf clippy borrows 解决 ZR233 review 的两个阻塞点: 1) 多架构 syscall 号读取错误:syscall_count / profile 原先 deref handle_syscall 的 arg0(&UserContext)取首个 u64 当 syscall 号,仅 x86_64(rax 为 TrapFrame 首字段)成立,riscv64(a7)/aarch64(x8)/ loongarch64 都会读错(riscv64 实测 getpid count=0 → FAIL)。改为把 kprobe 挂到内核 rcore-os#886 预留的 #[inline(never)] syscall::sysno(id: usize), 直接读 ctx.arg(0):无 deref、无 per-arch 偏移;aya 的 arg(0) 映射到各 架构第一个参数寄存器,单份 BPF 字节码在四个架构都正确。loader 符号解析 改为 contains("syscall") && contains("sysno") 唯一定位该符号。 2) clippy needless_borrows_for_generic_args:6 个 *-ebpf crate 的 HashMap::get/insert 与 PerfEventArray::output 形参是 impl Borrow<…>, 对 Copy 值多余加 &。去掉 & 直接按值传,不使用 allow。 验证:6 个 demo + 2 个 loader cargo fmt --check 通过;6 个 *-ebpf 在 x86_64 与 riscv64 上 targeted clippy -D warnings 全绿。QEMU runtime 因本地 缺 bpf-linker 与嵌套模拟无法自验,交由 nightly / reviewer 复跑。
…#886) * feat(starry-kernel): eBPF kernel runtime for tracepoint/kprobe/perf Kernel-side eBPF runtime, split out of #886 (its userspace programs and the `kebpf` loadable module move to separate PRs): - perf ringbuf: `mmap(perf_fd)` maps the `BpfPerfEvent` ringbuf pages, anchored to the mmap VMA to prevent a use-after-free; `FileLike::device_mmap` gains a `length` parameter (all impls updated). - sched tracepoints: `sched_switch` / `process_fork` / `process_exit` emitted via ax-feat `tracepoint-hooks`. - kprobe on x86_64: `handle_syscall` / `sys_getpid` are `#[inline(never)]` so a kprobe planted on their symbols actually fires. - raw tracepoint attach/detach made atomic-safe. - mm: `write_kernel_text` acquires the kernel-aspace lock inside `stop_machine` to keep IRQ-save guards LIFO (no leaked IRQ-disabled state on probe detach). - ebpf/transform + perf + sysfs surface supporting the above. `bpf(2)` remains served by the kernel's built-in eBPF runtime. The syscall registry that lets a loadable module (`kebpf`) take over `bpf(2)` is a separate follow-up PR (avoids a `syscall/mod.rs` conflict with this PR). * feat(starry-kernel): implement uprobe (user-space dynamic probes) Land kernel-side uprobe support so `perf_event_open(PERF_TYPE_UPROBE)` can plant a breakpoint in a user process' text and run an attached eBPF program on hit (replaces the previous `Unsupported` placeholder). Ported from the upstream `ebpf-kmod` design, adapted to tgoskits' memory/task APIs. - `task::ProcessData`: per-process `uprobe_manager` / `uprobe_point_list` (user addresses are only meaningful within one address space, unlike the global kprobe manager). - `kprobe`: implement the user-mode `KprobeAuxiliaryOps` paths — `int3` insertion via the kernel direct-map alias of the target page's physical frame (user PTE flags untouched), and an out-of-line single-step page allocated with `Backend::new_alloc` (USER|EXEC). `handle_breakpoint`/`handle_debug` fall through to the per-process uprobe handlers. - `uprobe`: new module — `register/unregister_uprobe` + break/debug dispatch on the current process' manager. - `perf::uprobe`: resolve the target ELF's mapped base by matching a VMA's file backing (`Backend::file_info().path`), then register on `base + offset`. - `perf::kprobe`: `ProbeTy::Uprobe` variant (enable/disable/callback/drop). uretprobe (`config == 1`) is still unsupported (as upstream). Verified to compile for x86_64; runtime e2e via the `upb` aya demo. * fix(starry-kernel): wire uprobe end-to-end and enable kretprobe/tracepoint attach The committed uprobe support compiled but panicked at runtime; make it actually fire, and close the gaps that blocked kretprobe and cooked tracepoint programs from attaching/running: - kprobe::copy_memory: read the target process' text for a uprobe through the kernel direct-map alias of its physical frame instead of the faultable user path (which asserts IRQs-enabled, but arm runs under the per-process manager lock). - ProcessData uprobe_manager/uprobe_point_list: SpinNoIrq -> sleeping Mutex, because arm/disarm needs the sleeping address-space lock; the exception-context handlers now take it with try_lock() (a single CAS, safe in atomic context). - task::user: route user-mode #BP/#DB exceptions to the per-process uprobe manager before signal handling, so a planted int3 fires the uprobe instead of becoming SIGTRAP. This was the missing dispatch. - perf::tracepoint: a cooked tracepoint callback receives its payload as Box<dyn Any>, so downcast through the box first (same as raw_tracepoint), fixing a "Ctx mismatch" panic when the tracepoint fires. - sysfs: expose /sys/bus/event_source/devices/{kprobe,uprobe}/format/retprobe so aya can resolve the retprobe config bit for kretprobe/uretprobe attach. - ebpf: alias helper id 113 (bpf_probe_read_kernel, emitted by aya's TracePointContext::read_at) onto the existing bpf_probe_read. Verified end-to-end in x86_64 QEMU: uprobe, kprobe, kretprobe, raw tracepoint and cooked tracepoint eBPF programs all attach and fire. * fix(starry-kernel): keep perf ringbuf mmap side-effect-free on non-direct paths A failed or non-direct mmap of a perf fd must not consume its single ringbuf slot. Two fixes: - sys_mmap only probes device_mmap for MAP_SHARED; MAP_PRIVATE never uses the result, so calling it would needlessly allocate the perf ringbuf and leave the fd un-mmap-able for the later real MAP_SHARED mapping. - BpfPerfEventWrapper now keeps only a Weak to the ringbuf pages; the sole strong ref is owned by the user VMA. An mmap abandoned or failed before a VMA adopts the anchor (permission/address error, aspace.map failure) frees the pages and leaves the fd mmap-able again, and a re-mmap after munmap is now allowed (matching Linux) instead of returning ResourceBusy forever. UAF safety is unchanged: the VMA's strong ref keeps the pages alive past close(perf_fd). RingPage has no destructor and is only dereferenced while is_mapped() holds, so a dangling pointer after free is never accessed. * fix(starry-kernel): collapse uprobe exception arms into match guards clippy collapsible_match flagged the per-exception uprobe routing where each arm body was a single `if handler(..).is_some() { break 'exc }`. Fold the condition into the arm guard; behavior is identical (handler called once, falls through to ptrace handling on None). * refactor(starry-kernel): address PR #886 review (probe point + drop kebpf inline-never) 按 @Godones 复审意见处理: - syscall/mod.rs:抽出 `#[inline(never)] sysno()` 作为 kprobe 挂载点, 其第一个参数寄存器直接持有 syscall id(demo 可直接读取); `handle_syscall` 去掉 `#[inline(never)]`,改为转调 `sysno()`。 - ebpf/{map,prog,transform}.rs:移除面向 kebpf 可加载模块的全部 `#[inline(never)]` 及相关注释(内核与 kmod 同步内联即无符号依赖, 当前不需关注 kebpf)。 - ebpf/mod.rs:删除 `handle_prog_load` 中仅用于 kebpf 单态化的描述 与无用的 `_verifier_info` 绑定。 - kprobe.rs:`copy_memory` 取不到目标任务时直接 `.expect`(return 后 续 uprobe 设置仍会崩溃);导入 `MappingFlags`/`PageSize`,去掉过长路径。 本机 `cargo xtask starry build --arch x86_64` 通过,`cargo fmt` 干净。
…/kprobe/kretprobe/tracepoint) (#1132) * feat(starry-apps): relocate eBPF userspace programs to apps/starry/ebpf Move the aya eBPF userspace programs out of os/StarryOS/user/ebpf into apps/starry/ebpf so they sit alongside the other operator-facing Starry app cases (per review on #886), instead of the test-suit / user-ebpf xtask path. Per-case wiring (prebuild.sh / init.sh / qemu+build toml) lands in follow-up commits. - Dedup: drop `rawtp` (its raw-tracepoint path is covered by `sched_trace`) and `async_test` (a tokio breakpoint smoke, not an eBPF program). - Rename `syscall_ebpf` -> `syscall_count` (the three crates, the eBPF program function, and the loader's `program_mut` lookup) to match the demo name. Kept: syscall_count, profile, sched_trace, kret, mytrace, upb, upb2. * fix(starry-apps): update upb loader to aya UProbe::attach(UProbeScope) API The vendored aya git HEAD changed UProbe::attach from (point, target, Some(pid), cookie) to (point, target, scope: UProbeScope). Use UProbeScope::CallingProcess (== attach to this process, the old Some(std::process::id())). Lets the upb uprobe demo build against current aya. * feat(starry-apps): self-contained eBPF demos with per-app QEMU run harness Turn each apps/starry/ebpf demo into a directly runnable StarryOS app (`cargo xtask starry app qemu -t ebpf/<demo>`): a prebuild.sh builds the aya loader + embedded bytecode as a static musl binary into the rootfs overlay, and qemu-x86_64.toml drives it and asserts on a printed PASS token. Each loader is rewritten to be self-contained (no tokio / aya_log): it attaches, drives a deterministic workload, reads results back from a BPF map, and prints <DEMO>_PASS / _FAIL. - syscall_count: deref arg0 (&UserContext) with bpf_probe_read to read the real syscall number (it was counting the pointer value, hence the bogus huge keys), attach to handle_syscall, assert getpid count. - upb: count uprobe hits in a HashMap the loader reads back (aya_log's perf-ringbuf does not surface on StarryOS); pass current_exe() as the uprobe target and warm up the page before attach. - kret/mytrace: drop aya_log, count kretprobe / sys_enter_openat tracepoint hits via a HashMap and assert. - profile/sched_trace: self-contained workload + assertion. Verified end-to-end in x86_64 QEMU: all six demos PASS. * chore(starry-apps): remove leftover upb2 eBPF demo (duplicate of upb) upb2 是 uprobe demo 清理前的遗留副本:仍依赖 tokio/aya_log、使用旧的 4 参数 program.attach API,且缺少 prebuild.sh / qemu-x86_64.toml / build-x86_64-unknown-none.toml,无法通过 cargo xtask starry app qemu 运行, 与 PR “所有 loader 改写为自包含” 的描述矛盾。功能已由自包含的 upb 完全覆盖, 直接删除。 * fix(starry-apps): clear clippy collapsible_if/manual_flatten in ebpf loaders Address ZR233 review on #1132: the nested-workspace clippy run flagged collapsible_if and manual_flatten in the syscall_count/profile/upb/kret loaders. Collapse the kallsyms `if let " + "if name.contains` guards into edition-2024 let-chains and replace the `for x { if let Ok(..) }` map-iter patterns with `.flatten()`. No behavior change. * feat(starry-apps): add aarch64/riscv64/loongarch64 run configs for ebpf demos Address Godones review on #1132: extend the kprobe/tracepoint demos (syscall_count, profile, kret, mytrace, sched_trace) to the other three QEMU arches so `starry app qemu --all --arch <arch>` exercises them in the nightly Starry Apps matrix. Each gains qemu-<arch>.toml + the matching build-<triple>.toml, mirroring the proven per-arch platform/driver setup (aarch64/riscv64 dynamic, loongarch64 static). upb (uprobe) stays x86_64-only: the kernel uprobe out-of-line single-step completion (debug_uprobe_handler) is #[cfg(target_arch = "x86_64")], so the demo cannot run on the other arches yet. * fix(starry-apps): probe syscall::sysno for arch-independent syscall number + fix ebpf clippy borrows 解决 ZR233 review 的两个阻塞点: 1) 多架构 syscall 号读取错误:syscall_count / profile 原先 deref handle_syscall 的 arg0(&UserContext)取首个 u64 当 syscall 号,仅 x86_64(rax 为 TrapFrame 首字段)成立,riscv64(a7)/aarch64(x8)/ loongarch64 都会读错(riscv64 实测 getpid count=0 → FAIL)。改为把 kprobe 挂到内核 #886 预留的 #[inline(never)] syscall::sysno(id: usize), 直接读 ctx.arg(0):无 deref、无 per-arch 偏移;aya 的 arg(0) 映射到各 架构第一个参数寄存器,单份 BPF 字节码在四个架构都正确。loader 符号解析 改为 contains("syscall") && contains("sysno") 唯一定位该符号。 2) clippy needless_borrows_for_generic_args:6 个 *-ebpf crate 的 HashMap::get/insert 与 PerfEventArray::output 形参是 impl Borrow<…>, 对 Copy 值多余加 &。去掉 & 直接按值传,不使用 allow。 验证:6 个 demo + 2 个 loader cargo fmt --check 通过;6 个 *-ebpf 在 x86_64 与 riscv64 上 targeted clippy -D warnings 全绿。QEMU runtime 因本地 缺 bpf-linker 与嵌套模拟无法自验,交由 nightly / reviewer 复跑。
按 reviewer @Godones 意见,#886 已拆分:本 PR 现在只保留内核侧 eBPF 运行时。用户态 aya 程序将迁到
apps/starry/ebpf/单独成 PR(基于本 PR 栈式提交);kebpf可加载模块 +bpf(2)运行时注册待本 PR 合并后再单独提交。变更内容(纯内核运行时,25 文件)
StarryOS 内核(
os/StarryOS/kernel)mmap(perf_fd)映射BpfPerfEventringbuf 页,并锚定到 mmap VMA 防止 UAF;FileLike::device_mmap增加length参数(所有实现同步更新)。handle_syscall/sys_getpid加#[inline(never)],使挂在其符号上的 kprobe 真正触发。write_kernel_text在stop_machine内部加内核地址空间锁,保持 IRQ-save guard 的 LIFO 嵌套(探针 detach 时不再泄漏 IRQ-disabled 状态)。ebpf/transform、perf、sysfs等配套面。ArceOS 调度 tracepoint 基础设施
axfeat/axtask新增tracepoint-hooksfeature。axtask:SchedTracepoint跨 crate hook(经ax-crate-interface),在调度切换 / fork / exit 时触发sched:*tracepoint。说明
bpf(2)仍由内核内置 eBPF 运行时处理;让可加载模块接管bpf(2)的 syscall 注册表(kebpf)是后续单独 PR(避免与本 PR 在syscall/mod.rs冲突)。cargo xtask starry build --arch x86_64通过。