从 Kernel 2.2
开始,Linux 将传统上与超级用户 root
关联的特权划分为不同的单元,称为 Capabilites
。Capabilites
作为线程(Linux 并不真正区分进程和线程)的属性存在,每个单元可以独立启用和禁用。
原理
Linux 在执行特权相关操作时,权限检查时分两类进程:
- 特权进程(UID 为 0,即 root 用户) 绕过所有内核权限检查
- 非特权进程(UID 不为 0) 根据进程凭证(通常为UID、GID 和补充组列表)进行权限检查,检查是否具有该特权操作所对应的 Capabilites 判断权限
Capabilites 类别
Capability 名称 |
说明 |
CAP_AUDIT_CONTROL |
启用和禁用内核审计;改变审计过滤规则;检索审计状态和过滤规则 |
CAP_AUDIT_READ |
允许通过 multicast netlink 套接字读取审计日志 |
CAP_AUDIT_WRITE |
将记录写入内核审计日志 |
CAP_BLOCK_SUSPEND |
使用可以阻止系统挂起的特性 |
CAP_CHOWN |
修改文件所有者的权限 |
CAP_DAC_OVERRIDE |
忽略文件的 DAC 访问限制 |
CAP_DAC_READ_SEARCH |
忽略文件读及目录搜索的 DAC 访问限制 |
CAP_FOWNER |
忽略文件属主 ID 必须和进程用户 ID 相匹配的限制 |
CAP_FSETID |
允许设置文件的 setuid 位 |
CAP_IPC_LOCK |
允许锁定共享内存片段 |
CAP_IPC_OWNER |
忽略 IPC 所有权检查 |
CAP_KILL |
允许对不属于自己的进程发送信号 |
CAP_LEASE |
允许修改文件锁的 FL_LEASE 标志 |
CAP_LINUX_IMMUTABLE |
允许修改文件的 IMMUTABLE 和 APPEND 属性标志 |
CAP_MAC_ADMIN |
允许 MAC 配置或状态更改 |
CAP_MAC_OVERRIDE |
覆盖 MAC(Mandatory Access Control) |
CAP_MKNOD |
允许使用 mknod() 系统调用 |
CAP_NET_ADMIN |
允许执行网络管理任务 |
CAP_NET_BIND_SERVICE |
允许绑定到小于 1024 的端口 |
CAP_NET_BROADCAST |
允许网络广播和多播访问 |
CAP_NET_RAW |
允许使用原始套接字 |
CAP_SETGID |
允许改变进程的 GID |
CAP_SETFCAP |
允许为文件设置任意的 capabilities |
CAP_SETPCAP |
参考 capabilities man page |
CAP_SETUID |
允许改变进程的 UID |
CAP_SYS_ADMIN |
允许执行系统管理任务,如加载或卸载文件系统、设置磁盘配额等 |
CAP_SYS_BOOT |
允许重新启动系统 |
CAP_SYS_CHROOT |
允许使用 chroot() 系统调用 |
CAP_SYS_MODULE |
允许插入和删除内核模块 |
CAP_SYS_NICE |
允许提升优先级及设置其他进程的优先级 |
CAP_SYS_PACCT |
允许执行进程的 BSD 式审计 |
CAP_SYS_PTRACE |
允许跟踪任何进程 |
CAP_SYS_RAWIO |
允许直接访问 /devport、/dev/mem、/dev/kmem 及原始块设备 |
CAP_SYS_RESOURCE |
忽略资源限制 |
CAP_SYS_TIME |
允许改变系统时钟 |
CAP_SYS_TTY_CONFIG |
允许配置 TTY 设备 |
CAP_SYSLOG |
允许使用 syslog() 系统调用 |
CAP_WAKE_ALARM |
允许触发一些能唤醒系统的东西(比如 CLOCK_BOOTTIME_ALARM 计时器) |
Capabilities 使用
setcap/getcap 命令
apt install libcap2-bin -y
相关命令:
示例
setcap 'CAP_NET_RAW+eip CAP_NET_ADMIN+eip' /usr/sbin/dumpcap
setcap cap_net_bind_service=+eip /path/to/nginx
# 删除权限
setcap -r nginx
root@ubuntu:~# getcap /usr/bin/ping
/usr/bin/ping = cap_net_raw+ep
root@ubuntu:~# su - xiexianbin
xiexianbin@ubuntu:~$ getcap /usr/bin/ping
/usr/bin/ping = cap_net_raw+ep
xiexianbin@ubuntu:~$
# 普通用户使用 ping
$ setcap 'cap_net_admin,cap_net_raw+ep' /usr/bin/ping
$ getcap /usr/bin/ping
/usr/bin/ping = cap_net_admin,cap_net_raw+ep
root@ubuntu:~# ping -c1 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.954 ms
...
root@ubuntu:~# setcap cap_net_raw-p /usr/bin/ping
root@ubuntu:~# getcap /usr/bin/ping
/usr/bin/ping =
setcap cap_net_raw+p /usr/bin/ping
setcap cap_net_raw+ep /usr/bin/ping
命令说明:
ep
指 Effective 和 Permitted 集合
+
将指定的 Capabilities 添加到集合中
-
将指定的 Capabilities 从集合中移除
程序与进程的 Capabilities
- 程序文件的 Capabilities
- Permitted
- Inheritable
- Effective
- 进程中有五种 Capabilities 集合类型,分别是:
- Permitted
- Inheritable
- Effective
- Bounding
- Ambient
使用命令获取进程的 cat /proc/[pid]/status | grep Cap
xiexianbin@ubuntu:~$ cat /proc/850/status | grep Cap
CapInh: 0000000000000000
CapPrm: 000001ffffffffff
CapEff: 000001ffffffffff
CapBnd: 000001ffffffffff
CapAmb: 0000000000000000
使用 capsh
解码:
xiexianbin@ubuntu:~$ capsh --decode=000001ffffffffff
WARNING: libcap needs an update (cap=40 should have a name).
0x000001ffffffffff=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read,38,39,40
容器中的使用
Docker
$ docker run --help
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
Options:
...
--cap-add list Add Linux capabilities
--cap-drop list Drop Linux capabilities
...
--privileged Give extended privileges to this container
...
runtime-privilege-and-linux-capabilities 中列出的 Capabilities
分两类:
$ docker run -it --rm --cap-add=NET_ADMIN busybox /bin/sh
/ # ip link add dummy0 type dummy
/ #
Kubernetes
Kubernetes 配置 Capabilities
通过 spec.containers.sercurityContext.capabilities
配置 add
和 drop
配置:
apiVersion: v1
kind: Pod
metadata:
name: p-1
spec:
containers:
- name: p-1
image: busybox
args:
- sleep
- "3600"
securityContext:
capabilities:
add:
- NET_ADMIN
drop:
- KILL