首页 > 代码库 > SELinux

SELinux

 

(注:以下内容转自鸟哥的私房菜)

 

[root@www ~]# ls -Z
drwxr-xr-x root root root:object_r:user_home_t Desktop
-rw-r--r-- root root root:object_r:user_home_t install.log
-rw-r--r-- root root root:object_r:user_home_t install.log.syslog
# 上述特殊字体的部分,就是安全性本文的内容!

如上所示,安全性本文主要用冒号分为三个栏位,这三个栏位的意义为:

Identify:role:type
身份识别:角色:类型

那你怎么知道目前的 SELinux 模式呢?就透过 getenforce 吧!

 

[root@www ~]# getenforce
Enforcing <==诺!就显示出目前的模式为 Enforcing 囉!

另外,我们又如何知道 SELinux 的政策 (Policy) 为何呢?这时可以使用 sestatus 来观察:

 

[root@www ~]# sestatus [-vb]
选项与参数:-v :检查列于 /etc/sestatus.conf 内的档桉与程序的安全性本文内容;-b :将目前政策的规则布林值列出,亦即某些规则 (rule) 是否要启动 (0/1) 之意;

范例一:列出目前的 SELinux 使用哪个政策 (Policy)?
[root@www ~]# sestatus
SELinux status: enabled <==是否启动 SELinux
SELinuxfs mount: /selinux <==SELinux 的相关档桉资料挂载点
Current mode: enforcing <==目前的模式
Mode from config file: enforcing <==设定档指定的模式
Policy version: 21
Policy from config file: targeted <==目前的政策为何?

如上所示,目前是启动的,而且是 Enforcing 模式,而由设定档查询得知亦为 Enforcing 模式。 此外,目前的预设政策为 targeted 这一个。你应该要有疑问的是, SELinux 的设定档是哪个档桉啊? 其实就是 /etc/selinux/config 这个档桉喔!我们来看看内容:

 

[root@www ~]# vi /etc/selinux/config
SELINUX=enforcing <==调整 enforcing|disabled|permissive
SELINUXTYPE=targeted <==目前仅有 targeted 与 strict

SELinux 的启动与关闭

 

[root@www ~]# vi /boot/grub/menu.lst
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.18-92.el5)
root (hd0,0)
kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet selinux=0
initrd /initrd-2.6.18-92.el5.img
# 如果要启动 SELinux ,则不可以出现 selinux=0 的字样在 kernel 后面!

 

[root@www ~]# setenforce [0|1]
选项与参数:0 :转成 permissive 宽容模式;1 :转成 Enforcing 强制模式

范例一:将 SELinux 在 Enforcing 与 permissive 之间切换与观察
[root@www ~]# setenforce 0
[root@www ~]# getenforce
Permissive
[root@www ~]# setenforce 1
[root@www ~]# getenforce
Enforcing

重设 SELinux 安全性本文

既然安全性本文是错的,那么就将他改回来即可嘛!怎么修改呢?可以透过两个指令喔!首先我们使用 chcon 来处理:

 

[root@www ~]# chcon [-R] [-t type] [-u user] [-r role] 档桉
[root@www ~]# chcon [-R] --reference=范例档 档桉
选项与参数:-R :连同该目录下的次目录也同时修改;-t :后面接安全性本文的类型栏位!例如 httpd_sys_content_t ;-u :后面接身份识别,例如 system_u;-r :后面街角色,例如 system_r;--reference=范例档:拿某个档桉当范例来修改后续接的档桉的类型!

范例一:将刚刚的 index.html 类型改为 httpd_sys_content_t 的类型
[root@www ~]# chcon -t httpd_sys_content_t /var/www/html/index.html
[root@www ~]# ll -Z /var/www/html/index.html
-rw-r--r-- root root root:object_r:httpd_sys_content_t /var/www/html/index.html
# 瞧!这样就改回来啦!

范例二:以 /etc/passwd 为依据,将 index.html 修改成该类型
[root@www ~]# ll -Z /etc/passwd
-rw-r--r-- root root system_u:object_r:etc_t /etc/passwd

