Linux能力机制

Linux能力机制


早期linux上信任状模型非常简单,就是"超级用户对普通用户"模型。普通用户的很多操作需要root权限,这通过setuid实现。如果程序编写不好,就可能被攻击者利用,获得系统的控制权。使用能力机制(capability)减小这种风险。系统管理员为了系统的安全可以剥夺root用户的能力,这样即使root用户也将无法进行某些操作。而这个过程又是不可逆的,也就是说如果一种能力被删除,除非重新启动系统,否则即使root用户也无法重新添加被删除的能力。


能力的定义

能力机制(capability)相关结构列出如下(在include/linux/capability.h中):

Linux能力机制_第1张图片


每个进程的任务结构中有三个和能力有关的位图变量,列出如下(在include/linux/sched.h中):

Linux能力机制_第2张图片

每种能力由一位表示,1表示具有某种能力,0表示没有。因而这三个能力变量最大只能表示32个能力的有否。当进程进行操作时,检查任务结构中的cap_effective的对应位是否有效,例如,如果一个进程要设置系统的时钟,Linux的内核就会检查cap_effectiveCAP_SYS_TIME(25)是否有效。
能力定义的宏定义列出如下(在include/linux/capability.h中):

CAP_CHOWN

0

允许改变文件的所有权

CAP_DAC_OVERRIDE

1

忽略对文件的所有DAC访问限制

CAP_DAC_READ_SEARCH

2

忽略所有对读、搜索操作的限制

CAP_FOWNER

3

如果文件属于进程的UID,就取消对文件的限制

CAP_FSETID

4

允许设置setuid

CAP_KILL

5

允许对不属于自己的进程发送信号

CAP_SETGID

6

允许改变组ID

CAP_SETUID

7

允许改变用户ID

CAP_SETPCAP

8

允许向其它进程转移能力以及删除其它进程的任意能力

CAP_LINUX_IMMUTABLE

9

允许修改文件的不可修改(IMMUTABLE)和只添加(APPEND-ONLY)属性

CAP_NET_BIND_SERVICE

10

允许绑定到小于1024的端口

CAP_NET_BROADCAST

11

允许网络广播和多播访问

CAP_NET_ADMIN

12

允许执行网络管理任务:接口、防火墙和路由等

CAP_NET_RAW

13

允许使用原始(raw)套接字

CAP_IPC_LOCK

14

允许锁定共享内存片段

CAP_IPC_OWNER

15

忽略IPC所有权检查

CAP_SYS_MODULE

16

插入和删除内核模块

CAP_SYS_RAWIO

17

允许对ioperm/iopl的访问

CAP_SYS_CHROOT

18

允许使用chroot()系统调用

CAP_SYS_PTRACE

19

允许跟踪任何进程

CAP_SYS_PACCT

20

允许配置进程记帐(process accounting)

CAP_SYS_ADMIN

21

允许执行系统管理任务:加载/卸载文件系统、设置磁盘配额、开/关交换设备和文件等

CAP_SYS_BOOT

22

允许重新启动系统

CAP_SYS_NICE

23

允许提升优先级,设置其它进程的优先级

CAP_SYS_RESOURCE

24

忽略资源限制

CAP_SYS_TIME

25

允许改变系统时钟

CAP_SYS_TTY_CONFIG

26

允许配置TTY设备

CAP_MKNOD

27

允许使用mknod()系统调用

CAP_LEASE

28

允许取消文件上的租借期

内核提供了两个系统调用sys_capgetsys_capset来得到或设置指定PID或所有进程的能力,这两个函数都是通过对进程任务结构task_struct中的能力变量进行操作来实现的。在kernel/capability.c中有全局变量cap_bset设置进程初始的能力,这个变量列出如下:
kernel_cap_t cap_bset = CAP_INIT_EFF_SET;


用户可以在/proc/sys/kernel/cap-bound文件中可看到系统保留的能力。在默认情况下,所有的位都是打开的。在内核内存区中,/proc/sys/kernel/cap-bound直接映射到cap_bset变量中。
root用户可以删除系统保留的能力。却不能再恢复被删除的能力,只有init进程能够添加能力。通常,一个能力如果从能力边界集中被删除,只有系统重新启动才能恢复。
用户可通过shell命令行设置能力。例如:禁止加载/卸载任何内核模块,CAP_SYS_MODULE能力的值是16,可用下列命令完成:

[root@]# echo 0xFFFEFFFF >/proc/sys/kernel/cap-bound
 
能力机制操作函数集
Linux对能力的操作函数定义在操作函数集capability_ops,其列出如下(在linux26/security/capability.c中):

Linux能力机制_第3张图片

进程运行时,通过检查进程的有效能力集tsk->cap_effective的能力位,判断进程是否具有相应的能力。检查能力的通用函数cap_capable列出如下:

Linux能力机制_第4张图片

 
应用程序运行设置信任值
二进制应用程序运行时,Linux内核会调用函数load_elf_binary装载执行二进制elf格式文件。函数load_elf_binary执行时,会调用函数compute_creds设置新运行进程的信任值,包括uidgid、能力集、安全ID、密钥环等。函数compute_creds的调用层次图如图。
 

Linux能力机制_第5张图片

函数compute_creds计算并设置当前进程的信任值,然后设置信号、资源限制,唤醒等待的父进程。其列出如下(在linux26/fs/exec.c中):

Linux能力机制_第6张图片

新运行的进程应清空线程密钥环和进程密钥环。清除函数exec_keys列出如下(在linux26/security/keys/process_keys.c中):

Linux能力机制_第7张图片

函数selinux_bprm_apply_creds给当前进程设置uidgid、能力集和sid。其列出如下(在linux26/security/capability.c中):

Linux能力机制_第8张图片

函数cap_bprm_apply_creds设置当前进程的uid、gid和能力集。二进制文件通过调用函数fork(),产生新的进程,这个新的进程为当前进程。
当前进程的uid和gid来自于文件系统的uid和gid。
当前进程的能力集来自于父进程的能力集、系统的缺省能力集cap_bset和linux_binprm的能力集。结构linux_binprm存储二进制文件执行时产生的各种参数。当前进程能力集的计算逻辑公式列出如下:
函数cap_bprm_apply_creds列出如下(在linux26/security/commoncap.c中):

Linux能力机制_第9张图片


函数selinux_bprm_post_apply_creds在设置信任值后调用,用来设置信号、资源限制、唤醒等待的父进程。其列出如下:

Linux能力机制_第10张图片

Linux能力机制_第11张图片

640?wx_fmt=jpeg


你可能感兴趣的:(Linux能力机制)