sockets - ebpf:验证者在哪里打印它的消息?
问题描述
验证者在哪里打印它的消息?我嵌入了一个简单的代码struct bpf_insn
,我在其中加载并附加为BPF_PROG_TYPE_SOCKET_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 处理,而不是直接由内核处理)。
samples/bpf/sock_example.c
让我们看一下您在评论中提到的片段。
prog_fd = bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog, insns_cnt,
"GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE);
if (prog_fd < 0) {
printf("failed to load prog '%s'\n", strerror(errno));
goto cleanup;
}
这是我们尝试加载程序的部分。我们bpf_load_program()
从 libbpf 调用,并按此顺序传递程序类型、指令、指令数量、许可证字符串、与内核版本相关的一些标志,最后是:一个空缓冲区及其大小。大小BPF_LOG_BUF_SIZE
是非空的(在tools/lib/bpf/bpf
as中定义(UINT32_MAX >> 8)
)。
该函数bpf_load_program()
会将所有这些信息(包括指向缓冲区的指针)传递给bpf()
系统调用,系统调用将尝试加载程序。验证者将使用日志填充缓冲区(无论加载是否成功,但请参阅底部的注释)。然后由加载程序再次使用这些日志。该函数bpf_load_program()
是低级的,它对缓冲区中的验证者日志不做任何事情,即使加载失败也是如此。它留给调用者处理或转储日志。您尝试运行的示例应用程序也不执行任何操作;因此,缓冲区未使用,您无法在控制台中看到日志。
要查看日志,在您的情况下,您可能只需要转储此缓冲区。像下面这样简单的东西应该可以工作:
...
if (prog_fd < 0) {
printf("failed to load prog '%s'\n", strerror(errno));
printf("%s", bpf_log_buf);
goto cleanup;
}
注意:除了缓冲区和缓冲区的大小之外,加载器必须将一个log_level
整数传递给验证器,以告诉它应该使用什么级别的详细信息。如果值为 at 0
,则验证程序不向缓冲区打印任何内容。在当前情况下,我们不log_level
直接处理。bpf_load_program()
也不会将值设置为0
,但最终会调用libbpf__bpf_prog_load()
libbpf。该函数尝试在不更改 的情况下首次加载程序log_level
,但如果失败,它会使用log_level
set重新尝试1
- 有关详细信息,请参阅注释中的 Mark 指针。不同的值log_level
在内部内核头文件中定义并且不是用户 API 的一部分,这意味着验证程序关于日志详细程度的行为可能因内核版本而异。
推荐阅读
- php - PHP 不会将所有 Excel 文件导入 MySqli 数据库
- python - django 2.2.5 从一个应用程序导入 url 到另一个应用程序
- c - 语义版本控制:小改动还是大改动?(第二部分)
- npm - npm install - 包是否需要同时位于 peerDependencies 和依赖项中?
- c# - 未能在不同的项目中调用控制器操作
- unreal-engine4 - 未处理的异常:System.FormatException:输入字符串的格式不正确在虚幻引擎 4.23 上启动到 iphone x 时
- python - 将第二个值添加到键(dict)python
- linkedin - r_1st_connections_size 权限问题
- vba - PDF - pdf 打开时打开书签面板
- excel - VBA:将刚刚创建的工作表移动到工作簿中所有选项卡最右侧的代码