[root@www ~]# chcon --reference=/etc/passwd /var/www/html/index.html
[root@www ~]# ll -Z /var/www/html/index.html
-rw-r--r-- root root root:object_r:etc_t /var/www/html/index.html
# 看看!是否与上面的 /etc/passwd 相同了!不过,这又是错误的安全性本文!# 先不要急着修改!我们来进行底下的另外一个指令处置看看!

chcon 是透过直接指定的方式来处理安全性本文的类型资料。那我们知道其实系统预设的目录都有特殊的 SELinux 安全性本文, 举例来说, /var/www/html 原本就是 httpd 可以读取的目录嘛!既然如此,那有没有可以使用预设的安全性本文来还原的方式? 有的,那就是 restorecon 这玩意儿:

 

[root@www ~]# restorecon [-Rv] 档桉或目录
选项与参数:-R :连同次目录一起修改;-v :将过程显示到萤幕上

范例一:将刚刚错误的 index.html 以预设的安全性本文改正过来
[root@www ~]# restorecon -Rv /var/www/html/index.html
restorecon reset /var/www/html/index.html context system_u:object_r:etc_t:s0->
system_u:object_r:httpd_sys_content_t:s0
# 上面这两行其实是同一行喔!表示将 index.html 由 etc_t 改为 httpd_sys_content_t

然后回到刚刚图 5.4.2 给他重读一下,嘿嘿!又可以看到正确的内容啦!这个过程完全没有动到 rwx 权限, 因为该权限本来就是对的!而错的部分是在于 SELinux 的安全性本文当中那个类型 (type) 设定错误! 而设定错误的原因很可能是因为该档桉由其他位置複製或移动过来所导致的!因此, 你得要善用 restorecon 以及 chcon 来处理这方面的问题喔!

etroubleshoot –> 错误讯息写入 /var/log/messages

几乎所有 SELinux 相关的程式都会以 se 为开头,这个服务也是以 se 为开头!而 troubleshoot 大家都知道是错误克服, 因此这个 setroubleshoot 自然就得要启动他啦!这个服务会将关于 SELinux 的错误讯息与克服方法记录到 /var/log/messages 裡头,所以你一定得要启动这个服务才好。那如何在开机的时候就启动 setroubleshoot 呢?这样处理先:

 

[root@www ~]# chkconfig --list setroubleshoot
setroubleshoot 0:off 1:off 2:off 3:on 4:on 5:on 6:off
# 我们的 Linux 运作模式是在 3 或 5 号,因此这两个要 on 即可。

[root@www ~]# chkconfig setroubleshoot on
# 关于 chkconfig 我们会在后面章节介绍, --list 是列出目前的执行等级是否有启动,# 如果加上 on ,则是在开机时启动,若为 off 则开机时不启动。

这支服务预设几乎都会启动啦!除非你看到 3:off 或 5:off 时,才需要以『 chkconfig setroubleshoot on 』 去设定一下。那么如果有发生错误时,讯息像什么呢?我们刚刚不是以浏览器浏览 index.html 并导致错误吗? 那就将该错误捉来瞧瞧!

 

[root@www ~]# cat /var/log/messages | grep setroubleshoot
Mar 23 17:18:44 www setroubleshoot: SELinux is preventing the httpd from using
potentially mislabeled files (/var/www/html/index.html). For complete SELinux
messages. run sealert -l 6c028f77-ddb6-4515-91f4-4e3e719994d4

上面的错误讯息可是同一行喔!大纲说的是『SElinux 被用来避免 httpd 读取到错误的安全性本文, 想要查阅完整的资料,请执行 sealert -l 6c02…』没错!你注意到了!重点就是 sealert -l 啦! 上面提供的资讯并不完整,想要更完整的说明得要靠 sealert 配合侦测到的错误代码来处理。 实际处理后会像这样:

 

[root@www ~]# sealert -l 6c028f77-ddb6-4515-91f4-4e3e719994d4
Summary:

SELinux is preventing the httpd from using potentially mislabeled files
(/var/www/html/index.html). <==就是刚刚 /var/log/messages 的讯息

Detailed Description: <==底下是更完整的描述!要看!

SELinux has denied httpd access to potentially mislabeled file(s)
(/var/www/html/index.html). This means that SELinux will not allow httpd to use
these files. It is common for users to edit files in their home directory or tmp
directories and then move (mv) them to system directories. The problem is that
the files end up with the wrong file context which confined applications are not
allowed to access.

