惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
量子位
M
MIT News - Artificial intelligence
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Google DeepMind News
Google DeepMind News
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
雷峰网
雷峰网
I
InfoQ
罗磊的独立博客
博客园 - 聂微东
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
D
Docker
H
Hackread – Cybersecurity News, Data Breaches, AI and More
腾讯CDC
博客园 - 三生石上(FineUI控件)
The GitHub Blog
The GitHub Blog
K
Kaspersky official blog
P
Privacy & Cybersecurity Law Blog
S
SegmentFault 最新的问题
T
Threat Research - Cisco Blogs
H
Help Net Security
小众软件
小众软件
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
CERT Recently Published Vulnerability Notes
WordPress大学
WordPress大学
T
Tenable Blog
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
博客园 - Franky
A
Arctic Wolf
T
Threatpost
Scott Helme
Scott Helme
C
Cybersecurity and Infrastructure Security Agency CISA
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
The Exploit Database - CXSecurity.com
G
GRAHAM CLULEY
Security Latest
Security Latest
Spread Privacy
Spread Privacy
L
LINUX DO - 热门话题
V
Vulnerabilities – Threatpost
P
Privacy International News Feed
S
Schneier on Security
Latest news
Latest news
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com

一派胡言

吉隆坡游记 | 一派胡言 春节观鸟记:罗定篇 | 一派胡言 春节观鸟记:广州篇 | 一派胡言 观鸟改变了我 | 一派胡言 个人春秋2025 | 一派胡言 观鸟记:20251214, 20251220, 20251221, 20251225 | 一派胡言 那是傻瓜的血脉使然啊 | 一派胡言 观鸟记:Sungei Buloh 20251101 | 一派胡言 观鸟记: Tampines Eco Green 20251011 | 一派胡言 涅磐 | 一派胡言 东京也无非是这样 | 一派胡言 回忆我的中学母校 | 一派胡言 2025年Q1 漫画月旦 | 一派胡言 个人春秋2024 | 一派胡言 回顾21世纪 | 一派胡言 聊斋笔记若干 | 一派胡言 阅微草堂中的纪晓岚 | 一派胡言 Ipoh 游记 | 一派胡言 个人春秋2023 | 一派胡言 ebpf 札记(4): 用 ebpf 侦测函数内部的状态 | 一派胡言 ebpf 札记(3): 一个跟踪 kernel I/O request 生命周期的脚本 | 一派胡言 ebpf 札记(2): samples/bpf/cpustat(WIP) | 一派胡言 ebpf 札记(1): bpf_types.h | 一派胡言 The Linux Kernel Module Programming Guide 读书笔记 | 一派胡言 彼岸人生 | 一派胡言 同光之间的罗定——《晚清官场镜像》读书笔记 | 一派胡言 个人春秋2022 | 一派胡言 再看 Ghost in the Shell | 一派胡言 不要偷懒 | 一派胡言 个人阅读史2020 | 一派胡言 戒酒记 | 一派胡言 新加坡观察:基督教后期圣徒教会(LDS) | 一派胡言 debian 包的依赖问题 | 一派胡言 博客迁移日记 | 一派胡言
ebpf 札记(5): bpftrace cgroup_path 无法用作 map key | 一派胡言
2024-10-01 · via 一派胡言

背景

bpftrace 的函数 cgroup_path 接受 cgroup id ,返回一个表示 cgroup path 的字符串。 我们很容易觉得它应该可以用做 bpftrace 里面的 map key ,所以不久前社区有一个 issue 要求支持 cgroup_path 作为 map key。

结论

为这个 issue 提了一个 PR 之后,我发现这个实现有一个无法解决的问题:

bpftrace -e 'BEGIN { @[cgroup_path(13)]=42; @debug_var=@[cgroup_path(13)]; }'

考虑这样一个脚本,最后退出运行的时候,我们会发现虽然这个匿名的 map (@) 会有值, key 是对应13的 cgroup path,值是42,但是 @debug_var 会是0。

因为无法解决问题,所以最后这个 issue 被关闭了,目前 bpftrace cgroup_path 无法成为 map key。

原因

使用 bpftrace emit-elf1 功能,我们可以得到 bpftrace script 对应的 elf 文件:

bpftrace -e 'BEGIN { @[cgroup_path(13)]=42; @debug_var=@[cgroup_path(13)]; }' --emit-elf cgroup_elf

使用 llvm-objdump -S cgroup_elf 我们有:

cgroup_elf:	file format elf64-bpf

Disassembly of section s_BEGIN_1:

