我目前的理解是,您必须手动使用restorecon
以将所需的上下文应用于新创建的文件或目录,除非您对它从其父目录继承的上下文感到满意。
我想知道是否可以根据路径在创建时自动应用上下文,而无需运行restorecon
。
我谷歌了一下,发现这个帖子Dan Walsh 提到了在创建时更改上下文restorecond
的用法inotify
。他还指出了它的明显问题(竞争条件)。如果子目录不应从父目录继承其上下文,这是自动解决重新上下文问题的唯一方法吗?
一个问题是,它restorecond
似乎不能以与相同的方式处理条目/etc/selinux/targeted/contexts/files/file_contexts
,也就是说,没有正则表达式,并且它不能递归工作,因此/etc/selinux/restorecond.conf
不能包含类似
/var/www(/.*)?/logs(/.*)?
或者
/var/www/*
甚至
/var/www/*/logs
有办法解决这个问题吗?
编辑:
按照@Michael的回答,如果存在相应的规则,这应该可以在OOTB上运行,但事实并非如此:
# rm -rf /var/www/foo
# semanage fcontext -a -t httpd_log_t '/var/www/foo/logs'
# grep '/var/www.*logs' /etc/selinux/targeted/contexts/files/file_contexts*
/etc/selinux/targeted/contexts/files/file_contexts:/var/www(/.*)?/logs(/.*)? system_u:object_r:httpd_log_t:s0
/etc/selinux/targeted/contexts/files/file_contexts.local:/var/www/foo/logs system_u:object_r:httpd_log_t:s0
# matchpathcon /var/www/foo/logs
/var/www/foo/logs system_u:object_r:httpd_log_t:s0
# mkdir -p /var/www/foo/logs
# touch /var/www/foo/logs/quux
# ls -alZ /var/www/foo/logs*
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 .
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 ..
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 quux
# restorecon -vR /var/www/foo
restorecon reset /var/www/foo/logs context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:httpd_log_t:s0
restorecon reset /var/www/foo/logs/quux context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:httpd_log_t:s0
答案1
内核执行以下步骤来确定新创建的文件的文件类型。
- 策略中存在特定的文件转换规则。因此应用它。
- 使新创建的文件获取父目录的类型。
在大多数情况下,新文件会继承父目录类型。有时这并不理想——因此政策制定者可以根据谁在何处进行标记等条件创建规则,以便转换为另一种类型。
这是通过声明在策略中控制的type_transition
,尽管通常策略制定者会调用filetrans_pattern
宏。
在内核中,这些决定不是基于路径而是基于类型(尽管在较新的策略中存在一个小例外)。
规则通常是这样的;
type_transition httpd_t var_log_t:file httpd_var_log_t;
在此示例中,规则规定:如果执行文件创建的进程/用户是httpd_t
,且正在创建对象的目录是var_log_t
,且该对象被归类为file
,则新文件必须标记为httpd_var_log_t
。
当然,这有许多限制,一个很好的例子就是在 apache 中创建 .htaccess 文件的情况(在 /var/www/html 中)。在这个例子中,创建与父目录类型相同的文件类型的默认策略适用,但实际上该文件的正确类型不是httpd_sys_htacess_t
默认的httpd_sys_content_t
。
这是一个已知问题很多年了,最终通过允许政策制定者在政策中指定转换适用的文件名而得到解决——不幸的是,此功能在 EL6 中不可用。
在您的特定情况下——正如您所提到的,有一些涉及 restorecond 的解决方法。除此之外,您最好将数据分成不同类型的数据,将它们放在单独的子目录中,其中子目录具有充分标记的类型。如果这仍然不可能,并且 restorecond 也不可能——唯一的解决方案是在文件创建后对文件运行 restorecon 的后修复。
即使是“较新”的 filetrans 也存在问题,因为它最终不支持通配符或正则表达式,这严重限制了它对特定命名良好的文件(如 .htaccess)的功能。
就目前而言,还不存在像其正则表达式一样灵活的内核机制restorecon
来正确地标记文件。
答案2
Fedora 16 中解决了文件创建时正确标记的问题,其中有一个功能叫做文件名转换(尽管您也可以将其称为“命名文件转换”),其定义基本上表明:
借助文件名转换功能,策略编写者可以编写考虑文件名而不是文件路径的规则。这是文件路径的基本名称。由于内核在创建对象时知道包含目录的标签、创建对象的进程的标签和对象的名称。我们现在可以编写一条策略规则,规定如果 unconfined_t 进程在标记为 etc_t 的目录中创建名为 resolv.conf 的文件,则该文件应标记为 resolv.conf。
众所周知,对象在创建时被标记的方式可能会因创建该对象的过程的不同而有所不同(cp
对阵mv
就是一个很好的例子)。另外,标记对象的默认方式是通过继承:对象获取父目录的标签。
虽然这很方便,但并不总是正确的,系统管理员必须使用restorecon
+ restorecond
+ (的组合)手动纠正这种情况semanage fcontext -a -t
。
这就是 Name File Transitions 试图纠正的问题,通过让
[...] 政策制定者有能力通过在政策中编写一条规则来覆盖这一点,该规则规定,如果类型为 a_t 的进程在标有 b_t 的目录中创建了“文件”类的对象,则该对象将被创建为 c_t。
显然,自定义位置不存在命名文件转换。你可以找到已经存在的转换,例如:
# sesearch -ASCT -s unconfined_t | grep Found
...
Found XX named file transition filename_trans:
...
因此,为了解决您的问题,您需要事先知道哪个用户(SELinux 用户)将在哪里创建什么文件/目录,然后编写包括文件转换的自定义策略。我上面链接的 Fedora 项目 wiki 页面中有几个示例。
答案3
这不是问题,只是你从错误的方向去处理它。
如果你想要自己的文件上下文,只需使用 创建自己的文件上下文即可semanage fcontext
。做接受正则表达式。
这是一个常见的例子,用于重新定位 Apache 提供文件服务的目录:
semanage fcontext -a -t httpd_sys_content_t "/volume1/web(/.*)?"
请随意根据您的需要进行调整。