SELinux 工具使用

setatus

查看 SELinux 状态

~# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Max kernel policy version:      28

或者使用 selinuxenabled。

selinuxenabled

~# selinuxenabled
~# echo $?
0

两个工具所属的包 policycoreutils 和 libselinux-utils 都是 RHEL/CentOS 的 minimal ISO 都默认安装的(SELinux 基础),因此在脚本中使用是比较安全的。

semodule

加载、禁用、启用、删除规则(策略)模块:

# 加载
~# semodule -i librados.pp
~# semodule -l | grep librados
librados        0.0.1
# 加载
~# semodule -i librados.pp
~# semodule -l | grep librados
librados        0.0.1
# 禁用,会在 /etc/selinux/targeted/modules/active/modules/ 中增加一个 xxx.pp.disabled 文件,
# 且 fc 定义的类型会从 /etc/selinux/targeted/modules/active/file_contexts 和 /etc/selinux/targeted/contexts/files/file_contexts 中删除
~# semodule -d librados
~# semodule -l | grep librados
librados        0.0.1   Disabled
# 启用
~# semodule -e librados
~# semodule -l | grep librados
librados        0.0.1
# 删除,会将 pp 文件从 /etc/selinux/targeted/modules/active/modules/ 中删除,
# 且 fc 定义的类型会从 /etc/selinux/targeted/modules/active/file_contexts 和 /etc/selinux/targeted/contexts/files/file_contexts 中删除
~# semodule -r librados
~# semodule -l | grep librados
~#

只要没有使用 -r, -d 对模块进行删除或者禁用处理,机器重启之后,模块会自动加载。一旦 -r 删除模块,不管重启机器与否,模块相关的信息就彻底消失了,而 -d 禁用模块,机器重启之后模块仍然是禁用状态。

matchpathcon

查询当前 file contexts 配置下指定文件或文件夹的默认 file context:

~# matchpathcon /var/run/ceph/ceph-client.cinder.18633.139917485152304.casok
/var/run/ceph/ceph-client.cinder.18633.139917485152304.casok    system_u:object_r:librados_var_run_t:s0
~# matchpathcon -V /var/run/ceph/ceph-client.cinder.18633.139917485152304.casok
/var/run/ceph/ceph-client.cinder.18633.139917485152304.casok has context unconfined_u:object_r:ceph_var_run_t:s0, should be system_u:object_r:librados_var_run_t:s0

chcon

临时改变文件/文件夹的 SELinux 属性,注意设置未定义的 file context type 会报错:

~# chcon -t ceph_var_run_t /var/run/ceph
chcon: failed to change context of '/var/run/ceph' to 'system_u:object_r:ceph_var_run_t:s0': Invalid argument
~# chcon -t var_run_t /var/run/ceph

加载 ceph.pp:

~# semodule -i ceph.pp
~# semodule -l | grep ceph
ceph    1.1.1

查看 file context 的变化:

~# grep ceph /etc/selinux/targeted/modules/active/file_contexts
/var/ceph(/.*)?     system_u:object_r:ceph_var_lib_t:s0
/var/log/ceph(/.*)?     system_u:object_r:ceph_log_t:s0
/var/run/ceph(/.*)?     system_u:object_r:ceph_var_run_t:s0
/var/log/radosgw(/.*)?  system_u:object_r:ceph_log_t:s0
/usr/bin/radosgw        --      system_u:object_r:ceph_exec_t:s0
/usr/bin/ceph-mgr       --      system_u:object_r:ceph_exec_t:s0
/usr/bin/ceph-mon       --      system_u:object_r:ceph_exec_t:s0
/usr/bin/ceph-mds       --      system_u:object_r:ceph_exec_t:s0
/usr/bin/ceph-osd       --      system_u:object_r:ceph_exec_t:s0
/usr/bin/ceph-fuse      --      system_u:object_r:ceph_exec_t:s0
/etc/rc\.d/init\.d/ceph --      system_u:object_r:ceph_initrc_exec_t:s0
/etc/rc\.d/init\.d/radosgw      --      system_u:object_r:ceph_initrc_exec_t:s0