0000000000000000 <BEGIN_1>:
       0:	b7 07 00 00 0d 00 00 00	r7 = 0xd
       1:	7b 7a d8 ff 00 00 00 00	*(u64 *)(r10 - 0x28) = r7
       2:	b7 06 00 00 00 00 00 00	r6 = 0x0
       3:	7b 6a d0 ff 00 00 00 00	*(u64 *)(r10 - 0x30) = r6
       4:	b7 01 00 00 2a 00 00 00	r1 = 0x2a
       5:	7b 1a e0 ff 00 00 00 00	*(u64 *)(r10 - 0x20) = r1
       6:	bf a2 00 00 00 00 00 00	r2 = r10
       7:	07 02 00 00 d0 ff ff ff	r2 += -0x30
       8:	bf a3 00 00 00 00 00 00	r3 = r10
       9:	07 03 00 00 e0 ff ff ff	r3 += -0x20
      10:	18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00	r1 = 0x0 ll
      12:	b7 04 00 00 00 00 00 00	r4 = 0x0
      13:	85 00 00 00 02 00 00 00	call 0x2
      14:	7b 7a e8 ff 00 00 00 00	*(u64 *)(r10 - 0x18) = r7
      15:	b7 01 00 00 01 00 00 00	r1 = 0x1
      16:	7b 1a e0 ff 00 00 00 00	*(u64 *)(r10 - 0x20) = r1
      17:	bf a2 00 00 00 00 00 00	r2 = r10
      18:	07 02 00 00 e0 ff ff ff	r2 += -0x20
      19:	18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00	r1 = 0x0 ll
      21:	85 00 00 00 01 00 00 00	call 0x1
      22:	b7 01 00 00 00 00 00 00	r1 = 0x0
      23:	15 00 01 00 00 00 00 00	if r0 == 0x0 goto +0x1 <LBB0_2>
      24:	79 01 00 00 00 00 00 00	r1 = *(u64 *)(r0 + 0x0)

00000000000000c8 <LBB0_2>:
      25:	7b 6a f0 ff 00 00 00 00	*(u64 *)(r10 - 0x10) = r6
      26:	7b 1a f8 ff 00 00 00 00	*(u64 *)(r10 - 0x8) = r1
      27:	bf a2 00 00 00 00 00 00	r2 = r10
      28:	07 02 00 00 f0 ff ff ff	r2 += -0x10
      29:	bf a3 00 00 00 00 00 00	r3 = r10
      30:	07 03 00 00 f8 ff ff ff	r3 += -0x8
      31:	18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00	r1 = 0x0 ll
      33:	b7 04 00 00 00 00 00 00	r4 = 0x0
      34:	85 00 00 00 02 00 00 00	call 0x2
      35:	b7 00 00 00 00 00 00 00	r0 = 0x0
      36:	95 00 00 00 00 00 00 00	exit

13行 call 0x2 调用 bpf_map_update_elem, 21行 call 0x1 调用 bpf_map_lookup_elem , 从这两行回去看 key 的构造,可以发现,在2-5行,代码用了两个 u64 来存 bpf_map_update_elem 的 key <13, 0> (13 是我们传入的 cgroup id, 0 是 cgroup_path_id 后文我们会讨论)。 在14-16行,我们看到 bpf_map_lookup_elem 使用的 key 是 <13, 1> , *因为 update 和 lookup 的时候使用了不同的 key,所以在 map 中使用 cgroup_path 作为 key 无法达成我们预期的结果*。

cgroup_path 的实现

cgroup_path 在 bpftrace 里面其实是一个函数: ```shell cgroup_path(int cgroupid, string filter) ``` 在生成 IR 过程中,bpftrace 每次遇到 “cgroup_path” 都会创建一个 CgroupPath 实例。

 struct CgroupPath {
  uint64_t cgroup_path_id;
  uint64_t cgroup_id;

  std::vector<llvm::Type*> asLLVMType(ast::IRBuilderBPF& b);
} __attribute__((packed));

cgroup_path_idcgroup_id 是上文提及的两个 u64 变量。

cgroup_path_id 其实是一个自增的变量,因为在后面 resource analyse 阶段, bpftrace 会把 string filter (默认的 filter 是"*")保存到 cgroup_path_args 这个向量里面, 这样我们可以用 cgroup_path_id 作为索引找到对应的 filter。

在使用 cgroup_path 作为 map key 的情况下,bpf map 里面保存的是 <cgroup_id, cgroup_path_id> 但是 cgroup_path_id 每次都会变动,导致 update 跟 lookup 的 key 不一样。

我尝试绕开这个问题,发现完全绕不开:

  1. 去掉 cgroup_path_id: 我们完全可能出现同一个 cgroup_id 使用不同 filter 的情况。
  2. 直接把 filter 存进来:抛开性能不说,要在 bpf prog 里面存一个字符串,还是只能存一个地址, 最后还是每个 key 都会变。
  3. 在 map 里面只使用 cgroup_id 作为key, 到 output 的时候才去把 cgroup_path_id 联回来。 老实说,这是最有可能的一种方案,但是 output 的时候,bpftrace 只能读到 key 的数据, 如果 key 用 cgroup_id 的值,那根本拿不到整个 CgroupPath 的信息,如果存 cgroup_id 的地址——这回到情况2。
  4. 在 IR 阶段,把 cgroup_id 和 filter 相同的 cgroup_path 对应成同一个 CgroupPath, 你还别说,这个还真的可能可以实现!但我是在写这篇博客的时候想到的,等老衲回去试一试。

总结

最后考虑到开发成本和收益,我关掉了这个 PR,但是写完这篇博客之后就有点不同了,没准可以再试一发。