LWN: 允许非root用户访问bpf

Providing wider access to bpf()

By Jonathan Corbet

June 27, 2019

bpf()系统调用,可以供user space调用来加载BPF program到kernel进行执行,修改BPF map,以及其他一些BPF相关的功能。BPF program都是验证过的并且隔离在沙盒环境,不过客观来说这些program仍是运行在特权上下文,并且根据所加载的不同类型的program,能导致各种类型的担忧。因此,绝大多数BPF操作(包括加载各种类型的BPF program)都严格限制只有CAP_SYS_ADMIN权限的进程可以调用,通常也就意味着需要root权限。BPF program在很多场景下面都会有帮助,因此人们其实一直希望能有更多自由来使用bpf()。其中一个方向就是Song Liu提出的,在kernel里增加一个与众不同的安全策略。

这个方案描述起来很简单,就是创建了一个新的设备节点 /dev/bpf,核心想法是只要进程有权限打开/dev/bpf文件,就能使用sys_bpf()提供的 绝大多数功能,不过作者所说的“绝大多数”一直没有详细解释。如果不是root用户,假如需要进行一些BPF操作,例如创建一个map、或者加载program,都需要首先打开这个/dev/bpf文件。然后通过ioctl()调用(BPF_DEV_IOCTL_GET_PERM)来对进程授权允许进行bpf()调用。今后可以通过调用BPF_DEV_IOCTL_PUT_PERM ioctl()来关闭这个授权。

在kernel内部对此功能的实现方式是在task_struct结构里面增加了一个新的bpf_flags。这个bit被置1就意味着允许使用BPF。不过这个patch的这部分实现还是可能会改变的,因为正如Daniel Borkmann指出,为了一个bit的信息来增加一个unsigned long成员变量,不是一个合理的方案。后面应该会改到其他地方来记录这个bit信息。

下一步就是增加一点逻辑来确定当前的进程是否能够进行BPF操作:

static inline bool bpf_capable(int cap)
    {
	return test_bit(TASK_BPF_FLAG_PERMITTED, &current->bpf_flags) ||
	    capable(cap);
    }

当前的kernel是通过检查CAP_SYS_ADMIN或者CAP_NET_ADMIN来判断是否有权限调用BPF功能的,在此patch合入之后就可以改为使用bpf_capable()来判断了。patch里面一开始说的用来管控“绝大多数”BPF功能,不过代码里面看来是把kernel/bpf下面的所有capable()调用都给替换成bpf_capable()了。

这样改动之后,系统管理员就能够创建一个新的名叫bpf的组,配置这个bpf group作为/dev/bpf文件的属主。后续/dev/bpf的访问权限会被配置成允许组成员进行读操作(使用ioctl()并不需要写操作权限),这样只要进程属于bpf group,就能够使用bpf()系统调用了。

需要注意的是,BPF能做到的事情可不仅仅局限在BPF虚拟机而已。例如,在tracepoint里面挂载一个BPF program,也需要tracing部分代码的配合;利用BPF来监控网络,也需要网络子系统的配合。这些子系统里面也会有一些权限检查,例如tracepoint的访问会需要有perf_event_open()权限,在某些系统上可能会控制得很严格。这组patch set没有修改这些权限检查代码,只有一个例外:在允许BPF访问的时候,会把BPF socket-filter program相关的限制去掉。

总之,这个patch在做的事情就是增加一个新的capability bit,并独立于Linux通常的capability check机制之外,允许任何能读/dev/bpf的进程打开或者关闭这个权限。这个新的capability主要用于BPF子系统,还有networking代码里的一处地方也有用到,很有可能今后会需要扩展到kernel的其他子系统里的相关部分。目前的实现还是跟kernel security model安全模型有点不太一致。

没有增加一个新的capability bit(例如CAP_SYS_BPF),是有客观原因的。目前的capability处理程序不知道这个新bit的含义,因此可能无法正确处理。不过,目前还不清楚这种采用另一种方法来实现capability bit的做法是不是真的有好处。

总有一天人们会需要能对BPF的功能有一些更细粒度的访问控制。好消息Linux security module (LSM)里面已经有了一些hook,适合实现这方面的底层支持。既然现在LSM有了越来越多的应用,加强了系统管理员在kernel的security policy方面的管控,那么为什么不利用基于LSM的方式来实现这个管控呢?对这方面做一些探索,可能可以更好的帮助这个patch set更加通用,不局限于BPF部分,从而得到更好的review。

全文完

LWN文章遵循CC BY-SA 4.0许可协议。

极度欢迎将文章分享到朋友圈 

长按下面二维码关注:Linux News搬运工,希望每周的深度文章以及开源社区的各种新近言论,能够让大家满意~

我来评几句
登录后评论

已发表评论数()

相关站点

热门文章