LWN:CAP_PERFMON,有一个新增的capability!

关注了就能看到更多这么棒的文章哦~

CAP_PERFMON — and new capabilities in general

By Jonathan Corbet
February 21, 2020


原文来自:https://lwn.net/Articles/812719/

perf_event_open()这个系统调用非常复杂,需要使用者仔细研究一下才能掌握。这个系统调用还有一些安全特性需要掌握:它可以拿到当前正在运行的系统中的许多信息,并且因为它的内部实现非常复杂,所以经常会出现一些让人烦恼的bug。目前的kernel中,对perf_event_open()的安全管控其实非常简单:如果有CAP_SYS_ADMIN权限,就可以使用perf_event_open()(尽管系统管理员可以把它配置成不需要任何权限就能用)。目前有人试着在增加一个新的capability来专用于perf events subsystem,看起来很有道理的样子,反而引起人们的一个疑问“为何不经常加一些新的capability”。

capabiilty,一直一来人们希望用它来把传统Unix里面的超级用户的权限拆得更加细粒度一些,这样可以让系统管理员给相应的人一些特定的权限,而不用让他变成超级用户。目前Linux kernel里面定义了37种capability,可以用来对许多任务配置许可权限,包括配置terminal device,设置系统的resource limit,安装kernel module,调整系统时间等。在这么多种capability中,CAP_SYS_ADMIN是用来进行系统管理工作的。CAP_SYS_ADMIN也就变成了在其他各种capability都不合适的时候会缺省申请的capabiilty。它涵盖的权限非常多,所以人们称之为“the new root”。

快速搜一下就知道,在5.6-rc kernel里面有大概500多处地方都是在检查CAP_SYS_ADMIN。在5.6的合并窗口期,还新增了一些依据CAP_SYS_ADMIN来放行的地方,包括发送一些硬件特有的命令给这种设备、配置time namespace、加载BPF program来替换kernel operation structure、开放对x86 MTRR寄存器的访问。perf event subsystem也一直依赖CAP_SYS_ADMIN来避免被普通用户调用。所以,要想让某个用户来调用perf_event_open(),就需要系统管理员给他开放CAP_SYS_ADMIN,从而也就对他开放了诸如mount filesystem,访问PCI configuration space,调整memory-management policy,加载BPF program等等权限。通常来说不应该不应该给仅仅要做perf tuning的application授予这么多权限。

Alexey Bundankov的patch set就是为了解决这个问题,他创建了一个新的名为CAP_PERFMON的capability,用来管控这些performance-monitoring task。如果使用了这个patch,用户(或者他调用的程序)就可以只被赋予CAP_PERFMON,而不需要CAP_SYS_ADMIN。这样就可以既能获得performance数据,也不会让别人担心它滥用其他权限。当然,CAP_SYS_ADMIN也能够调用perf_event_open(),否则的话很可能会导致现在能正常工作的软件出错了。不过,只要用户已经有了CAP_PERFMON了,那么就不需要再授予它CAP_SYS_ADMIN了。

乍一看,这个改动看起来很显而易见。像这种从一个非常强大的capabiilty里面分出一个相对无害的功能的做法,大多数人都能接受。不过,这样一来我们就有一点想不通了,为什么之前很少有人这么做。上一次新增一个capability还是2014年的时候,当时增加了CAP_AUDIT_READ。而上一次从CAP_SYS_ADMIN中剥离出一个capability还是2010年的时候创建的CAP_SYSLOG。通常来说,某个功能加到了CAP_SYS_ADMIN里面的话,就没有再分出来了。为什么会有这种现象?

其中一个原因,就是之前提到的兼容性问题:如果CAP_SYS_ADMIN允许了某个动作,那么此后永远都要能允许它,否则有可能让现在能正常工作的软件变得不可用了。Serge Hallyn增加了CAP_SYSLOG的时候,他就用代码确保了拥有CAP_SYS_ADMIN的进程也有SYSLOG权限。不过,当时的kernel代码会报出一个warning信息,提示用户今后不可以再用CAP_SYS_ADMIN来控制此功能。在10年之后,这部分兼容代码以及warning信息仍然在kernel里面。如果CAP_SYS_ADMIN本身的权限没有减少,那么从中分出一些新的capability就没有多少好处了。

增加新的capability也有自身的一些风险,毕竟已有的代码完全不知道这个新的capability,以及它控制了什么东西。如果某个应用程序清掉了一个capabiilty mask中的多数bit,那么也会自认清除掉新增的这个bit,不过可能这个bit反而是应该打开的。经验告诉我们,如果在某个拥有特权的进程运行时仔细选择并去除掉一些capabiilty的话,有可能会出现一些出人意料的安全性问题。每个新增的capability都有类似的情况。所以新增capability的时候需要非常小心。这也是为什么SELinux编译的时候会专门检查是否有新增的capability但是没有在SELinux里面做过相应的改动,有的话就直接报错。

这样一来,许多人都认为Linux里面的capability是一个不成功的试验品。没人成功实现一个基于capability的实用系统,并且其中许多现存的capability都很容易被提升到root权限。kernel之上的Linux系统里面很少利用这些capability。如果最终实现的系统跟它原本定义的大不相同,那么很少有人有动力去继续做这件事情了,也很少有人会认真使用这个系统。

举个例子来说,为了减少用户的特权,很常见的一个需求就是从现有的工具软件中移除掉setuid bit,而仅仅给它增加响应的capability。kernel早在2008年的2.6.24就已经支持了file-baseed capability。作者本人的系统上正在运行的是Fedora 31,就总共包含了9个可执行程序是带有capability的:

    # getcap -r /
    /usr/bin/gnome-keyring-daemon = cap_ipc_lock+ep
    /usr/bin/clockdiff = cap_net_raw+p
    /usr/bin/arping = cap_net_raw+p
    /usr/bin/newuidmap = cap_setuid+ep
    /usr/bin/newgidmap = cap_setgid+ep
    /usr/bin/ping = cap_net_admin,cap_net_raw+p
    /usr/bin/gnome-shell = cap_sys_nice+ep
    /usr/sbin/mtr-packet = cap_net_raw+ep
    /usr/sbin/suexec = cap_setgid,cap_setuid+ep

我很高兴看到gnome-shell没有通过setuid root来执行,这样至少说明capability还是用起来了。不过对应的其实还存在31个setuid root的程序。看起来这个发行版距离完全利用capability来控制权限的目标还离得很远。

据说关于capability这一领域会有一些转变。人们总是永无休止地在加固我们的系统,预防攻击。这让开发者们开始再次审视起Linux capability功能了,希望能更好地利用它们。比如Android系统就已经用上了capability。systemd可以让管理员更细致地控制各种程序的capability。也许,Linux capability在多年被冷落之后,终于要找到更多系统开始部署了。

如果这种说法是真的,那么后续我们可能会看到更多人对改进capability的权限控制粒度的兴趣。包括从CAP_SYS_ADMIN中分出更多的权限,不过这些都需要非常非常小心地处理。CAP_SYS_ADMIN很可能今后可以摆脱它的"new root"的不光彩外号了,不过还是可以利用它来作为极少数program用来确保能正常工作的保底capabilty。

全文完

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

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注LWN深度文章以及开源社区的各种新近言论~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值