========================================
åˆè¯† SELinux
========================================
:slug: understanding_selinux
:date: 2017-06-22 18:21
:lang: zh_hans
:tags: selinux, centos
:description: 以 CentOS 为平å°æ•´ç†äº†å…¥é—¨ SELinux 所需è¦æŽŒæ¡çš„最基本知识,围绕例åæ¥è¿›è¡Œè¯´æ˜Žã€‚
:color: #161616
:featured_image: /nocimages/understanding_selinux_0.png
:noindent: true
.. contents::
这是我第一次写关于 SELinux çš„æ–‡ç« ï¼Œ SELinux 是一个比较庞大的强制访问控制方案,å•å•å°±æŽ§åˆ¶åŽŸç†è€Œè¨€æ˜¯ç›¸å¯¹ç®€å•æ˜“懂的,å¤æ‚的是å„ç§è§„则间的è”系和æŸç¼šï¼Œä»¥åŠå¦‚何选择。本文会从我对其ç†è§£çš„角度进行书写,关注点主è¦æ˜¯å®žçŽ°å’Œåº”用。
我是看的 Red Hat çš„ `SELinux User's and Administrator's Guide`_ 入的门,本文则会使用我自己的è¯æ¥è¿›è¡Œæ€»ç»“和概括,以便于快速入门,看æºé“¾æŽ¥çš„文档则å¯ä»¥æ›´è¯¦ç»†çš„了解到 SELinux,但有些内容比如å„ç§ç–略的选择,工具的选择和介ç»å´æ˜¯ä¸Šæ–‡æ‰€ç¼ºä¹çš„,我å•ç‹¬æ•´ç†çš„也会在下文æ述。
é‰´äºŽæœ¬æ–‡å¾ˆåŸºç¡€ï¼Œæ‰€ä»¥å‡ ä¸ªåŸºæœ¬çš„åè¯æˆ‘都会在文ä¸ä»¥é€‚当的形å¼è¯´æ˜Žã€‚
| *注: 关于部分有争议的åè¯æˆ‘ä¸å‡†å¤‡ç”¨ä¸æ–‡è¡¨ç¤ºï¼Œæ¯”如 type,class,subject ç‰ç‰ï¼Œè¢«å†™æˆä¸æ–‡çš„å‡æ˜¯æˆ‘力所能åŠä¸‹è®¤ä¸ºç»å¯¹ä¸ä¼šæœ‰äº‰è®®æˆ–者本身就å¯ä»¥ç”¨ä¸æ–‡æè¿°çš„*
| *注: 本文ä¸ä¼šæ¶‰åŠåˆ° SELinux çš„ MLS ç–ç•¥*
什么是 SELinux 以åŠå¦‚何ç†è§£å®ƒ
==================================================
:ruby:`安全增强型 Linux| Security-Enhanced Linux` 是 Linux å†…æ ¸ä¸‹çš„ä¸€ä¸ªå®‰å…¨æ¨¡å—,它在 Linux :ruby:`自主访问控制|Discretionary Access Control` [1]_ 的基础上æ供了é¢å¤–的访问控制安全ç–略,它æ供的控制组åˆä¸º :ruby:`以角色为基础的访问控制|Role-Based Access Control` (RBAC), Type Enforcement (TE) å’Œå¯é€‰çš„ Multi-Level Security (MLS)。需è¦æ˜Žç¡®çš„是 SELinux 是用æ¥å¼ºåŒ–已有的安全系统的,而ç»å¯¹ä¸æ˜¯ç”¨æ¥æ›¿ä»£çš„。
列出一æ¡æŸ¥çœ‹å½“å‰æ–‡ä»¶ï¼ˆå¤¹ï¼‰ SELinux 上下文属性的命令:
.. code-block:: shell-session
# ls -Z test
-rwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 test
一个相当熟悉的命令 :code:`ls` ,就åƒå¹³å¸¸ä½¿ç”¨ :code:`ls -l` 查看文件的详细信æ¯ä¸€æ ·ã€‚所以由æ¤è®©æˆ‘对 SELinux çš„ç†è§£å˜æˆäº†å…¶ä¸ºç»„æˆ Linux 系统安全的最基本的一部分,必须掌æ¡ã€‚
明确两个åè¯:
Object
所有的文件,包括文件夹ã€è½¯é“¾æŽ¥ã€è®¾å¤‡ç‰ï¼Œéƒ½è¢«ç†è§£ä¸º Object。
Subject
Linux 下的进程。
简述æƒé™å®¡æŸ¥è¿‡ç¨‹
------------------------------------------------------------
.. ditaa::
:alt: selinux 处ç†æµç¨‹
+-------------------------------------------------------------------+
User Space | Kernel Space | User Space
| |
| |
| deny |
| /----------------------------------\ |
| | | |
| +-----+ allow +---------+ | | allow/deny
exec a command ---> | --> system call ----> | DAC | ----------> | SELinux | ------+---> | -------------->
| +-----+ +---------+ |
| ^ | |
| : : |
| | v |
| /-=---\ |
| | AVC | |
| \-----/ |
| ^ | |
| : : |
| | v |
| /----------\ |
| | Policies | |
| \----------/ |
| |
+-------------------------------------------------------------------+
上图是在å¯ç”¨ SELinux 情况下的一个 Linux æƒé™å®¡æŸ¥è¿‡ç¨‹ï¼Œå½“用户空间下的一个进程需è¦ç³»ç»Ÿè°ƒç”¨æ—¶ï¼Œé¦–先会进行 DAC 检查,åªæœ‰ DAC 检查通过的æ‰ä¼šè¿›è¡Œ SELinux çš„ç–略验è¯ï¼Œæœ€åŽåˆ¤æ–是å¦å…许被调用。针对 SELinux çš„ç–略所决定的是å¦å…许执行的æŸä¸€æ“作,会被缓å˜åœ¨ :ruby:`访问å‘é‡ç¼“å˜|Access Vector Cache` (AVC) 内,以æ高执行效率。
SELinux 的默认ç–略为 targeted (也是推è的),在这个ç–略下,Type Enforcement (TE) 是主è¦çš„çš„æƒé™æŽ§åˆ¶æ‰‹æ®µï¼Œå¤§å¤šæ•°æƒ…况下, SELinux 用户和角色都是å¯ä»¥å¿½ç•¥çš„。也就是说关注点在 :code:`admin_home_t` 这个 type 属性上。
拥有相åŒåŸŸç±»åž‹çš„进程è¿è¡ŒäºŽåŒä¸€ä¸ªåŸŸä¸‹ï¼Œä¸åŒåŸŸä¸‹çš„进程在没有相应的 SELinux ç–ç•¥å…许的情况下是ä¸èƒ½äº’相访问和æ“作的。注æ„的是,默认情况下的 Linux 用户è¿è¡Œåœ¨ :code:`unconfined_t` 域(åŽæ–‡ä»¥éžéžé™åˆ¶æ€§åŸŸæ述)下,而由该域下用户所直接执行的命令对应的进程大部分åŒæ ·æ˜¯å¤„于该域的,虽然对于éžé™åˆ¶æ€§åŸŸä¸‹çš„进程而言,SELinux ç–略也是会起作用的,但目å‰å˜åœ¨çš„ç–略规则对éžé™åˆ¶æ€§åŸŸä¸‹è¿›ç¨‹å¼€æ”¾å‡ 乎所有的访问æƒé™ï¼Œç›¸å½“于 SELinux ä¸èµ·ä½œç”¨äº†ï¼Œä»…é DAC æ¥åšæƒé™æŽ§åˆ¶ã€‚所以这边就引入到一个处ç†æ–¹å¼ï¼Œå«åš :ruby:`域过渡|Domain transitions` ,会在下文详细æ述用法。
简而言之就是,进程所属的域类型确定了该进程所拥有的æƒé™ï¼Œç”± SELinux ç–略规则æ¥æŽ§åˆ¶ã€‚
CentOS 下 SELinux 工具åŠå¯¹åº”的包
==================================================
`本人整ç†çš„工具列表`_ ,一般æ¥è¯´å°±æ˜¯ Red Hat 系所通用的了,其它å‘è¡Œç‰ˆå¤§è‡´ä¹Ÿåº”è¯¥ä¸€æ ·ã€‚
å…¶ä¸ï¼Œ :code:`semodule_unpackage`, :code:`sepolicy`, :code:`sefcontext_compile`, :code:`selabel_digest`, :code:`selabel_lookup`, :code:`selabel_lookup_best_match`, :code:`selabel_partial_match`, :code:`selinuxexeccon`, :code:`selinux_restorecon` 这些工具我在 CentOS 6 下则并未找到, CentOS 7 下æ‰å¯ä»¥å®‰è£…到。
CentOS 7 下的 :code:`sepolicy` 这一套件对于查询布尔值的说明ã€åŸŸä¹‹é—´é€šè®¯æƒ…况ç‰éžå¸¸æ–¹ä¾¿ï¼Œå¯ä»¥æŸ¥ man 手册以详细了解。还有命令的替æ¢å…³ç³»ï¼Œæ¯”如 :code:`sepolicy generate` 替æ¢äº†ä¹‹å‰çš„ :code:`sepolgen`。
常用的最最基本的工具,大概是 :code:`semanage`, :code:`restorecon`, :code:`chcon`, :code:`fixfiles`, :code:`setsebool`, :code:`getsebool`, :code:`sestatus`, :code:`avcstat`, :code:`setenforce`, :code:`getenforce`, :code:`sesearch`, :code:`sepolicy`, :code:`matchpathcon`.
还有一个 :code:`ausearch` 属于审计一å—的,但是用于查询 SELinux 的报错éžå¸¸æœ‰æ•ˆï¼Œéœ€è¦æŸ¥ man 手册详细了解记ä½ï¼Œå¹¶æ´»ç”¨ã€‚
SELinux é…置文件
==================================================
以 CentOS 7 为例, :code:`/etc/selinux/config` 为 SELinux 的主é…ç½®æ–‡ä»¶ï¼Œå®ƒæŽ§åˆ¶ç€ SELinux çš„å¯ç”¨ä¸Žç¦ç”¨ï¼Œå¯ç”¨çš„模å¼å’Œä½¿ç”¨çš„ç–略。
以默认的 enforcing 模å¼å’Œ targeted ç–略为例,该ç–略的é…置文件在 :code:`/etc/selinux/targeted` 目录下,如果是其它的ç–略的è¯ï¼Œé…置文件åŒæ ·éœ€è¦åœ¨ :code:`/etc/selinux/{对应ç–ç•¥å}` 目录下。
比如默认已ç»é…置好的文件 SELinux 上下文属性分é…规则在 :code:`/etc/selinux/targeted/contexts/files/file_contexts` 文件内,而如果使用了 :code:`semanage` 自定义了的è¯ï¼Œåˆ™ä¼šåœ¨ :code:`/etc/selinux/targeted/contexts/files/file_contexts.local` 文件内。注æ„的是ä¸è¦ç›´æŽ¥åŽ»ä¿®æ”¹æ–‡ä»¶å†…的内容。
SELinux 上下文组æˆ
==================================================
SELinux ä¸Šä¸‹æ–‡æ ¼å¼ä¸º :code:`se_user:role:type:level` ,也就是由这四个å—段组æˆï¼Œå¯ä»¥çœ‹æœ¬æ–‡æœ€å¼€å§‹é‚£æ¡å‘½ä»¤çš„输出,以下是å—段说明:
se_user
SELinux user 是被ç–略已知的身份,该身份确定了一组特定的规则和一个 MLS/MSC 范围。æ¯ä¸ª Linux 用户都会通过 SELinux ç–ç•¥è¢«æ˜ å°„åˆ°ä¸€ä¸ª SELinux 用户,这使得 Linux 用户继承了对应 SELinux 用户的一些é™åˆ¶ã€‚SELinux 用户身份被用在其会è¯é‡Œè¿›ç¨‹çš„ SELinux 上下文信æ¯ä¸ï¼Œç”¨äºŽå®šä¹‰è¯¥è¿›ç¨‹ä»¥ä»€ä¹ˆè§„则和级别è¿è¡Œã€‚
以 root 用户执行以下命令:
.. code-block:: shell-session
# semanage login -l
Login Name SELinux User MLS/MCS Range Service
__default__ unconfined_u s0-s0:c0.c1023 *
root unconfined_u s0-s0:c0.c1023 *
system_u system_u s0-s0:c0.c1023 *
å¯ä»¥çœ‹åˆ°æ˜¾ç¤ºäº† Linux 用户和 SELinux çš„æ˜ å°„å…³ç³»ã€‚å¦‚æžœç³»ç»Ÿä¸æ”¯æŒ MLS/MCS çš„è¯ï¼Œé‚£ä¹ˆæœ€åŽä¸¤åˆ—则应该ä¸ä¼šæ˜¾ç¤ºï¼ˆæŸ¥åˆ°çš„èµ„æ–™ä¸Šç¤ºä¾‹æ˜¯åœ¨è¿™æ ·å的,我并没有ä¸æ”¯æŒ MLS/MCS 的环境æ¥æµ‹è¯•éªŒè¯ï¼‰ï¼Œä»¥ä¸‹æ˜¯æ¯ä¸ªå—段的介ç»ï¼š
* Login Name 表示匹é…çš„ Linux 用户,以 :code:`%` 开头的代表匹é…到一个组。如果没有任何匹é…é¡¹åˆ™åŒ¹é… :code:`__default__` 行的规则。
* SELinux User 表示匹é…到的 Linux 用户所对应的 SELinux 用户,这里的用户必须是已ç»æœ‰é…置好å˜åœ¨çš„,å¯ä»¥åœ¨ :code:`/etc/selinux/{POLICYNAME}/contexts/users/` 目录下找到。
* MLS/MCS Range 则表示 Multi-Level Security å’Œ Multi-Category Security 所使用的级别,下文将详细æ述。
* Service 列则是用于判æ–从什么æœåŠ¡ï¼ˆè¿™é‡Œçš„æœåŠ¡éœ€è¦æ˜¯å¯ä»¥ä»¥ä¹‹ç™»å½•çš„ PAM æœåŠ¡ï¼‰ç™»å½•çš„用户采用什么 SELinux 上下文属性,ä¸è¿‡ :code:`semanage` 工具是没有æ供相应的设置的,但å¯ä»¥ç›´æŽ¥ä¿®æ”¹ :code:`/etc/selinux/{POLICYNAME}/logins/` 文件夹下的对应用户å的文件,比如è¦ä¿®æ”¹ä»Ž sshd 登录的 root 用户的 SELinux user 为 :code:`user_u` çš„è¯ï¼Œæ–°å»ºä¸€ä¸ª :code:`/etc/selinux/targeted/logins/root` æ–‡ä»¶ï¼Œæ·»åŠ å†…å®¹ :code:`sshd:user_u:s0` 到文件内,详细的å¯ä»¥çœ‹ `Google Books 上`_ æœç´¢åˆ°çš„说明。
:code:`system_u` 行是给系统进程所使用的,一般ä¸ç”¨åŽ»è€ƒè™‘它。而登录时用户的上下文确认则ä¾èµ–于 :code:`/etc/selinux/{POLICYNAME}/contexts/users/` 目录下的é…置文件,è¿è¡Œ :code:`man user_contexts` 查看详细的说明。如果说在 :code:`/etc/selinux/{POLICYNAME}/contexts/users/` 目录下的é…置文件é…ç½®ä¸æ£ç¡®ï¼Œé‚£ä¹ˆä¼šä»Ž :code:`/etc/selinux/{POLICYNAME}/contexts/default_context` 文件下获å–默认的é…置。
role
Role-Based Access Control 是 SELinux 的一部分,role å°±æ˜¯å…¶å±žæ€§ã€‚å…¶æ ¹æ® SELinux user æ¥ç¡®å®š role,å†æ ¹æ® role æ¥ç¡®å®šä¸€ä¸ªåŸŸã€‚所以 role 相当于是 SELinux 用户与å„类域间的æœåŠ¡ä½“,确定了 role å°±å¯ä»¥ç¡®å®šè¿›ç¨‹æ‰€å±žåŸŸï¼Œæœ€ç»ˆæŽ§åˆ¶ä½•ç§ object type å¯ä»¥è¢«è®¿é—®ã€‚这一系列的判æ–é™ä½Žäº†ææƒæ”»å‡»çš„风险。注æ„的是 RBAC 是用于进程而并éžæ–‡ä»¶çš„,对于文件æ¥è¯´ï¼Œè§’色并没有什么æ„义,文件上所赋予的 :code:`object_r` role 是æŒä¹…化å˜å‚¨å’Œç½‘络文件系统上给文件的一个通用化角色,ä¸è¿‡åœ¨ :code:`/proc` 文件夹下,一些和进程相关的文件的角色å¯èƒ½æ˜¯ :code:`system_r` 。
SElinux user 与 role 的对应ç–ç•¥å¯ä»¥é€šè¿‡å¦‚下命令查看:
.. code-block:: shell-session
# semanage user -l
Labeling MLS/ MLS/
SELinux User Prefix MCS Level MCS Range SELinux Roles
guest_u user s0 s0 guest_r
root user s0 s0-s0:c0.c1023 staff_r sysadm_r system_r unconfined_r
staff_u user s0 s0-s0:c0.c1023 staff_r sysadm_r system_r unconfined_r
sysadm_u user s0 s0-s0:c0.c1023 sysadm_r
system_u user s0 s0-s0:c0.c1023 system_r unconfined_r
unconfined_u user s0 s0-s0:c0.c1023 system_r unconfined_r
user_u user s0 s0 user_r
xguest_u user s0 s0 xguest_r
一æ¡è®°å½•å¯¹åº”有多个 roles 则æ„味ç€è¯¥ SELinux user å¯ä»¥åœ¨è®°å½•çš„ roles 之间切æ¢ï¼Œå¯ä»¥ä½¿ç”¨ :code:`newrole` 命令æ¥åˆ‡æ¢ã€‚
而 role 所å…许被分é…的域类型则å¯ä»¥é€šè¿‡å¦‚下命令æ¥æŸ¥çœ‹ï¼š
.. code-block:: shell-session
# seinfo -ruser_r -x
user_r
Dominated Roles:
user_r
Types:
abrt_helper_t
alsa_home_t
antivirus_home_t
httpd_user_content_t
httpd_user_htaccess_t
...
举个æƒé™çš„例å,比如需è¦æ‰§è¡Œ :code:`sudo` 命令,å¯ä»¥çœ‹åˆ°å…¶ SELinux 上下文下的 object type 为 :code:`sudo_exec_t` ,然åŽæ¥åšä»¥ä¸‹å‡ 个信æ¯çš„查询(这边感谢 irc é¢‘é“ #selinux 里的 grift æ点关è”属性概念):
* :code:`sudo_exec_t` çš„å…³è”属性有哪些:
.. code-block:: shell-session
# seinfo -xtsudo_exec_t
sudo_exec_t
application_exec_type
entry_type
exec_type
file_type
non_auth_file_type
non_security_file_type
* :code:`user_r` 角色对应的 :code:`user_t` 域是å¦æœ‰å¯¹è¯¥ object type 的直接规则以å…许其执行æƒé™ï¼š
.. code-block:: shell-session
# sesearch -A -suser_t -d -tsudo_exec_t
#
* :code:`user_t` 域是å¦æœ‰å¯¹è¯¥ object type å…³è”属性的规则æ¥æ‰§è¡Œï¼š
.. code-block:: shell-session
# sesearch -ASCT -suser_t -tsudo_exec_t
Found 3 semantic av rules:
allow user_t application_exec_type : file { ioctl read getattr lock execute execute_no_trans open } ;
allow user_usertype file_type : filesystem getattr ;
allow user_usertype application_exec_type : file { ioctl read getattr lock execute execute_no_trans open } ;
所以虽然该域没有对该 object type 的直接规则用于执行,但是该域本身被赋予了对具有 :code:`application_exec_type` 属性的 object type 的执行ç‰æƒé™ï¼Œæ‰€ä»¥æ‰§è¡Œæ˜¯æ²¡æœ‰é—®é¢˜ï¼š
.. code-block:: shell-session
$ sudo -i
sudo: PERM_SUDOERS: setresuid(-1, 1, -1): Operation not permitted
但是æ“作还是被拒ç»äº†ï¼Œä»Žæ示信æ¯å°±å¯ä»¥çœ‹åˆ°æ˜¯ setuid æ“作被拒,进一æ¥æŸ¥çœ‹è¯¦ç»†ä¿¡æ¯ï¼š
.. code-block:: shell-session
# audit2why -al | tail
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access.
type=AVC msg=audit(1498119023.011:274): avc: denied { setuid } for pid=2944 comm="sudo" capability=7 scontext=user_u:user_r:user_t:s0 tcontext=user_u:user_r:user_t:s0 tclass=capability
Was caused by:
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access.
很明确地说明了 :code:`user_t` 域下是没有 setuid 的能力的,如下命令查看其拥有的能力:
.. code-block:: shell-session
# sesearch -ASCT -suser_t -tuser_t | grep capability
allow user_t user_t : capability { chown fowner setgid net_bind_service sys_chroot audit_write } ;
DT allow user_t user_t : capability sys_chroot ; [ selinuxuser_use_ssh_chroot ]
所以 :code:`user_r` 这个角色默认是ä¸èƒ½æ‰§è¡Œ :code:`sudo` 的。而 :code:`staff_r` 这个角色å¯ä»¥ï¼Œä½†æ˜¯å‚考上述规则查看åŽä¼šå‘现其åŒæ ·æ²¡æœ‰å¯¹è‡ªèº«åŸŸ :code:`staff_t` çš„ setuid 能力,å¯ä»¥æ‰§è¡Œçš„åŽŸå› æ˜¯å½“å…¶åœ¨æ‰§è¡Œ :code:`sudo` 命令时,有域过渡规则规定其过渡到 :code:`staff_sudo_t` 域下(这边åŒæ ·éœ€è¦æ³¨æ„该 role 是å¦å…许被分é…该域,å‚考上文命令),该域则有 setuid 的能力。以下命令查看过渡规则:
.. code-block:: shell-session
# sesearch -T -sstaff_t | grep sudo_exec_t
type_transition staff_t sudo_exec_t : process staff_sudo_t;
本段连带ç€ä¹Ÿè§£é‡Šäº†ä¸‹ type 的相关用法,它们本就是需è¦äº’相结åˆä½¿ç”¨çš„。
type
Type 是 Type Enforcement (TE) 的属性,为进程定义了域,为文件定义了类型。SELinux ç–ç•¥è§„åˆ™å®šä¹‰äº†ä»€ä¹ˆæ ·çš„ç±»åž‹å¯ä»¥äº’ç›¸è®¿é—®ï¼Œæ— è®ºæ˜¯åŸŸåŽ»è®¿é—®ç±»åž‹ï¼Œè¿˜æ˜¯åŸŸä¹‹é—´çš„è®¿é—®ã€‚åªæœ‰å½“ SELinux ç–略规则显示的定义了的时候,访问æ‰è¢«å…许。注æ„的是 TE 是 SELinux 的主è¦æŽ§åˆ¶æ‰‹æ®µï¼Œå¤§éƒ¨åˆ†æƒ…况下, SELinux user å’Œ role 是å¯ä»¥è¢«å¿½ç•¥çš„。下文有一个例å是围绕 TE åšè¯¦ç»†ä»‹ç»çš„。
level
Level 是 Multi-Level Security (MLS) å’Œ Multi-Category Security (MCS) çš„å±žæ€§ï¼Œå…¶ä¸ MCS 是 MLS 的特殊实现。一个 MLS 范围是一对级别,当两个级别ä¸åŒæ—¶çš„ä¹¦å†™æ ¼å¼ä¸º :code:`低级别-高级别` ;当两个级别相åŒæ—¶å¯ç›´æŽ¥ä¹¦å†™ä¸º :code:`低级别` ( :code:`s0-s0` å’Œ :code:`s0` æ˜¯ä¸€æ ·çš„)。æ¯ä¸€ä¸ª level 都是çµæ•åº¦-分类 (sensitivity-category) 的组åˆï¼Œ category 是å¯é€‰çš„。当å˜åœ¨æœ‰ category 的时候,level çš„æ ¼å¼ä¸º :code:`sensitivity:category-set`,如果 category ä¸å˜åœ¨ï¼Œé‚£ä¹ˆä»…写作 :code:`sensitivity`。
如果 category 是一系列连ç»çš„,那么å¯ä»¥ç®€å†™ï¼Œæ¯”如 :code:`c0.c3` å’Œ :code:`c0,c1,c2,c3` 是相åŒçš„。人性化的ç‰çº§æ˜ 射关系在文件 :code:`/etc/selinux/targeted/setrans.conf` 下é…置。在 RHEL 系列ä¸ï¼Œé»˜è®¤çš„ targeted ç–略是强制执行 MCS 的,仅有一个çµæ•åº¦ s0,有 1024 个ä¸åŒçš„ categories,从 c0 到 c1023。 s0-s0:c0.c1023 是针对所有 categories çš„ sensitivity 0 级别。
本文ä¸ä¼šæ¶‰åŠ MLS/MCS 这一å—的详细说明。
举个例åæ¥è§£é‡Š TE 为主的基本用法/原ç†
==================================================
ä¹‹å‰ `æœ‰ä¸€ç¯‡æ–‡ç« `_ 写的是在å¯ç”¨ SELinux 情况下部署 NextCloud 的,这里详细说明é…ç½® SELinux 部分,并介ç»ä¸€äº›åŸºæœ¬åŽŸç†ã€‚
* 环境: CentOS 7, æºç 编译安装的 Nginx ä»¥åŠ PHP-FPM, 导入官方仓库åŽä½¿ç”¨ :code:`yum` 命令安装的 MariaDB 10.1
* 目的: é…置好 SELinux 上下文属性,使得网站得以æ£å¸¸è¿è¡Œ
* 总览:
* MariaDB 是使用 :code:`yum` 直接从导入的 MariaDB 官方仓库下安装的,所有的文件的安装路径包å«åœ¨é¢„é…置好的 SELinux 上下文内,而我对其数æ®åº“文件å˜å‚¨è·¯å¾„进行了自定义,所以åªéœ€è¦å¯¹æ–°çš„æ•°æ®åº“文件å˜å‚¨è·¯å¾„进行é…ç½®å³å¯ã€‚
* Nginx å’Œ PHP-FPM 是从æºç 编译安装的,且路径设置都ä¸ä¸ºé»˜è®¤ï¼Œæ‰€ä»¥ç›¸åº”的全部文件的 SELinux 上下文都需è¦è¿›è¡Œé…置。
* æ¤å¤„ä¸è€ƒè™‘任何 DAC æ–¹é¢çš„问题,å‡å®š DAC å‡ä¸ºå…许。
* æ¥éª¤ï¼š
* **é…ç½® MariaDB æ•°æ®åº“å˜å‚¨è·¯å¾„çš„ SELinux 上下文信æ¯**
我自定义的 MariaDB æ•°æ®åº“å˜å‚¨è·¯å¾„为 :code:`/o/db/data/mariadb` ,å¯ä»¥æ˜¾è€Œæ˜“è§çš„是 mariadb 进程需è¦å¯¹è¿™ä¸ªè·¯å¾„有å¯è¯»å¯å†™çš„æƒé™ï¼Œé‚£å…ˆæ¥çœ‹ä¸€ä¸‹ mariadb 守护进程执行工具的 SELinux 上下文信æ¯ï¼š
.. code-block:: shell-session
# ls -Z /usr/sbin/mysqld
-rwxr-xr-x. root root system_u:object_r:mysqld_exec_t:s0 /usr/sbin/mysqld
把关注点放在 :code:`mysqld_exec_t` 这个 SELinux object type 上,是å¦æœ‰å¯¹ä¸€ä¸ªæ–‡ä»¶è¿›è¡Œè¯»å†™æ‰§è¡Œç‰å„ç§å„æ ·çš„æƒé™æ˜¯è¦ä»¥è¿›ç¨‹æ‰€åœ¨çš„域类型(也就是 subject type)æ¥è¿›è¡Œåˆ¤æ–的,拥有æ£ç¡®çš„ SELinux 上下文的å¯æ‰§è¡Œæ–‡ä»¶ï¼Œåœ¨æ‰§è¡Œæ—¶ä¼šå› 为当å‰æ‰€åœ¨åŸŸä¸åŒè€Œä½¿æ‰§è¡Œè¿›ç¨‹è¿›å…¥åˆ°ä¸åŒçš„域下,这便是域过渡。å¯ä»¥é€šè¿‡å‘½ä»¤æ¥æŸ¥çœ‹åˆ°è¿‡æ¸¡è§„则:
.. code-block:: shell-session
# sesearch -T -tmysqld_exec_t
Found 11 semantic te rules:
type_transition openshift_initrc_t mysqld_exec_t : process mysqld_t;
type_transition piranha_pulse_t mysqld_exec_t : process mysqld_t;
type_transition init_t mysqld_exec_t : process mysqld_t;
type_transition kdumpctl_t mysqld_exec_t : process mysqld_t;
type_transition condor_startd_t mysqld_exec_t : process mysqld_t;
type_transition cluster_t mysqld_exec_t : process mysqld_t;
type_transition svc_run_t mysqld_exec_t : process mysqld_t;
type_transition mysqld_safe_t mysqld_exec_t : process mysqld_t;
type_transition glusterd_t mysqld_exec_t : process mysqld_t;
type_transition mysqlmanagerd_t mysqld_exec_t : process mysqld_t;
type_transition initrc_t mysqld_exec_t : process mysqld_t;
å¯ä»¥çœ‹åˆ°åªæœ‰ä¸Šè¿° :code:`cluster_t`, :code:`init_t` ç‰ 11 个域æ‰æœ‰ä¸Ž :code:`mysqld_exec_t` 相关的域过渡规则,且åªèƒ½è¿‡æ¸¡åˆ° :code:`mysqld_t` 下。然åŽå†æ¥çœ‹å½“å‰ bash 进程的域类型和当å‰ç”¨æˆ·çš„ SELinux 上下文:
.. code-block:: shell-session
# ps auxfZ | grep bash
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 uuu 6243 0.0 0.5 115392 3100 pts/0 Ss 19:04 0:00 \_ -bash
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 6267 0.0 0.5 115484 3276 pts/0 S 19:04 0:00 \_ -bash
# id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
å½“å‰ bash 进程所在域由其对应的用户所确定,在没有é…置的情况下,所在域类型便是 :code:`unconfined_t` 了,很明显 :code:`mysqld_exec_t` 没有针对 :code:`unconfined_t` 域的过渡规则,那么直接执行就会导致其进程所在域ä»ç„¶å¤„于 :code:`unconfined_t` 域下:
.. code-block:: shell-session
# sed -i '/\[mysqld\]/auser=root' /etc/my.cnf.d/server.cnf
# /usr/sbin/mysqld > /dev/null 2>&1 &
[1] 10210
# ps -eZ | grep mysqld
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 10210 pts/0 00:00:00 mysqld
# sed -i '/user=root/d' /etc/my.cnf.d/server.cnf
虽然ä¸ä¼šå½±å“到æ£å¸¸è¿è¡Œï¼Œä½†é»˜è®¤æƒ…况下在这个域下进程基本相当于和没有 SELinux ä¸€æ ·äº†ï¼Œå¾ˆä¸å®‰å…¨ã€‚
ä¸è¿‡é€šå¸¸æƒ…况下都是使用 systemdctl æ¥è°ƒç”¨ systemd daemon æ¥æ‰§è¡Œçš„,查看 systemd 进程的 SELinux 上下文信æ¯ï¼Œå¯ä»¥çœ‹åˆ°ï¼š
.. code-block:: shell-session
# ps -eZ | grep systemd
system_u:system_r:init_t:s0 1 ? 00:01:51 systemd
其域类型便是 :code:`init_t` ,所以由它执行的 mysqld å¯ä»¥è¿‡æ¸¡åˆ° :code:`mysqld_t` 域下:
.. code-block:: shell-session
# systemctl start mariadb
# ps -eZ | grep mysqld
system_u:system_r:mysqld_t:s0 7385 ? 00:00:00 mysqld
明确了 mariadb è¿è¡Œè¿›ç¨‹æ‰€åœ¨çš„域,接下æ¥å°±æ˜¯æ˜Žç¡®éœ€è¦ç»™è‡ªå®šä¹‰æ•°æ®åº“路径设置的 SELinux 上下文的 object type 了。åŒæ ·å¯ä»¥å…ˆé€šè¿‡å‘½ä»¤æ¥æŸ¥çœ‹å“ªä¸ª type 符åˆè¦æ±‚:
.. code-block:: shell-session
# sesearch -A -d -s mysqld_t | egrep ' file | dir ' | grep 'read write'
allow mysqld_t mysqld_tmp_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow mysqld_t mysqld_var_run_t : dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir open } ;
allow mysqld_t mysqld_log_t : dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir open } ;
allow mysqld_t var_run_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow mysqld_t mysqld_log_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow mysqld_t mysqld_tmp_t : dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir open } ;
allow mysqld_t mysqld_var_run_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow mysqld_t tmp_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow mysqld_t var_log_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow mysqld_t faillog_t : dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir open } ;
allow mysqld_t mysqld_t : file { ioctl read write getattr lock append open } ;
allow mysqld_t hugetlbfs_t : file { ioctl read write getattr lock append open } ;
allow mysqld_t mysqld_db_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow mysqld_t var_lib_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow mysqld_t faillog_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow mysqld_t lastlog_t : file { ioctl read write create getattr setattr lock append open } ;
allow mysqld_t mysqld_db_t : dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir open } ;
allow mysqld_t krb5_host_rcache_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow mysqld_t krb5_host_rcache_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
allow mysqld_t tmp_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
allow mysqld_t security_t : file { ioctl read write getattr lock append open } ;
å¯ä»¥çœ‹åˆ°æœ‰å¾ˆå¤šçš„ object type 都满足我的 read, write æƒé™çš„è¦æ±‚,其ä¸æœ‰ä¸€ä¸ª type çš„å称为 :code:`mysqld_db_t` ,很能说明问题,从其拥有的æƒé™æ¥çœ‹ï¼Œå¾ˆæ˜Žæ˜¾ read, write 两个æƒé™æ˜¯ä¸å¤Ÿç”¨çš„(关于æƒé™æ‰€å¯¹åº”çš„å„ç§æ“作以åŽå†è¯´ï¼‰ï¼Œé‚£ä¹ˆå°±ç”¨å®ƒäº†ã€‚接下æ¥å°±æ˜¯å¯¹æ–°è·¯å¾„é…ç½® SELinux 上下文信æ¯äº†ï¼š
.. code-block:: shell-session
# semanage fcontext -a -t mysqld_db_t '/o/db/data/mariadb(/.*)?'
# restorecon -Rv /o/db/data/mariadb
第一æ¡å‘½ä»¤æ˜¯å¯¹ :code:`/o/db/data/mariadb` 文件夹åŠå…¶æ‰€æœ‰å内容æŒä¹…化设置相应的 SELinux 上下文的 object typeï¼Œå› ä¸ºè¿™æ¡å‘½ä»¤ä¸ä¼šä½¿ä¹‹åŠæ—¶ç”Ÿæ•ˆï¼Œæ‰€ä»¥éœ€è¦ç¬¬äºŒæ¡å‘½ä»¤é…åˆï¼Œä½¿å¾—å…¶åŠæ—¶ç”Ÿæ•ˆã€‚
è¿™æ ·å对于 MariaDB 下自定义的数æ®åº“å˜å‚¨è·¯å¾„的设置就好了。
* **é…ç½® Nginx çš„ SELinux 上下文信æ¯**
在这里虽然没有现有的执行文件å¯ä»¥ç”¨æ¥åšå‚考,但是默认的规则å´æ˜¯åœ¨çš„。所以æœç´¢æ–‡ä»¶ :code:`/etc/selinux/targeted/contexts/files/file_contexts` 下的 :code:`/usr/sbin/nginx` å—段,就å¯ä»¥çŸ¥é“默认情况下对 nginx 分é…的执行域是什么了。å‚考上述 MariaDB 过程,å¯ä»¥æŸ¥åˆ°å…¶æ‰§è¡ŒåŸŸç±»åž‹ä¸º :code:`httpd_t` ,åŒæ ·å‚考上述 MariaDB 过程å¯ä»¥å¯¹ Nginx 进程需è¦çš„指定系统文件é…ç½® object type 为 :code:`httpd_sys_content_t` ,而对需è¦è¯»å†™çš„系统文件é…ç½® object type 为 :code:`httpd_sys_rw_content_t` ,需è¦å¯ä»¥è®© :code:`httpd_t` 域直接执行的文件é…ç½® object type 为 :code:`httpd_sys_script_exec_t` 。如何é…置的è¯ï¼ŒåŒæ ·æ˜¯ä½¿ç”¨ :code:`semanage` 命令。
å¯èƒ½åœ¨è¿™é‡Œä¼šéœ€è¦å¤åˆ¶å‡ 个原先é…置好的é…ç½®æ–‡ä»¶åˆ°å½“å‰ Nginx çš„é…置目录,那么就需è¦æ³¨æ„在文件å¤åˆ¶/移动过程ä¸çš„ SELinux 上下文å˜åŒ–,比如:
.. code-block:: shell-session
# ls -Z ~/i.conf
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /root/i.conf
# ls -dZ /o/conf/nginx/conf.d
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /o/conf/nginx/conf.d
# cp ~/i.conf /o/conf/nginx/conf.d/
# ls -Z /o/conf/nginx/conf.d/i.conf
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /o/conf/nginx/conf.d/i.conf
# rm /o/conf/nginx/conf.d/i.conf
rm: remove regular file ‘/o/conf/nginx/conf.d/i.conf’? y
# mv i.conf /o/conf/nginx/conf.d/
# ls -Z /o/conf/nginx/conf.d/i.conf
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /o/conf/nginx/conf.d/i.conf
# mv /o/conf/nginx/conf.d/i.conf ~/
# touch /o/conf/nginx/conf.d/i.conf
# chcon -t etc_t /o/conf/nginx/conf.d/i.conf
# ls -Z /o/conf/nginx/conf.d/i.conf
-rw-r--r--. root root unconfined_u:object_r:etc_t:s0 /o/conf/nginx/conf.d/i.conf
# ls -Z ~/i.conf
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /root/i.conf
# cp ~/i.conf /o/conf/nginx/conf.d/i.conf
cp: overwrite ‘/o/conf/nginx/conf.d/i.conf’? y
# ls -Z /o/conf/nginx/conf.d/i.conf
-rw-r--r--. root root unconfined_u:object_r:etc_t:s0 /o/conf/nginx/conf.d/i.conf
# cp --preserve=context ~/i.conf /o/conf/nginx/conf.d/i.conf
cp: overwrite ‘/o/conf/nginx/conf.d/i.conf’? y
# ls -Z /o/conf/nginx/conf.d/i.conf
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /o/conf/nginx/conf.d/i.conf
# chcon -t etc_t /o/conf/nginx/conf.d/i.conf
# ls -Z /o/conf/nginx/conf.d/i.conf
-rw-r--r--. root root unconfined_u:object_r:etc_t:s0 /o/conf/nginx/conf.d/i.conf
# mv ~/i.conf /o/conf/nginx/conf.d/i.conf
mv: overwrite ‘/o/conf/nginx/conf.d/i.conf’? y
# ls -Z /o/conf/nginx/conf.d/i.conf
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /o/conf/nginx/conf.d/i.conf
å¯ä»¥çœ‹åˆ°ï¼Œåœ¨å¤åˆ¶æ–‡ä»¶çš„æ—¶å€™ï¼Œå¦‚æžœç›®æ ‡æ–‡ä»¶ä¸å˜åœ¨ï¼Œåˆ™ä¼šä¿ç•™æºæ–‡ä»¶çš„ SELinux 上下文信æ¯ï¼Œè€Œå¦‚æžœç›®æ ‡æ–‡ä»¶å˜åœ¨ï¼Œåˆ™ä¼šä¿ç•™åŽŸç›®æ ‡æ–‡ä»¶çš„ SELinux 上下文信æ¯ï¼Œä¸è¿‡ä¹Ÿå¯ä»¥é€šè¿‡ä½¿ç”¨å‚æ•° :code:`--preserve=context` ä¿ç•™æºæ–‡ä»¶çš„ SELinux 上下文信æ¯ã€‚
在移动文件的时候,则是ä¿ç•™æºæ–‡ä»¶çš„ SELinux 上下文信æ¯è€Œä¸ç®¡ç›®æ ‡æ–‡ä»¶æ˜¯å¦å˜åœ¨ã€‚
命令 :code:`matchpathcon` å¯ä»¥æ–¹ä¾¿åœ°æ£€æŸ¥æ–‡ä»¶ï¼ˆå¤¹ï¼‰çš„ SELinux 上下文与系统é…置是å¦ä¸€è‡´ï¼Œæ¯”如:
.. code-block:: shell-session
# matchpathcon -V /o/conf/nginx/conf.d/* | grep -v 'verified\.$'
/o/conf/nginx/conf.d/i.conf has context unconfined_u:object_r:admin_home_t:s0, should be system_u:object_r:httpd_sys_content_t:s0
* **é…ç½® PHP-FPM çš„ SELinux 上下文信æ¯**
PHP-FPM 所默认的执行域åŒæ ·æ˜¯ :code:`httpd_t` ,上述类似的ä¸å†è¯´æ˜Žã€‚ä¸è¿‡åœ¨è¿™é‡Œæœ‰ä¸€ä¸ªéœ€æ±‚是,在 web 应用è¿è¡Œçš„过程ä¸ï¼Œéœ€è¦å’Œæ•°æ®åº“进行通讯,如果数æ®åº“有监å¬ç€çš„ unix socket 文件的è¯ï¼Œé‚£ä¹ˆç›´æŽ¥è®¾ç½®å¥½æ”¹æ–‡ä»¶çš„ SELinux æƒé™å°±å¯ä»¥è®© PHP-FPM æ¥é€šè®¯äº†ï¼Œå¯å¦‚果是监å¬çš„ tcp socket çš„è¯ï¼Œé‚£ä¹ˆå°±ä¾èµ– SELinux çš„å¦ä¸€ä¸ªå±žæ€§ï¼Œå¸ƒå°”值。布尔值的设定å…许在è¿è¡Œæ—¶ä¿®æ”¹éƒ¨åˆ† SELinux ç–略,而ä¸éœ€è¦ä»»ä½• SELinux ç–略的书写知识(那我的ç†è§£å°±æ˜¯è¿™äº›ä¸ªå±žæ€§æ‰€æŽ§åˆ¶çš„æƒé™åœ¨æ²¡æœ‰å¸ƒå°”值的情况下åªèƒ½é€šè¿‡ä¿®æ”¹ SELinux ç–ç•¥æ¥ä¿®æ”¹è€Œä¸æ˜¯ç®€å•é…ç½®å‡ ä¸‹å°±è¡Œçš„äº†ï¼‰ã€‚æŸ¥çœ‹å¸ƒå°”å€¼å¯ä»¥ä½¿ç”¨å¦‚下命令:
.. code-block:: shell-session
# getsebool -a | grep <pattern or str>
还有一个命令å¯ä»¥å¾ˆæ–¹ä¾¿çš„查看对应布尔值的说明:
.. code-block:: shell-session
# sepolicy booleans -a | grep httpd_can
httpd_can_check_spam=_("Allow http daemon to check spam")
httpd_can_connect_ftp=_("Allow httpd to act as a FTP client connecting to the ftp port and ephemeral ports")
httpd_can_connect_ldap=_("Allow httpd to connect to the ldap port")
...
# sepolicy booleans -b httpd_can_network_connect
httpd_can_network_connect=_("Allow HTTPD scripts and modules to connect to the network using TCP.")
è¿™æ ·å就一目了然了,以下命令用于设置布尔值:
.. code-block:: shell-session
# setsebool -P httpd_can_network_connect on
:code:`-P` 选项是对其进行æŒä¹…化å˜å‚¨åˆ°ç¡¬ç›˜ä¸Šçš„,ä¸ç„¶é‡å¯åŽè®¾ç½®å°±å¤±æ•ˆäº†ã€‚è¿™å‡ ä¸ªå‘½ä»¤çš„é€‰é¡¹éƒ½å¾ˆå°‘ï¼Œ man 一下就å¯ä»¥çœ‹å¾—很清楚。
* **查错**
一次性å¯èƒ½ä¸ä¼šå®Œå…¨é…ç½®æ£ç¡®ä¸”æ— é—æ¼ï¼Œé‚£ä¹ˆæŸ¥çœ‹ SELinux 的审计日志就éžå¸¸é‡è¦äº†ã€‚
CentOS 7 下默认是有è¿è¡Œ auditd 的,所以一般而言å¯ä»¥ä½¿ç”¨å¦‚下命令æ¥æŸ¥çœ‹æœ‰çš„报错:
.. code-block:: bash
ausearch -i -m AVC,USER_AVC,SELINUX_ERR -ts today
其日志文件的ä½ç½®é»˜è®¤ä¸º :code:`/var/log/audit/audit.log` ,而关于其å„å—段的å«ä¹‰ï¼Œå¯ä»¥çœ‹è¿™ç¯‡æ–‡ç« `UNDERSTANDING AUDIT LOG FILES`_ 。
还有一个命令是 :code:`audit2why` å¯ä»¥æ–¹ä¾¿çš„把拒ç»æ—¥å¿—ä¿¡æ¯è½¬åŒ–ä¸ºæ›´æ˜“è¯»çš„æ ¼å¼ã€‚
* 总结: 通过上述的å„ç§å·¥å…·è¿›è¡Œç»„åˆé‡å¤ï¼Œå°±å¯ä»¥å®Œæˆå®žçŽ°ç›®çš„的所有设置。所以å•å°±é…置本身而言, SELinux 还是比较简å•çš„,但是如果å„ç§æœåŠ¡ä¸€å¤šï¼ŒåŠŸèƒ½ä¸€å¤æ‚,所需è¦è€ƒè™‘的属性,文件扩展属性,å„ç§åŸŸä¹‹é—´çš„è”系就会使é…ç½® SELinux å˜å¾—å¤æ‚。那么在ä¸è€ƒè™‘编写 SELinux ç–略而仅仅是实用现有ç–ç•¥çš„æƒ…å†µä¸‹ï¼ŒæŽŒæ¡ SELinux 更多的就是é ç»éªŒç§¯ç´¯äº†ã€‚
而更多的é…ç½®/说明/例å,比如é™åˆ¶ä¸Žéžé™åˆ¶ç”¨æˆ·ï¼Œ :code:`file_t` å’Œ :code:`default_t` ,文件系统挂载é…置,文件å过渡,ç¦ç”¨ ptrace(), sVirt ç‰ç‰å¾ˆå¤šå†…容,å¯ä»¥çœ‹æœ¬æ–‡æœ€å¼€å§‹æåˆ°çš„é‚£ç¯‡æ–‡ç« ï¼Œæˆ–è€…å…¶å®ƒæ›´æ·±å…¥æè¿°çš„æ–‡ç« ã€‚
以上。
.. [1] Linux 下的自主访问控制就是平常最基本的对文件(夹)进行设置用户å/组以åŠç›¸åº”çš„ :code:`wrxst` æƒé™ï¼Œç„¶åŽä»¥ç”¨æˆ·èº«ä»½æ¥æ‰§è¡Œï¼Œè¿™æ ·å的一ç§è®¿é—®æŽ§åˆ¶ç®¡ç†ç®€å•ä½†å®‰å…¨ç³»æ•°ä¸é«˜ï¼Œä¸€æ—¦èŽ·å–æŸä¸€ä¸ªç”¨æˆ·çš„æƒé™å°±å¯ä»¥åšè¯¥ç”¨æˆ·èƒ½åšçš„任何事情,还å¯ä»¥è¾ƒä¸ºç®€å•åœ°è¿›è¡Œææƒæ”»å‡»ç‰ã€‚
.. _`SELinux User's and Administrator's Guide`: https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/index.html
.. _`本人整ç†çš„工具列表`: https://gist.github.com/bekcpear/590580d46bf739d3a58675212a2e7316
.. _`Google Books 上`: https://books.google.com/books?id=E8_cDgAAQBAJ&pg=PA70&dq=%22semanage+login+-l%22+Service&hl=en&sa=X&ved=0ahUKEwjN4LWN883UAhUP5WMKHZFrCK0Q6AEINTAC#v=onepage&q=%22semanage%20login%20-l%22%20Service&f=false
.. _`æœ‰ä¸€ç¯‡æ–‡ç« `: /build_nextcloud_service_on_centos_with_selinux.html#selinux-nextcloud
.. _`UNDERSTANDING AUDIT LOG FILES`: https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Understanding_Audit_Log_Files.html
.. _`SELinux User's and Administrator's Guide ç¬¬äºŒç« èŠ‚ SELINUX CONTEXTS 的部分内容`: https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/chap-Security-Enhanced_Linux-SELinux_Contexts.html
.. _`Creative Commons Attribution-ShareAlike 3.0 Unported License`: http://creativecommons.org/licenses/by-sa/3.0/