Sockets ebpf:验证器在哪里打印消息?

Sockets ebpf:验证器在哪里打印消息?,sockets,bpf,ebpf,Sockets,Bpf,Ebpf,验证器在哪里打印其消息?我在struct bpf\u insn中嵌入了一个简单的代码,我将其加载并附加为bpf\u PROG\u TYPE\u SOCKET\u FILTER类型: struct bpf_insn prog[] = { BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), BPF_EXIT_INSN(), }; 此代码故意出错(R0在退出前未初始化)bpf_prog_load()返回EACCESS错误并未能加载,这是预期的,但我想查看验证器消息(

验证器在哪里打印其消息?我在
struct bpf\u insn
中嵌入了一个简单的代码,我将其加载并附加为
bpf\u PROG\u TYPE\u SOCKET\u FILTER
类型:

struct bpf_insn prog[] = {
   BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
   BPF_EXIT_INSN(),
};

此代码故意出错(
R0
在退出前未初始化)
bpf_prog_load()
返回
EACCESS
错误并未能加载,这是预期的,但我想查看验证器消息(dmesg或控制台中无任何内容)。

尝试加载eBPF程序时,由加载程序将缓冲区传递给内核验证器,然后打印它,以获得验证器的输出

验证器将使用用户空间程序提供的缓冲区,并在其中打印所有日志。除极少数特定消息外,它不会将任何内容打印到内核日志或控制台(由shell处理,而不是直接由内核处理)

让我们看一看您在评论中提到的来自的一个片段

prog_fd=bpf_load_程序(bpf_prog_TYPE_SOCKET_FILTER,prog,insns_cnt,
“GPL”,0,bpf_log_buf,bpf_log_buf_SIZE);
如果(程序fd<0){
printf(“未能加载程序“%s”\n”,strerror(errno));
去清理;
}
这是我们尝试加载程序的部分。我们从libbpf调用
bpf\u load\u program()
,然后按此顺序传递程序类型、指令、指令数、许可证字符串、与内核版本相关的一些标志,最后传递一个空缓冲区及其大小。大小
BPF\u LOG\u BUF\u size
不为空(在
tools/lib/BPF/BPF
中定义为
(UINT32\u MAX>>8)

函数
bpf\u load\u program()
将把所有这些信息(包括指向缓冲区的指针)传递给
bpf()
系统调用,系统调用将尝试加载程序。验证器将用日志填充缓冲区(无论加载是否成功,但请参见底部的注释)。然后,还是由加载程序来使用这些日志。函数
bpf\u load\u program()
是低级的,它对缓冲区中验证器的日志不做任何处理,即使在加载失败时也是如此。它让调用者处理或转储日志。您尝试运行的示例应用程序也不执行任何操作;因此,缓冲区未使用,您无法在控制台中查看日志

要查看日志,在您的情况下,您可能只需要转储此缓冲区。以下简单的方法应该可以奏效:

。。。
如果(程序fd<0){
printf(“未能加载程序“%s”\n”,strerror(errno));
printf(“%s”,bpf\u log\u buf);
去清理;
}

注意:除了缓冲区和缓冲区大小之外,加载程序还必须向验证器传递一个
0
,则验证器不向缓冲区打印任何内容。在当前情况下,我们不直接处理
log\u级别
bpf\u load\u program()
也不这样做,并将值设置为
0
,但它最终在libbpf中调用
libbpf\u bpf\u prog\u load()
。该函数尝试第一次加载程序而不更改
日志级别
,但如果失败,它会在
日志级别
设置为
1
的情况下进行新的尝试-有关详细信息,请参阅注释中的Mark指针。
log\u level
的不同值在中定义,不属于用户API的一部分,这意味着验证器在日志详细性方面的行为可能因内核版本而异。

它将它们打印到验证器的日志缓冲区。由加载程序提供缓冲区供验证器填充,然后将其转储到控制台。如何加载程序?@Qeole,是的,你是对的,
manbpf
对此非常清楚。然而,这似乎不足以使它发挥作用。我还以内核的
samples/bpf/sock\u为例。c
将bpf程序代码压缩到最小,就像我的一样,重建并启动了程序——它确实返回
EACCESS
,但不打印任何验证器消息。
samples/bpf/sock\u example.c
将缓冲区传递给验证器:
bpf\u load\u程序(…,bpf_log_buf,bpf_log_buf_SIZE)
。但加载失败时,它似乎不会打印该缓冲区的内容,只有
strerror(errno)
,因此您不会得到verfier的输出。您可能只需要添加类似
printf(“%s”,bpf_log_buf)的内容
prog\u fd<0
时。准确地说,谢谢!另外,值得一提的是,这将适用于log\u level>0。啊,对。您必须进行其他更改吗?您是否切换到
bpf\u load\u program\u xattr()
可能?看起来像
bpf\u load\u program()
只将
log\u级别设置为0?我没有做任何更改。但是,我查看了
bpf\u load\u程序()
代码,它在其中调用
bpf\u load\u program\u xattr()
正确地说,如果sys\u bpf失败,它会显式地将log\u level设置为1,然后再次调用sys\u bpf。听起来不错,我忘记了这一点。代码阅读方面做得很好:)。我将更新答案以提及
日志级别