linux capability
传统的unix权限模型将进程分为root用户进程(有效用户id为0)和普通用户进程。普通用户需要root权限的某些功能,通常通过setuid系统调用实现。但普通用户并不需要root的所有权限,可能仅仅需要修改系统时间的权限而已。这种粗放的权限管理方式势必会带来一定的安全隐患。
linux内核中引入了capability,用于消除需要执行某些操作的程序对root权限的依赖。
capability用于分割root用户的权限,将root的权限分割为不同的能力,每一种能力代表一定的特权操作。例如,CAP_SYS_MODULE用于表示用户加载内核模块的特权操作。根据进程具有的能力来进行特权操作的访问控制。
只有进程和可执行文件才有能力,每个进程拥有以下几组能力集(set)。
- cap_effective: 进程当前可用的能力集
- cap_inheritable: 进程可以传递给子进程的能力集
- cap_permitted: 进程可拥有的最大能力集
- cap_ambient: Linux 4.3后引入的能力集,
- cap_bounding: 用于进一步限制能力的获取
可以通过/proc/${pid}/status文件中的CapInh CapPrm CapEff CapBnd CapAmb来表示,每个字段为8个字节即64bit,每个比特表示一种能力,这几个字段存放在进程的内核数据结构task_struct中,由此可见capability的最小单位为线程,而不是进程。
example 1 设置进程能力
在执行下面程序之前需要安装yum install libcap-devel
1 |
|
并执行如下操作:
1 | gcc capability.c -lcap -o capability |
example 2 获取进程能力
1 |
|
可以通过capget命令获取进程的能力
1 | [vagrant@localhost tmp]$ gcc get_capability.c -lcap -o get_capability |
工具
- getcap用于获取程序文件所具有的能力。
- getpcaps用于获取进程所具有的能力。
- setcap用于设置程序文件所具有的能力。
- capsh 查看和设置程序的能力
1 | 将chown命令授权给普通用户也具备更改文件owner的能力 |
runc项目中的应用
runc的容器配置文件spec.Process.Capabilities
可以定义各个能力集的能力,用来限制容器的能力。
docker中的应用
docker默认情况下给容器去掉了一些比较危险的capabilities,比如cap_sys_admin
。
例如在docker中使用gdb命令默认是不允许的,这是因为docker已经将SYS_PTRACE相关的能力给去掉了。
在docker中使用--cap-add
和--cap-drop
命令来增加和删除capabilities,
可以使用--privileged
赋予容器所有的capabilities,该操作谨慎使用。