我让 snmpd 在 /custom/location/myscript.sh 下执行一个脚本。如果我禁用 selinux,一切正常。如果我启用 selinux,它会停止工作,如果我执行 audit2why,我会看到以下内容:
type=AVC msg=audit(1371990300.064:23445): avc: denied { read open } for pid=21423 comm="snmpd" name="myscript.sh" dev=dm-0 ino=1046532 scontext=unconfined_u:system_r:snmpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
Was caused by:
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access.
type=AVC msg=audit(1371990313.066:23446): avc: denied { read open } for pid=21425 comm="snmpd" name="myscript.sh" dev=dm-0 ino=1046532 scontext=unconfined_u:system_r:snmpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
Was caused by:
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access.
如果我执行 ls -Z /custom/location,我会看到以下内容:
-rwxr-xr-x. root root unconfined_u:object_r:default_t:s0 myscript.sh
因此我需要对目录执行 chcon-R。我尝试过:
chcon -R -u unconfined_u -r system_r -t snmpd_t /custom/location
只会得到以下错误:
chcon: failed to change context of `myscript.sh' to `unconfined_u:system_r:snmpd_t:s0': Permission denied
我也尝试使用 audit2allow 创建自定义策略,但似乎不起作用。
我真的不想禁用 selinux。有人能帮助我了解如何允许 snmpd 读取 /custom/location 吗?
谢谢布拉德
由于输出太长,我截断了一些 - 但这是 ausearch 的结果:
----
time->Sun Jun 23 08:27:13 2013
type=SYSCALL msg=audit(1371990433.731:23453): arch=c000003e syscall=189 success=no
exit=-13 a0=11760e0 a1=3e50616319 a2=1178ef0 a3=21 items=0 ppid=20865 pid=21434 auid=0
uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3863 comm="chcon"
exe="/usr/bin/chcon" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=
(null)
type=AVC msg=audit(1371990433.731:23453): avc: denied { relabelto } for pid=21434
comm="chcon" name="scripts" dev=dm-0 ino=1046530
scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
tcontext=unconfined_u:system_r:snmpd_t:s0 tclass=dir
----
time->Sun Jun 23 08:27:24 2013
type=SYSCALL msg=audit(1371990444.075:23454): arch=c000003e syscall=59 success=no
exit=-13 a0=7fdb8933c6d0 a1=7fdb8933c3a0 a2=7fff16ef1790 a3=1f items=0 ppid=18001
pid=21435 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none)
ses=3765 comm="snmpd" exe="/usr/sbin/snmpd" subj=unconfined_u:system_r:snmpd_t:s0 key=
(null)
type=AVC msg=audit(1371990444.075:23454): avc: denied { read open } for pid=21435
comm="snmpd" name="snmp.sh" dev=dm-0 ino=1046532
scontext=unconfined_u:system_r:snmpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0
tclass=file
----
答案1
首先,你可能根本不需要编写自定义模块。
首先,我会将脚本放在 SELinux 期望找到可执行文件的位置之一,并且仅当这不可能时,才使用audit2allow
(而不是audit2why
,它给出了人性化的消息,但在理解真正的问题方面用处不大)的输出,我才会分析 AVC 拒绝。
更改文件的安全上下文是一种特权操作,并且您无法获知尝试使用哪个用户执行该命令。使用root
。
但请注意,正确的做法不是对chcon
文件执行此操作,因为在系统重新标记后该文件不会保留,而是用来semanage
向路径添加安全上下文:
semanage fcontext -a type_enforcement "/path/expression(/.*)?"
检查输出semanage fcontext -l | less
以获得关于路径表达式应该是什么样子的第一印象。
为了更深入地了解该问题,您需要知道snmpd
守护进程可以转换到哪些上下文。您可以在seinfo
和 sesearch
手册页中找到帮助。
的上游源代码refpolicy
可以检查以了解带标签文件读取的可执行文件的正确标签是什么snmpd_t
。更好的办法可能是使用包管理器下载与操作系统中使用的策略版本匹配的源策略。
这是了解模块中涉及的不同文件(尤其是 5b)的功能的良好资源。
首先检查为此模块定义的文件上下文(这semanage fcontext -l | grep snmp
或多或少是你使用时会找到的内容):
# cat refpolicy/policy/modules/contrib/snmp.fc
/etc/rc\.d/init\.d/((snmpd)|(snmptrapd)) -- gen_context(system_u:object_r:snmpd_initrc_exec_t,s0)
/usr/sbin/snmptrap -- gen_context(system_u:object_r:snmpd_exec_t,s0)
/usr/sbin/snmptrapd -- gen_context(system_u:object_r:snmpd_exec_t,s0)
/usr/share/snmp/mibs/\.index -- gen_context(system_u:object_r:snmpd_var_lib_t,s0)
/var/agentx(/.*)? gen_context(system_u:object_r:snmpd_var_lib_t,s0)
/var/net-snmp(/.*) gen_context(system_u:object_r:snmpd_var_lib_t,s0)
/var/lib/net-snmp(/.*)? gen_context(system_u:object_r:snmpd_var_lib_t,s0)
/var/lib/snmp(/.*)? gen_context(system_u:object_r:snmpd_var_lib_t,s0)
/var/log/snmpd\.log.* -- gen_context(system_u:object_r:snmpd_log_t,s0)
/var/run/net-snmpd(/.*)? gen_context(system_u:object_r:snmpd_var_run_t,s0)
/var/run/snmpd(/.*)? gen_context(system_u:object_r:snmpd_var_run_t,s0)
/var/run/snmpd\.pid -- gen_context(system_u:object_r:snmpd_var_run_t,s0)
然后,这里定义的类型强制规则(片段):
# head -22 refpolicy/policy/modules/contrib/snmp.te
policy_module(snmp, 1.14.0)
########################################
#
# Declarations
#
type snmpd_t;
type snmpd_exec_t;
init_daemon_domain(snmpd_t, snmpd_exec_t)
type snmpd_initrc_exec_t;
init_script_file(snmpd_initrc_exec_t)
type snmpd_log_t;
logging_log_file(snmpd_log_t)
type snmpd_var_run_t;
files_pid_file(snmpd_var_run_t)
type snmpd_var_lib_t;
files_type(snmpd_var_lib_t)
最后,接口(snmp.if
),文件。
有了这些信息,你需要找出正确的上下文,以便snmpd
能够执行脚本,然后手动将上下文规则添加到可执行文件所在的路径。