为啥 bpf 代码无法访问 cpumap_enqueue_ctx 的前 8 个字节?

Posted

技术标签:

【中文标题】为啥 bpf 代码无法访问 cpumap_enqueue_ctx 的前 8 个字节?【英文标题】:Why are the first 8 bytes of cpumap_enqueue_ctx not accessible by bpf code?为什么 bpf 代码无法访问 cpumap_enqueue_ctx 的前 8 个字节? 【发布时间】:2020-01-01 16:33:18 【问题描述】:

阅读一些附加到跟踪点的 ebpf 示例,我注意到每个结构都是从这样的填充开始构建的(来自samples/bpf/xdp_redirect_cpu_kern.c

/* Tracepoint: /sys/kernel/debug/tracing/events/xdp/xdp_cpumap_enqueue/format
 * Code in:         kernel/include/trace/events/xdp.h
 */
struct cpumap_enqueue_ctx 
        u64 __pad;              // First 8 bytes are not accessible by bpf code
        int map_id;             //      offset:8;  size:4; signed:1;
        u32 act;                //      offset:12; size:4; signed:0;
        int cpu;                //      offset:16; size:4; signed:1;
        unsigned int drops;     //      offset:20; size:4; signed:0;
        unsigned int processed; //      offset:24; size:4; signed:0;
        int to_cpu;             //      offset:28; size:4; signed:1;
;

我发现的只是这条评论说前 8 个字节不能被 bpf 代码访问,但我不明白为什么。

【问题讨论】:

【参考方案1】:

来自this mailing list:

bpf 代码无法访问跟踪点上下文结构的前 8 个字节。这是一个可以追溯到最初包含此代码的选择。

查看解释:commit 98b5c2c65c29(“perf, bpf: allow bpf programs attach to tracepoints”)

来自commit 98b5c2c65c29:

introduce BPF_PROG_TYPE_TRACEPOINT program type and allow it to be attached
to the perf tracepoint handler, which will copy the arguments into
the per-cpu buffer and pass it to the bpf program as its first argument.
The layout of the fields can be discovered by doing
'cat /sys/kernel/debug/tracing/events/sched/sched_switch/format'
prior to the compilation of the program with exception that first 8 bytes
are reserved and not accessible to the program. This area is used to store
the pointer to 'struct pt_regs' which some of the bpf helpers will use:
+---------+
| 8 bytes | hidden 'struct pt_regs *' (inaccessible to bpf program)
+---------+
| N bytes | static tracepoint fields defined in tracepoint/format (bpf readonly)
+---------+
| dynamic | __dynamic_array bytes of tracepoint (inaccessible to bpf yet)
+---------+

Not that all of the fields are already dumped to user space via perf ring buffer
and broken application access it directly without consulting tracepoint/format.
Same rule applies here: static tracepoint fields should only be accessed
in a format defined in tracepoint/format. The order of fields and
field sizes are not an ABI.

因此前 8 个字节不可访问,因为它们用于存储指向 BPF 助手使用的关键结构的指针,因此需要保持隐藏以防止损坏或信息泄漏。

【讨论】:

以上是关于为啥 bpf 代码无法访问 cpumap_enqueue_ctx 的前 8 个字节?的主要内容,如果未能解决你的问题,请参考以下文章

perf:无法合成 bpf 事件

无法从BPF跳转至EXCEL

为啥 GCC 不对无法访问的代码发出警告?

为啥连续抛出 2 个异常不会产生无法访问的代码警告?

代码中显然有一个无法访问的语句,但可以编译 - 为啥? [复制]

当 if 条件为常量时,为啥未检测到无法访问的代码?