Skip to content

fix(starry): replace magic numbers in tracepoint and ebpf init#1404

Closed
CN-TangLin wants to merge 6 commits into
rcore-os:devfrom
CN-TangLin:fix/starry-tracepoint-ebpf-magic-numbers
Closed

fix(starry): replace magic numbers in tracepoint and ebpf init#1404
CN-TangLin wants to merge 6 commits into
rcore-os:devfrom
CN-TangLin:fix/starry-tracepoint-ebpf-magic-numbers

Conversation

@CN-TangLin

Copy link
Copy Markdown
Contributor

问题

tracepoint 和 ebpf 模块中存在四处硬编码的数字字面量:

  • tracepoint/mod.rs: TracePipeRaw::new(4096)NonZero::new(4096).unwrap()
  • ebpf/mod.rs: set.get(&4)set.entry(113) —— BPF helper function ID

变更

定义为命名常量并替换:

  • TRACE_RAW_PIPE_CAPACITY: usize = 4096 —— trace pipe 环形缓冲区最大记录数
  • TRACE_CMDLINE_CACHE_SIZE: usize = 4096 —— 进程命令行缓存容量
  • BPF_FUNC_PROBE_READ: u32 = 4 —— bpf_probe_read helper ID
  • BPF_FUNC_PROBE_READ_KERNEL: u32 = 113 —— bpf_probe_read_kernel helper ID

逻辑

遵循"严禁硬编码"原则,使用命名常量替代字面量,提高代码可读性和可维护性。

Replace raw config values 0/1 in kprobe/uprobe dispatch with named
constants PROBE_CONFIG_ENTRY / PROBE_CONFIG_RETURN, matching the
Linux PERF_TYPE_PROBE ABI.  Also refactor the kprobe config match
from a nested if/else chain into flat const-pattern match arms.
为 BpfPerfEventWrapper 实现 try_read_record 方法,使 perf event fd
支持 read(2) 系统调用读取 ringbuf 中的 eBPF 输出记录。

主要变更:
- bpf.rs: 添加 mmap_kvirt 字段保存 ringbuf 内核虚拟地址,实现
  try_read_record 从 perf_event_mmap_page 读取 data_head/data_tail,
  处理环缓冲区 wrapping,读取 perf_event_header 确定记录尺寸,
  推进 data_tail;添加 wrapping_add/copy_ring 辅助函数
- mod.rs: 实现 FileLike::read,通过 downcast 获取 BpfPerfEventWrapper
  并调用 try_read_record,使用 PAGE_SIZE_4K 作为栈缓冲区尺寸常量
将 PerfEvent::read 从轮询式非阻塞读重构为基于 block_on(poll_io(...))
的阻塞读模式,匹配 Linux read(perf_fd) 语义。当 ringbuf 无数据时
返回 WouldBlock 让 poll_io 等待,数据到达后由已有的
BpfPerfEventWrapper poll 基础设施(poll_ready/poll_notify/IrqNotify)
唤醒任务继续读取。

重构要点:
- 使用 block_on(poll_io(...)) 替代简单轮询,复用已有的 Pollable 实现
- read 闭包在返回 WouldBlock 前释放 SpinNoPreempt 锁
- 通过 PerfEvent::poll → BpfPerfEventWrapper::poll 获取可读性状态
- 通过 PerfEvent::register → BpfPerfEventWrapper::register 注册 waker
消除 perf 模块中的两处硬编码:
- BPF_JIT_MEM_PAGES = 4:x86_64 JIT 可执行内存页数
- KRETPROBE_MAX_ACTIVE = 10:kretprobe 最大并发实例数

使用命名常量替代字面量,提高代码可读性和可维护性。
为 PerfEvent 添加 nonblocking 标志支持:
- PerfEvent 新增 AtomicBool 字段存储 O_NONBLOCK 状态
- 实现 FileLike::nonblocking() / set_nonblocking()
- read(2) 在 nonblocking 模式下,ringbuf 为空时立即返回 EAGAIN
  而非阻塞等待(通过 poll_io 的 non_blocking 参数传递)
消除 tracepoint 和 ebpf 模块中的四处硬编码:
- TRACE_RAW_PIPE_CAPACITY = 4096:trace pipe 环形缓冲区最大记录数
- TRACE_CMDLINE_CACHE_SIZE = 4096:进程命令行缓存容量
- BPF_FUNC_PROBE_READ = 4:bpf_probe_read helper ID
- BPF_FUNC_PROBE_READ_KERNEL = 113:bpf_probe_read_kernel helper ID

使用命名常量替代字面量,提高代码可读性和可维护性。
@CN-TangLin