~# diff /etc/selinux/targeted/modules/active/file_contexts /etc/selinux/targeted/contexts/files/file_contexts
~#
~# semodule -d ceph
~# grep ceph /etc/selinux/targeted/modules/active/file_contexts
~#
~# semodule -e ceph

加载 ceph 的规则模块后,就可以使用 chcon 顺利的改变 /var/run/ceph 目录的标签了:

~# ll /var/run/ceph -Zd
drwxrwxrwx. ceph ceph system_u:object_r:var_run_t:s0   /var/run/ceph
~# chcon -t ceph_var_run_t /var/run/ceph
~# ll /var/run/ceph -Zd
drwxrwxrwx. ceph ceph system_u:object_r:ceph_var_run_t:s0 /var/run/ceph

restorecon

恢复文件在 file contexts 配置中定义的 type,如果指定 -F 选项则恢复 user, role, type, level 所有的 SELinux context。

首先使用 chcon 将 /var/run/ceph 临时改回 var_run_t type,由于已经加载的 ceph.pp 模块中 file context 已经定义了 ceph_var_run_t 类型,因此使用 restorecon 之后会恢复为 ceph_var_run_t type:

~# chcon -t var_run_t /var/run/ceph
~# ll /var/run/ceph -Zd
drwxrwxrwx. ceph ceph system_u:object_r:var_run_t:s0   /var/run/ceph
~# restorecon -F /var/run/ceph
~# ll /var/run/ceph -Zd
drwxrwxrwx. ceph ceph system_u:object_r:ceph_var_run_t:s0 /var/run/ceph

禁用、删除 ceph 模块之后,type 会变成 unlabeled_t,然后 restorecon 会恢复成默认类型 var_run_t

~# semodule -d ceph
~# ll /var/run/ceph -Zd
drwxrwxrwx. ceph ceph system_u:object_r:unlabeled_t:s0 /var/run/ceph
~# restorecon /var/run/ceph
~# ll /var/run/ceph -Zd
drwxrwxrwx. ceph ceph system_u:object_r:var_run_t:s0   /var/run/ceph

semanage

综合性工具,常用的子命令是 module 、fcontext 以及 port。

semanage module,功能与 semodule 基本类似;
semanage fcontext,操作 file context,可以查询、增加、删除、修改 file type 规则,但要求该 file type 是已定义的 file type(即不能新增 file type) ,修改的规则保存在 /etc/selinux/targeted/contexts/files/file_contexts.local 中:

~# semanage fcontext -l | grep librados
/var/run/ceph/.*\.casok                            all files          system_u:object_r:librados_var_run_t:s0

~# semanage fcontext --add --type librados_var_run_t -- '/var/run/xxx(/.*\.asok)?'
~# semanage fcontext -l | grep librados
/var/run/ceph/.*\.casok                            all files          system_u:object_r:librados_var_run_t:s0
/var/run/xxx(/.*\.asok)?                           all files          system_u:object_r:librados_var_run_t:s0

~# semanage fcontext --add --type librados_var_run_t -f s '/var/run/abc(/.*\.asok)?'
~# semanage fcontext -l | grep librados
/var/run/ceph/.*\.casok                            all files          system_u:object_r:librados_var_run_t:s0
/var/run/xxx(/.*\.asok)?                           all files          system_u:object_r:librados_var_run_t:s0
/var/run/abc(/.*\.asok)?                           socket             system_u:object_r:librados_var_run_t:s0

~# semanage fcontext --delete -t librados_var_run_t -f s '/var/run/abc(/.*\.asok)?'
~# semanage fcontext -l | grep librados
/var/run/ceph/.*\.casok                            all files          system_u:object_r:librados_var_run_t:s0
/var/run/xxx(/.*\.asok)?                           all files          system_u:object_r:librados_var_run_t:s0

~# semanage fcontext -d -t librados_var_run_t -- '/var/run/xxx(/.*\.asok)?'
~# semanage fcontext -l | grep librados
/var/run/ceph/.*\.casok                            all files          system_u:object_r:librados_var_run_t:s0

