Linux能力(capability)机制

Linux能力机制概述

在以往的UNIX系统上,为了做进程的权限检查,把进程分为两类:特权进程(有效用户ID是0)和非特权进程(有效用户ID是非0)。特权进程可以通过内核所有的权限检查,而非特权进程的检查则是基于进程的身份(有效ID,有效组及补充组信息)进行。

从linux内核2.2开始,Linux把超级用户不同单元的权限分开,可以单独的开启和禁止,称为能力(capability)。可以将能力赋给普通的进程,使其可以做root用户可以做的事情。

此时内核在检查进程是否具有某项权限的时候,不再检查该进程的是特权进程还是非特权进程,而是检查该进程是否具有其进行该操作的能力。例如当进程设置系统时间,内核会检查该进程是否有设置系统时间(CAP_SYS_TIME)的能力,而不是检查进程的ID是否为0;

当前Linux系统中共有37项特权,可在/usr/include/linux/capability.h文件中查看

#define CAP_CHOWN            0
#define CAP_DAC_OVERRIDE     1
#define CAP_DAC_READ_SEARCH  2
#define CAP_FOWNER           3
#define CAP_FSETID           4
#define CAP_KILL             5
#define CAP_SETGID           6
#define CAP_SETUID           7
#define CAP_SETPCAP          8
#define CAP_LINUX_IMMUTABLE  9
#define CAP_NET_BIND_SERVICE 10
#define CAP_NET_BROADCAST    11
#define CAP_NET_ADMIN        12
#define CAP_NET_RAW          13
#define CAP_IPC_LOCK         14
#define CAP_IPC_OWNER        15
#define CAP_SYS_MODULE       16
#define CAP_SYS_RAWIO        17
#define CAP_SYS_CHROOT       18
#define CAP_SYS_PTRACE       19
#define CAP_SYS_PACCT        20
#define CAP_SYS_ADMIN        21
#define CAP_SYS_BOOT         22
#define CAP_SYS_NICE         23
#define CAP_SYS_RESOURCE     24
#define CAP_SYS_TIME         25
#define CAP_SYS_TTY_CONFIG   26
#define CAP_MKNOD            27
#define CAP_LEASE            28
#define CAP_AUDIT_WRITE      29
#define CAP_AUDIT_CONTROL    30
#define CAP_SETFCAP         31
#define CAP_MAC_OVERRIDE     32
#define CAP_MAC_ADMIN        33
#define CAP_SYSLOG           34
#define CAP_WAKE_ALARM            35
#define CAP_BLOCK_SUSPEND    36

Linux能力机制的实现

一个完整的能力机制需要满足以下三个条件:

1、对进程的所有特权操作,linux内核必须检查该进程该操作的特权位是否使能。

2、Linux内核必须提供系统调用,允许进程能力的修改与恢复。

3、文件系统必须支持能力机制可以附加到一个可执行文件上,但文件运行时,将其能力附加到进程当中。

到linux内核版本2.6.24为止,上述条件的1、2可以满足。从linux内核2.6.24开始,上述3个条件可以都可以满足

每个进程包括三个能力集,含义如下:

Permitted: 它是effective capabilities和Inheritable capability的超集。如果一个进程在Permitted集合中丢失一个能力,它无论如何不能再次获取该能力(除非特权用户再次赋予它)

Inheritable: 它是表明该进程可以通过execve继承给新进程的能力。

Effecitive: Linux内核真正检查的能力集。

从2.6.24开始,Linux内核可以给可执行文件赋予能力,可执行文件的三个能力集含义如下:

Permitted:该能力当可执行文件执行时自动附加到进程中,忽略Inhertiable capability。

Inheritable:它与进程的Inheritable集合做与操作,决定执行execve后新进程的Permitted集合。

Effective: 文件的Effective不是一个集合,而是一个单独的位,用来决定进程成的Effective集合。

有上述描述可知,Linux系统中的能力分为两部分,一部分是进程能力,一部分是文件能力,而Linux内核最终检查的是进程能力中的Effective。而文件能力和进程能力中的其他部分用来完整能力继承、限制等方面的内容。

查看某个进程的能力

# cat /proc/62598/status
Name:    supervisord
Umask:    0022
State:    S (sleeping)
Tgid:    62598
Ngid:    0
Pid:    62598
PPid:    1
TracerPid:    0
Uid:    0    0    0    0
Gid:    0    0    0    0
FDSize:    64
Groups:
VmPeak:      221404 kB
VmSize:      221404 kB
VmLck:           0 kB
VmPin:           0 kB
VmHWM:       12080 kB
VmRSS:       12080 kB
RssAnon:       10940 kB
RssFile:        1140 kB
RssShmem:           0 kB
VmData:       10116 kB
VmStk:         132 kB
VmExe:           4 kB
VmLib:       10396 kB
VmPTE:         236 kB
VmSwap:           0 kB
Threads:    1
SigQ:    1/6978
SigPnd:    0000000000000000
ShdPnd:    0000000000000000
SigBlk:    0000000000000000
SigIgn:    0000000001001000
SigCgt:    0000000180014807
CapInh:    0000000000000000
CapPrm:    0000001fffffffff
CapEff:    0000001fffffffff
CapBnd:    0000001fffffffff
CapAmb:    0000000000000000
Seccomp:    0

SpeculationStoreBypass:    vulnerable
Cpus_allowed:    ffffffff,ffffffff
Cpus_allowed_list:    0-63
Mems_allowed:    00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list:    0
voluntary_ctxt_switches:    22260
nonvoluntary_ctxt_switches:    2