为何无CAP_SETPCAP权限无法从能力边界集中移除能力?
问题背景
我有一个以非root用户运行的Linux服务,它拥有若干能力集。启动时我希望派生一个子进程,该子进程需要移除其中一项能力(例如CAP_DAC_OVERRIDE)。这样做的目的是,若子进程存在安全漏洞,攻击者将无法滥用该能力,从而降低风险。父进程作为代理进程,会保留CAP_DAC_OVERRIDE能力,当收到子进程的IPC消息时,将代表无特权的子进程执行相关操作。
我可以将该能力从子进程的所有能力集(可继承、允许、有效、环境)中移除,但无法从边界集中移除。调用prctl(PR_CAPBSET_DROP)会报错prctl(PR_CAPBSET_DROP): Operation not permitted,显然需要CAP_SETPCAP权限才行。我知道可以让进程初始时携带CAP_SETPCAP权限,修改边界集后再移除它。我的问题是:为何Linux要求必须持有CAP_SETPCAP权限才能从自身边界集中移除能力?Linux内核阻止进程降低自身权限的做法似乎有些奇怪。
核心原因
Linux对修改边界集(Capability Bounding Set)要求CAP_SETPCAP权限,本质是由边界集的设计定位和权限模型的一致性决定的:
边界集是全局能力上限而非进程自身权限:边界集的作用是限制进程及其所有子进程后续能获取的能力范围,是系统层面预设的“能力天花板”。它通常由更可信的实体(如init进程、容器管理工具)配置,确保进程不会突破预设的权限边界。如果允许任意进程自行缩小边界集,可能破坏上层系统的权限规划——比如某个进程意外修改后,其后续派生的子进程无法获得系统原本允许的必要能力,引发服务故障。
CAP_SETPCAP的职责就是管理能力配置权限:CAP_SETPCAP的核心作用就是赋予进程修改能力集配置的权限,包括边界集的调整。不管是提升还是降低边界集,都属于对能力范围的配置操作,内核统一要求CAP_SETPCAP,是为了确保只有受信任的进程能修改这个全局限制,避免权限配置混乱。
移除常规能力集已足够实现安全需求:你已经可以通过移除子进程的允许(Permitted)、有效(Effective)等能力集来限制其权限,这些操作不需要CAP_SETPCAP。只要子进程的Permitted和Effective集里没有CAP_DAC_OVERRIDE,它就根本无法使用该能力,边界集里保留该能力不会带来实际风险——因为子进程没有激活它的权限。
内容的提问来源于stack exchange,提问作者C0deH4cker