Allowing Access: <==若要允许存取,你需要进行的动作!

If you want httpd to access this files, you need to relabel them using
restorecon -v ‘/var/www/html/index.html‘. You might want to relabel the entire
directory using restorecon -R -v ‘/var/www/html‘.
....(底下省略)....

重点就是上面特殊字体显示的地方!你只要照着『Allowing Access』裡面的提示去进行处理, 就能够完成你的 SELinux 类型设定了!比对刚刚我们上个小节提到的 restorecon 与 chcon 你就能够知道, setroubleshoot 提供的讯息有多有效了吧!

* auditd –> 详细资料写入 /var/log/audit/audit.log

audit 是稽核的意思,这个 auditd 会将 SELinux 发生的错误资讯写入 /var/log/audit/audit.log 中! 与上个服务相同的,你最好在开机时就设定这服务为启动的模式,因此可以照样造句:

 

[root@www ~]# chkconfig --list auditd
auditd 0:off 1:off 2:on 3:on 4:on 5:on 6:off

[root@www ~]# chkconfig auditd on
# 若 3:off 及 5:off 时,才需要进行!

与 setroubleshoot 不同的是, auditd 会将许多的 SELinux 资讯都记录下来,不只是错误讯息而已, 因此登录档 /var/log/audit/audit.log 非常的庞大!要直接到这档桉裡面去搜寻资料是挺累人的~ 还好,SELinux 有提供一个 audit2why 的指令来让我们查询错误讯息的回报呢!那么这个指令如何使用呢? 可以这样用的:

 

[root@www ~]# audit2why < /var/log/audit/audit.log
# 意思是,将登录档的内容读进来分析,并输出分析的结果!结果有点像这样:
type=AVC msg=audit(1237799959.349:355): avc: denied { getattr } for pid=24094
comm="httpd" path="/var/www/html/index.html" dev=hda2 ino=654685 scontext=root:s
ystem_r:httpd_t:s0 tcontext=root:object_r:user_home_t:s0 tclass=file
Was caused by:
Missing or disabled TE allow rule.
Allow rules may exist but be disabled by boolean settings; check boolean
settings.
You can see the necessary allow rules by running audit2allow with this
audit message as input.

audit2why 的用法与输出结果如上,比较有趣的是那个 AVC ,AVC 是 access vector cache 的缩写, 目的是记录所有与 SELinux 有关的存取统计资料。输出的资讯当中,会有谈到产生错误的问题为何,如上表特殊字体部分, 你会发现错误讯息主要告知 type 不符,所以导致错误的发生啊!不过,就鸟哥来看,我个人觉得 setroubleshoot 比较好用呢! 这两个好东西都可以帮助你解决 SELinux 的错误,因此,请务必至少要学会其中一项错误分析的方法喔!

政策查阅

CentOS 5.x 预设使使用 targeted 政策,那么这个政策提供多少相关的规则呢?此时可以透过 seinfo 来查询喔!

 

[root@www ~]# seinfo [-Atrub]
选项与参数:-A :列出 SELinux 的状态、规则布林值、身份识别、角色、类别等所有资讯-t :列出 SELinux 的所有类别 (type) 种类-r :列出 SELinux 的所有角色 (role) 种类-u :列出 SELinux 的所有身份识别 (user) 种类-b :列出所有规则的种类 (布林值)

范例一:列出 SELinux 在此政策下的统计状态
[root@www ~]# seinfo
Statistics for policy file: /etc/selinux/targeted/policy/policy.21
Policy Version & Type: v.21 (binary, MLS) <==列出政策所在档与版本

Classes: 61 Permissions: 220
Types: 1521 Attributes: 155
Users: 3 Roles: 6
Booleans: 213 Cond. Expr.: 190
Sensitivities: 1 Categories: 1024
Allow: 86561 Neverallow: 0
Auditallow: 34 Dontaudit: 5460
Role allow: 5 Role trans: 0
....(底下省略)....# 从上面我们可以看到这个政策是 targeted ,此政策的安全性本文类别有 1521 个;# 而针对网路服务的规则 (Booleans) 共制订了 213 条规则!

