instructions - ebpf:验证 LD_ABS 和 LD_IND 指令
问题描述
我正在阅读验证程序代码,特别是验证安全性LD_ABS
和LD_IND
指令的部分(check_ld_abs())。正如评论所说,这些指令隐含地期望在r6
寄存器中输入,即这是我们必须加载指针的地方__sk_buff
。所以我验证了以下类型的程序BPF_PROG_TYPE_SOCKET_FILTER
将被验证者拒绝:
struct bpf_insn prog[] = {
BPF_LD_ABS(BPF_B, offsetof(struct iphdr, protocol)),
/* exit with value 0 */
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
};
...
>> 0: (30) r0 = *(u8 *)skb[9]
R6 !read_ok
即它需要在r6
之前准备LD_ABS
:
BPF_MOV64_REG(BPF_REG_6, BPF_REG_1)
但是,评论还提到了显式输入(在这种情况下,输入可以是任何寄存器)?仅由 使用LD_IND
吗?与隐式模式有什么区别?
谢谢。
解决方案
这不是隐式或显式模式。这些指令只需要几个参数,其中一些是隐式的,其中一些是显式的。
上下文是隐式的,因为正如您所解释的,它必须在 中引用
r6
,这意味着它没有被用户显式传递给指令:您看不到r6
inBPF_LD_ABS(BPF_B, offsetof(struct iphdr, protocol))
。指令将期望来自该寄存器的上下文是一个隐式约定。相比之下,指令也使用的源寄存器和立即值是字节码中指令本身的一部分,使它们成为显式参数。
内核文档在某种程度上证实了这一点:
eBPF 有两个非通用指令:(BPF_ABS | | BPF_LD) 和 (BPF_IND | | BPF_LD) 用于访问数据包数据。
它们必须从经典继承,才能在 eBPF 解释器中运行的套接字过滤器具有强大的性能。这些指令只能在解释器上下文是指向
struct sk_buff
并具有七个隐式操作数的指针时使用。寄存器 R6 是一个隐式输入,必须包含指向 sk_buff 的指针。寄存器 R0 是一个隐含的输出,其中包含从数据包中获取的数据。寄存器 R1-R5 是暂存寄存器,不得用于跨 BPF_ABS | 存储数据。BPF_LD 或 BPF_IND | BPF_LD 指令。
提醒一句:
LD_ABS
从绝对地址加载数据,从上下文的开头(存储在 中)开始并添加字段中r6
包含的偏移量。imm
数据存储到r0
(隐式输出)。它不使用src
寄存器。LD_IND
执行间接加载,它首先使用src
寄存器中的(变量)值偏移上下文,然后将(固定)imm
值添加为第二个偏移量以到达要加载到的字节r0
。
推荐阅读
- jekyll - 带有变量的 Jekyll/Liquid 表单模板
- python - 如何从数据库中自动读取先前生成的列名列表并单独保存?
- swift - 'ViewController' 与协议 'UITableViewDelegate' 的冗余一致性和另一个错误
- ios - 负 CGSize 值的目的
- shell - 无法在 JupyterLab 中导出 PATH
- html - XHTML2FO.xsl 在转换为 PDF 时为嵌套的 html 表格标签提供错误
- java - 如何返回包含 xs 和 ys 的所有点的列表。在java中使用流时?
- vb.net - 我怎样才能让计时器越来越慢,直到它停止?
- pytorch - PyTorch Geometric 如何输入一个样本而不是小批量?
- inheritance - 部分定义函数的名称“如果存在”,可以继承的“像抽象”是什么?