Copy link
Copy Markdown
Contributor Author

Consolidated into #1412 or #1413

@CN-TangLin CN-TangLin closed this Jun 27, 2026

@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 #1404 Review — 已关闭,合并至 #1412

状态: 此 PR 已关闭(未合并),内容已合并到 #1412。本次审查作为记录性代码审查。


📋 总览

6 个文件变更,+196/-28。标题为「replace magic numbers in tracepoint and ebpf init」,但实际 diff 包含了远超魔数替换的功能:PerfEvent::read() 完整实现、ring buffer 读取逻辑、nonblocking 支持等。建议后续将功能增强和纯重命名/魔数替换分开为独立 PR。

✅ 做得好的部分

  1. 常量命名BPF_FUNC_PROBE_READBPF_FUNC_PROBE_READ_KERNELPROBE_CONFIG_ENTRY/PROBE_CONFIG_RETURNKRETPROBE_MAX_ACTIVEBPF_JIT_MEM_PAGESTRACE_RAW_PIPE_CAPACITYTRACE_CMDLINE_CACHE_SIZE 命名清晰,注释充分。

  2. match 模式重构PerfProbeConfig::Raw(PROBE_CONFIG_ENTRY) 比原来的 if val == 0 / val == 1 更清晰、更安全。

  3. uprobe.rs 复用常量:从 kprobe 模块导入 PROBE_CONFIG_ENTRY/PROBE_CONFIG_RETURN 避免了重复定义。

🔍 代码正确性分析

  1. wrapping_add + copy_ring 环形缓冲区读取 (perf/bpf.rs):

    • data_region_size 是 2 的幂次页面数,base < modulusoffset < modulus,因此 wrapping_addsum % modulus 路径正确。
    • copy_ring 的 wrap-around 处理正确:to.wrapping_sub(from) % ring_size 在 ring_size 为 2 的幂时等价于 (to - from + ring_size) % ring_size
    • ✅ 无越界风险。
  2. try_read_record 并发安全 (perf/bpf.rs:125):

    • 调用路径受 PerfEvent::read()SpinNoPreempt 锁保护,data_tail 更新不会并发竞争。
    • mmap_kvirt 的 header page 和 data region 不重叠(data_region 偏移 PAGE_SIZE_4K),无 aliasing 问题。
    • 建议在 fn doc comment 中补充「必须在 SpinNoPreempt 锁内调用」的并发前提条件。
  3. PerfEvent::read()drop(event) 位置 (perf/mod.rs:136):在写入 dst 之前释放 spin lock,避免在持锁期间做 I/O 和 poll_io 调度。设计合理。

⚠️ 建议改进

  1. bpf.rs 安全注释try_read_record 中有多处 unsafe 块。虽然 SAFETY 注释充分,但建议补充并发约束到函数级 doc comment。

  2. record_size 校验record_size < hdr_size 检查已覆盖 size=0 的情况。✅

  3. data_tail 累加溢出u64 类型,正常使用下不会溢出。✅

CI 状态

所有 CI check runs 均为 skipped(PR 关闭过快,CI 未实际运行)。本地无需重复构建。

结论

代码质量整体良好,魔数替换和 read() 实现逻辑正确。此 PR 已被作者合并至 #1412,建议在 #1412 上继续审查。

Powered by mimo-v2.5-pro

CN-TangLin added a commit to CN-TangLin/tgoskits that referenced this pull request Jul 1, 2026
…pf/tracepoint

Replace magic numbers with named constants and improve security in
perf, ebpf, and tracepoint subsystems:

- perf/kprobe: add PROBE_CONFIG_ENTRY/RETURN constants, refactor
  config match from if/else chain into const-pattern arms
- perf/bpf: add BPF_JIT_MEM_PAGES constant, replace magic 4 with it
- perf/bpf: remove vm.register_allowed_memory(0..u64::MAX) to
  restrict BPF direct memory access, preventing buggy/hostile
  programs from reading arbitrary kernel memory
- perf/kprobe: add KRETPROBE_MAX_ACTIVE constant (10, per Linux
  max(10, 2*NR_CPUS) for single-CPU), replace magic 10 in builder
- tracepoint/mod: add MAX_ACTIVE_TRACEPOINTS (16) and
  MAX_SLOTS_PER_TRACEPOINT (64) constants
- ebpf/mod: add MAX_EXEC_MEM_PAGES (256) constant, replace magic 256
  in JIT executable memory allocation

Changes combined from PRs rcore-os#1399, rcore-os#1402, rcore-os#1404, rcore-os#1405.
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.

1 participant