范例二:列出与 httpd 有关的规则 (booleans) 有哪些?
[root@www ~]# seinfo -b | grep httpd
Rule loading disabled
allow_httpd_mod_auth_pam
allow_httpd_bugzilla_script_anon_write
httpd_enable_ftp_server
....(底下省略)....# 你可以看到,有非常多的与 httpd 有关的规则订定呢!

从上面我们可以看到与 httpd 有关的布林值,同样的,如果你想要找到有 httpd 字样的安全性本文类别时, 就可以使用『 seinfo -t | grep httpd 』来查询了!如果查询到相关的类别或者是布林值后,想要知道详细的规则时, 就得要使用 sesearch 这个指令了!

 

[root@www ~]# sesearch [-a] [-s 主体类别] [-t 目标类别] [-b 布林值]
选项与参数:-a :列出该类别或布林值的所有相关资讯-t :后面还要接类别,例如 -t httpd_t-b :后面还要接布林值的规则,例如 -b httpd_enable_ftp_server

范例一:找出目标档桉资源类别为 httpd_sys_content_t 的有关资讯
[root@www ~]# sesearch -a -t httpd_sys_content_t
Found 74 av rules:
allow readahead_t httpd_sys_content_t : file { ioctl read getattr lock };
allow readahead_t httpd_sys_content_t : dir { ioctl read getattr lock search };
....(底下省略)....# 『 allow 主体程序安全性本文类别 目标档桉安全性本文类别 』# 如上,说明这个类别可以被那个主题程序的类别所读取,以及目标档桉资源的格式。

范例二:找出主体程序为 httpd_t 且目标档桉类别为 httpd 相关的所有资讯
[root@www ~]# sesearch -s httpd_t -t httpd_* -a
Found 163 av rules:
....(中间省略)....
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock };
allow httpd_t httpd_sys_content_t : dir { ioctl read getattr lock search };
allow httpd_t httpd_sys_content_t : lnk_file { ioctl read getattr lock };
....(后面省略)....# 从上面的资料就可以看出当程序为 httpd_t 这个类别,是可以读取 # httpd_sys_content_t 的!

你可以很轻易的查询到某个主体程序 (subject) 可以读取的目标档桉资源 (Object) , 从我们上面的练习,我们也可以很轻鬆的就知道,为何 httpd_t 可以读取 httpd_sys_content_t 囉! 那如果是布林值呢?裡面又规范了什么?让我们来看看先:

范例三:我知道有个布林值为 httpd_enable_homedirs ,请问该布林值规范多少规则?

范例三:我知道有个布林值为 httpd_enable_homedirs ,请问该布林值规范多少规则?
[root@www ~]# sesearch -b httpd_enable_homedirs -a
Found 21 av rules:
allow httpd_t user_home_dir_t : dir { getattr search };
allow httpd_t cifs_t : file { ioctl read getattr lock };
allow httpd_t cifs_t : dir { ioctl read getattr lock search };
....(后面省略)....

从这个布林值的设定我们可以看到裡面规范了非常多的主体程序与目标档桉资源的放行与否! 所以你知道了,实际规范这些规则的,就是布林值的项目啦!那也就是我们之前所说的一堆规则是也! 你的主体程序能否对某些目标档桉进行存取,与这个布林值非常有关係喔!因为布林值可以将规则设定为启动 (1) 或者是关闭 (0) 啦!

由 seinfo 与 sesearch 的输出资讯,我们也会得到实际的政策资料都是放置到 /etc/selinux/targeted/policy/ 底下, 事实上,所有与 targetd 相关的资讯都是放置到 /etc/selinux/targeted 裡面的呢!包括安全性本文相关的资讯。 这部分等一下谈到安全性本文的预设值修改时,我们再来讨论。

布林值的查询与修改

上面我们透过 sesearch 知道了,其实 Subject 与 Object 能否有存取的权限,是与布林值有关的, 那么系统有多少布林值可以透过 seinfo -b 来查询,但,每个布林值是启动的还是关闭的呢?这就来查询看看吧:

 

[root@www ~]# getsebool [-a] [布林值条款]
选项与参数:-a :列出目前系统上面的所有布林值条款设定为开启或关闭值