semanage port,操作 socket 端口,可以查询、增加、删除、修改端口 type 定义,但要求该端口 type 是已定义的 file type(即不能新增端口 type) :

~# semanage port -l | grep mysqld
mysqld_port_t                  tcp      1186, 3306, 63132-63164
# semanage port -a -t mysqld_port_t -p tcp 3333
~# semanage port -l | grep mysqld
mysqld_port_t                  tcp      3333, 1186, 3306, 63132-63164

~# semanage port -d -t mysqld_port_t -p tcp 3333
~# semanage port -l | grep mysqld
mysqld_port_t                  tcp      1186, 3306, 63132-63164

~# seinfo -t | grep nmbd_port_t
   nmbd_port_t
~# seinfo -tnmbd_port_t -x
   nmbd_port_t
      port_type
      reserved_port_type
      defined_port_type
~# semanage port -l | grep nmbd_port_t
nmbd_port_t                    udp      137, 138

seinfo

查询所有定义的 type, attribute, role, user 等(支持过滤条件):

~# seinfo --type | grep ceph
   ceph_var_lib_t
   ceph_var_run_t
   ceph_log_t
   ceph_initrc_exec_t
   ceph_t
   ceph_exec_t
~# seinfo --type=ceph_t --user=system_u | grep ceph
   ceph_t
~# seinfo --type=ceph_var_run_t -x
   ceph_var_run_t
      file_type
      non_security_file_type
      non_auth_file_type
      pidfile

sesearch

查找符合查询条件的规则:

~# sesearch --allow --source virtd_t | grep rados
   allow virtd_t librados_var_run_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow virtd_t librados_var_run_t : sock_file { ioctl read write create getattr setattr lock append unlink link rename open } ;
~# sesearch --allow --target librados_var_run_t | grep rados
   allow virtd_t librados_var_run_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow virtd_t librados_var_run_t : sock_file { ioctl read write create getattr setattr lock append unlink link rename open } ;
   allow librados_var_run_t librados_var_run_t : filesystem associate ;
~# sesearch --allow --source virtd_t --target librados_var_run_t | grep rados
   allow virtd_t librados_var_run_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
   allow virtd_t librados_var_run_t : sock_file { ioctl read write create getattr setattr lock append unlink link rename open } ;

sedismod

使用 sedismod 可以查看编译后的二进制规则模块(即 pp 文件)。

首先分析文件类型(注意自己手工编译后的 pp 文件是裸的 pp 文件,但加载之后的 pp 文件是 bzip2 格式的压缩文件),并得到最终的 pp 文件:

~# file /etc/selinux/targeted/modules/active/modules/glance.pp
/etc/selinux/targeted/modules/active/modules/glance.pp: bzip2 compressed data, block size = 900k
~# bzcat glance.pp > glance.d
~# file glance.d
glance.d: SE Linux modular policy version 1, 2 sections, mod version 17, MLS, module name glance\005

查看规则的具体信息:

~# sedismod glance.d
Reading policy...
libsepol.policydb_index_others: security: 0 users, 2 roles, 94 types, 4 bools
libsepol.policydb_index_others: security: 1 sens, 1024 cats
libsepol.policydb_index_others: security: 52 classes, 0 rules, 0 cond rules
libsepol.policydb_index_others: security: 0 users, 2 roles, 94 types, 4 bools
libsepol.policydb_index_others: security: 1 sens, 1024 cats
libsepol.policydb_index_others: security: 52 classes, 0 rules, 0 cond rules
Binary policy module file loaded.
Module name: glance
Module version: 1.1.0
...
Command ('m' for menu): 6
...
glance_domain [1]: attribute for types glance_registry_t, glance_api_t, glance_scrubber_t flags:0
...
Command ('m' for menu): 1
...
allow glance_domain [etc_t] : [dir] { getattr search open };
...

TIPS

  1. touch 之类的命令生成的 label 用户字段为 unconfined_u,需要注意下面这个原因:
Your command prompt is unconfined so when you touch a file then it gets created with that.
  1. 此外还要注意:

CentOS 从内核 3.10.0-693.21.1 开始 /etc/selinux/targeted 的目录结构有所变化,将原有的 /etc/selinux/targeted/modules/active/ 目录下的内容和原有的 /etc/selinux/targeted/active/ 目录合并,原有的 /etc/selinux/targeted/modules/ 目录及其子目录下不再有任何 有意义的内容,且以前的 bzip2 压缩的 .pp 文件变成了 bzip2 压缩 hll 文件,解压之后实质仍然是 sedismod 可以识别的策略文件。

注:CentOS 8 下 modules 目录已迁移至 /var/lib/selinux/targeted/active/

  1. socket 相关的规则通常与端口相关,即使定义了允许 connect 之类的规则,还需要关注允许的相应端口:
// selinux-policy/policy/modules/kernel/corenetwork.if.in

########################################
## <summary>
##	Connect TCP sockets to all ports > 32768.
## </summary>
## <param name="domain">
##	<summary>
##	Domain allowed access.
##	</summary>
## </param>
#
interface(`corenet_tcp_connect_all_ephemeral_ports',`
	gen_require(`
		attribute ephemeral_port_type;
	')

	allow $1 ephemeral_port_type:tcp_socket name_connect;
')

########################################
## <summary>
##	Connect TCP sockets to all ports.
## </summary>
## <desc>
##	<p>
##	Connect TCP sockets to all ports
##	</p>
##	<p>
##	Related interfaces:
##	</p>
##	<ul>
##		<li>corenet_all_recvfrom_unlabeled()</li>
##		<li>corenet_tcp_sendrecv_generic_if()</li>
##		<li>corenet_tcp_sendrecv_generic_node()</li>
##		<li>corenet_tcp_sendrecv_all_ports()</li>
##		<li>corenet_tcp_bind_all_ports()</li>
##	</ul>
##	<p>
##	Example client being able to connect to all ports over
##	generic nodes, without labeled networking:
##	</p>
##	<p>
##	allow myclient_t self:tcp_socket create_stream_socket_perms;
##	corenet_tcp_sendrecv_generic_if(myclient_t)
##	corenet_tcp_sendrecv_generic_node(myclient_t)
##	corenet_tcp_sendrecv_all_ports(myclient_t)
##	corenet_tcp_connect_all_ports(myclient_t)
##	corenet_all_recvfrom_unlabeled(myclient_t)
##	</p>
## </desc>
## <param name="domain">
##	<summary>
##	Domain allowed access.
##	</summary>
## </param>
## <infoflow type="write" weight="1"/>
#
interface(`corenet_tcp_connect_all_ports',`
	gen_require(`
		attribute port_type;
	')

	allow $1 port_type:tcp_socket name_connect;
')
// selinux-policy-contrib/glance.te

tunable_policy(`glance_api_can_network',`
	corenet_sendrecv_all_client_packets(glance_api_t)
	corenet_tcp_connect_all_ports(glance_api_t)
	corenet_tcp_sendrecv_all_ports(glance_api_t)
')
# getsebool glance_api_can_network
glance_api_can_network --> off
# setsebool -P glance_api_can_network 1
  1. 生成 man 手册页
$ sepolicy manpage -d glance_api_t
/tmp/glance_api_selinux.8
$ sepolicy manpage -d glance_api_t -p . -w
./glance_api_selinux.8
./RHEL7/glance_api.html
./index.html has been created
./RHEL7/RHEL7.html has been created
./style.css has been created
$ sepolicy manpage -a
/tmp/NetworkManager_selinux.8
/tmp/abrt_selinux.8
/tmp/abrt_dump_oops_selinux.8
/tmp/abrt_handle_event_selinux.8
...

参考资料

[1] 3 SELinux sestatus Command Output Explained with Examples

https://www.thegeekstuff.com/2017/06/selinux-sestatus/

[2] 15 SELinux chcon Command Examples to Change Security Context

https://www.thegeekstuff.com/2017/07/chcon-command-examples/

[3] 10 Linux restorecon Command Examples to Restore SELinux Context

https://www.thegeekstuff.com/2017/05/restorecon-examples/

[4] SELinux sets wrong context by default

https://www.centos.org/forums/viewtopic.php?t=52198


最后修改于 2019-01-18