BPF_PROG_TYPE_CGROUP_SYSCTL¶
本文档描述了 BPF_PROG_TYPE_CGROUP_SYSCTL
程序类型,该类型为 sysctl 提供 cgroup-bpf 钩子。
该钩子必须附加到 cgroup,并且每当该 cgroup 中的进程尝试从 proc 中的 sysctl 旋钮读取或写入时都会被调用。
1. 附加类型¶
必须使用 BPF_CGROUP_SYSCTL
附加类型将 BPF_PROG_TYPE_CGROUP_SYSCTL
程序附加到 cgroup。
2. 上下文¶
BPF_PROG_TYPE_CGROUP_SYSCTL
提供从 BPF 程序访问以下上下文的功能:
struct bpf_sysctl {
__u32 write;
__u32 file_pos;
};
write
指示 sysctl 值是正在读取 (0
) 还是正在写入 (1
)。此字段是只读的。file_pos
指示访问 sysctl 时的文件位置(读取或写入)。此字段是读写的。写入此字段会设置 sysctl proc 文件中read(2)
将从中读取或write(2)
将写入的起始位置。例如,即使用户空间在file_pos > 0
时调用write(2)
,将零写入此字段也可用于通过bpf_sysctl_set_new_value()
覆盖整个 sysctl 值。将非零值写入此字段可用于从指定的file_pos
开始访问 sysctl 值的一部分。并非所有 sysctl 都支持在file_pos != 0
时进行访问,例如,对数字 sysctl 条目的写入必须始终在文件位置0
。另请参阅kernel.sysctl_writes_strict
sysctl。
有关如何访问上下文字段的更多详细信息,请参阅 linux/bpf.h。
3. 返回码¶
BPF_PROG_TYPE_CGROUP_SYSCTL
程序必须返回以下返回码之一:
0
表示“拒绝访问 sysctl”;1
表示“继续访问”。
如果程序返回 0
,用户空间将从 read(2)
或 write(2)
获得 -1
,并且 errno
将设置为 EPERM
。
4. 辅助函数¶
由于 sysctl 旋钮由名称和值表示,sysctl 特定的 BPF 辅助函数专注于提供对这些属性的访问:
bpf_sysctl_get_name()
:将/proc/sys
中可见的 sysctl 名称获取到 BPF 程序提供的缓冲区中;bpf_sysctl_get_current_value()
:将 sysctl 当前持有的字符串值获取到 BPF 程序提供的缓冲区中。此辅助函数在从 sysctlread(2)
和向 sysctlwrite(2)
时都可用;bpf_sysctl_get_new_value()
:在实际写入发生之前,获取当前正在写入 sysctl 的新字符串值。此辅助函数只能在ctx->write == 1
时使用;bpf_sysctl_set_new_value()
:在实际写入发生之前,覆盖当前正在写入 sysctl 的新字符串值。sysctl 值将从当前的ctx->file_pos
开始被覆盖。如果整个值需要被覆盖,BPF 程序可以在调用此辅助函数之前将file_pos
设置为零。此辅助函数只能在ctx->write == 1
时使用。通过此辅助函数设置的新字符串值,内核会像处理用户空间传入的等效字符串一样进行处理和验证。
BPF 程序以与用户空间在 proc 文件系统中相同的方式(即作为字符串)看待 sysctl 值。由于许多 sysctl 值表示一个整数或一个整数向量,因此可以使用以下辅助函数从字符串中获取数值:
bpf_strtol()
:将字符串的初始部分转换为长整数,类似于用户空间的 strtol(3);bpf_strtoul()
:将字符串的初始部分转换为无符号长整数,类似于用户空间的 strtoul(3);
有关此处描述的辅助函数的更多详细信息,请参阅 linux/bpf.h。
5. 示例¶
有关用 C 语言编写的 BPF 程序示例,该程序访问 sysctl 名称和值,解析字符串值以获取整数向量,并使用结果决定是否允许或拒绝访问 sysctl,请参阅 test_sysctl_prog.c。
6. 注意事项¶
BPF_PROG_TYPE_CGROUP_SYSCTL
旨在用于受信任的根环境,例如监控 sysctl 使用情况或捕获在单独 cgroup 中以 root 身份运行的应用程序尝试设置的不合理值。
由于 task_dfl_cgroup(current) 在 sys_read / sys_write 时被调用,它可能返回与 sys_open 时不同的结果,即在 proc 文件系统中打开 sysctl 文件的进程可能与尝试从中读取/写入的进程不同,并且这两个进程可能在不同的 cgroup 中运行,这意味着 BPF_PROG_TYPE_CGROUP_SYSCTL
不应作为限制 sysctl 使用的安全机制。
与任何 cgroup-bpf 程序一样,如果运行在 cgroup 中的应用程序以 root 身份运行,并且不应允许其分离/替换管理员附加的 BPF 程序,则应格外小心。