范例一:查询本系统内所有的布林值设定状况
[root@www ~]# getsebool -a
NetworkManager_disable_trans --> off
allow_console_login --> off
allow_cvs_read_shadow --> off
allow_daemons_dump_core --> on
....(底下省略)....# 您瞧!这就告诉你目前的布林值状态囉!

那么如果查询到某个布林值,并且以 sesearch 知道该布林值的用途后,想要关闭或启动他,又该如何处置?

 

[root@www ~]# setsebool [-P] 布林值=[0|1]
选项与参数:-P :直接将设定值写入设定档,该设定资料未来会生效的!

范例一:查询 httpd_enable_homedirs 是否为关闭,若不为关闭,请关闭他!
[root@www ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> on <==结果是 on ,依题意给他关闭!

[root@www ~]# setsebool -P httpd_enable_homedirs=0
[root@www ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off

这个 setsebool 最好记得一定要加上 -P 的选项!因为这样才能将此设定写入设定档! 这是非常棒的工具组!你一定要知道如何使用 getsebool 与 setsebool 才行!

预设目录的安全性本文查询与修改

还记得我们在使用 restorecon 时谈到每个目录或档桉都会有预设的安全性本文吗? 会制订目录的安全性本文,是因为系统的一些服务所放置档桉的目录已经是确定的,当然有预设的安全性本文管理上较方便。 那你如何查询这些目录的预设安全性本文呢?就得要使用 semanage 囉!

 

[root@www ~]# semanage {login|user|port|interface|fcontext|translation} -l
[root@www ~]# semanage fcontext -{a|d|m} [-frst] file_spec
选项与参数:fcontext :主要用在安全性本文方面的用途, -l 为查询的意思;-a :增加的意思,你可以增加一些目录的预设安全性本文类型设定;-m :修改的意思;-d :删除的意思。

范例一:查询一下 /var/www/html 的预设安全性本文设定为何!
[root@www ~]# semanage fcontext -l
SELinux fcontext type Context
....(前面省略)....
/var/www(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
....(后面省略)....

从上面的说明,我们知道其实 semanage 可以处理非常多的任务,不过,在这个小节我们主要想瞭解的是每个目录的预设安全性本文。 如上面范例一所示,我们可以查询的到每个目录的安全性本文啦!而目录的设定可以使用正规表示法去指定一个范围。那么如果我们想要增加某些自订的目录的安全 性本文呢? 举例来说,我想要制订 /srv/samba 成为 public_content_t 的类型时,应该如何指定呢?

 

范例二:利用 semanage 设定 /srv/samba 目录的预设安全性本文为 public_content_t
[root@www ~]# mkdir /srv/samba
[root@www ~]# ll -Zd /srv/samba
drwxr-xr-x root root root:object_r:var_t /srv/samba
# 如上所示,预设的情况应该是 var_t 这个咚咚的!

[root@www ~]# semanage fcontext -l | grep ‘/srv‘
/srv/.* all files system_u:object_r:var_t:s0
/srv/([^/]*/)?ftp(/.*)? all files system_u:object_r:public_content_t:s0
/srv/([^/]*/)?www(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/srv/([^/]*/)?rsync(/.*)? all files system_u:object_r:public_content_t:s0
/srv/gallery2(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
/srv directory system_u:object_r:var_t:s0 <==看这裡!
# 上面则是预设的 /srv 底下的安全性本文资料,不过,并没有指定到 /srv/samba 啦

[root@www ~]# semanage fcontext -a -t public_content_t "/srv/samba(/.*)?"
[root@www ~]# semanage fcontext -l | grep ‘/srv/samba‘
/srv/samba(/.*)? all files system_u:object_r:public_content_t:s0

[root@www ~]# cat /etc/selinux/targeted/contexts/files/file_contexts.local
# This file is auto-generated by libsemanage
# Please use the semanage command to make changes
/srv/samba(/.*)? system_u:object_r:public_content_t:s0
# 其实就是写入这个档桉的囉! ^_^

[root@www ~]# restorecon -Rv /srv/samba* <==尝试恢复预设值
[root@www ~]# ll -Zd /srv/samba
drwxr-xr-x root root system_u:object_r:public_content_t /srv/samba/
# 有预设值,以后用 restorecon 来修改比较简单!

 

SELinux