介绍
在SELinux 系列的第一部分中,我们了解了如何启用和禁用 SELinux 以及如何使用布尔值更改某些策略设置。在第二部分,我们将讨论文件和进程安全上下文。
为了刷新您对上一教程的记忆,文件安全上下文是一种类型,进程安全上下文是一个域。
注意 本教程中显示的命令、包和文件在 CentOS 7 上进行了测试。其他发行版的概念保持不变。
在本教程中,除非另有说明,否则我们将以 root 用户身份运行命令。如果您无权访问 root 帐户并使用具有 sudo 权限的另一个帐户,则需要在命令之前使用sudo
关键字。
创建测试用户帐户
首先,让我们创建四个用户帐户来演示 SELinux 的功能。
- 普通用户 regularuser
- 切换用户 switcheduser
- 来宾用户 guestuser
- 受限用户 restricteduser
您当前应该是root用户。让我们运行以下命令来添加regularuser帐户:
$ useradd -c "Regular User" regularuser
然后我们运行passwd
命令更改其密码:
$ passwd regularuser
输出将要求我们提供新密码。提供后,该帐户将准备好登录:
Changing password for user regularuser.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
让我们也创建其他帐户:
$ useradd -c "Switched User" switcheduser
$ passwd switcheduser
$ useradd -c "Guest User" guestuser
$ passwd guestuser
$ useradd -c "Restricted Role User" restricteduser
$ passwd restricteduser
用于进程和文件的 SELinux
SELinux 的目的是确保进程在 Linux 环境中访问文件的方式。如果没有 SELinux,像 Apache 守护进程这样的进程或应用程序将在启动它的用户的上下文中运行。因此,如果您的系统受到在 root 用户下运行的流氓应用程序的危害,该应用程序可以为所欲为,因为 root 对每个文件都拥有无所不包的权限。
SELinux 试图更进一步并消除这种风险。使用 SELinux,进程或应用程序将只拥有运行所需的权限,仅此而已。应用程序的 SELinux 策略将确定它需要访问哪些类型的文件以及它可以转换到哪些进程。SELinux 策略由应用程序开发人员编写,并随支持它的 Linux 发行版一起提供。策略基本上是一组将进程和用户映射到其权限的规则。
我们通过了解 SELinux上下文和域的含义开始讨论本教程的这一部分。
安全的第一部分在 Linux 系统中的每个实体上贴上标签。标签就像任何其他文件或进程属性(所有者、组、创建日期等);它显示了资源的上下文。那么什么是上下文呢?简而言之,上下文是帮助 SELinux 做出访问控制决策的安全相关信息的集合。Linux 系统中的所有内容都可以有一个安全上下文:用户帐户、文件、目录、守护程序或端口都可以有它们的安全上下文。然而,安全上下文对于不同类型的对象将意味着的不同的含义。
SELinux 文件上下文
让我们从了解 SELinux 文件上下文开始。让我们看一下针对 /etc 目录的常规 ls -l 命令的输出。
$ ls -l /etc/*.conf
这将向我们展示一个熟悉的输出:
...
-rw-r--r--. 1 root root 19 Aug 19 21:42 /etc/locale.conf
-rw-r--r--. 1 root root 662 Jul 31 2013 /etc/logrotate.conf
-rw-r--r--. 1 root root 5171 Jun 10 07:35 /etc/man_db.conf
-rw-r--r--. 1 root root 936 Jun 10 05:59 /etc/mke2fs.conf
...
很简单吧?现在让我们添加 -Z 标志:
$ ls -Z /etc/*.conf
我们现在在用户和组所有权之后有一个额外的信息列:
...
-rw-r--r--. root root system_u:object_r:locale_t:s0 /etc/locale.conf
-rw-r--r--. root root system_u:object_r:etc_t:s0 /etc/logrotate.conf
-rw-r--r--. root root system_u:object_r:etc_t:s0 /etc/man_db.conf
-rw-r--r--. root root system_u:object_r:etc_t:s0 /etc/mke2fs.conf
...
此列显示文件的安全上下文。当您有可用的信息时,一个文件就被认为是用它的安全上下文标记的。让我们仔细看看其中一个安全上下文。
-rw-r--r--. root root system_u:object_r:etc_t:s0 /etc/logrotate.conf
安全上下文是这部分:
system_u:object_r:etc_t:s0
安全上下文有四个部分,其中的每个部分都用冒号 (:) 分隔。第一部分是文件的 SELinux用户上下文。我们稍后会讨论 SELinux 用户,但现在,我们可以看到它是system_u。每个 Linux 用户帐户都映射到一个 SELinux 用户,在这种情况下,拥有该文件的root用户将映射到 SELinux 用户system_u。此映射由 SELinux 策略完成。
第二部分指定 SELinux角色,即object_r。要复习 SELinux 角色,请回顾第一篇 SELinux 文章。
这里最重要的是第三部分,这里列为etc_t的文件类型。这是定义文件或目录所属类型的部分。我们可以看到大部分文件都属于/etc
目录中的etc_t类型。假设,您可以将类型视为文件的一种“组”或属性:它是对文件进行分类的一种方式。
我们还可以看到一些文件可能属于其他类型,例如locale.conf
具有locale_t类型。即使此处列出的所有文件都具有相同的用户和组所有者,它们的类型也可能不同。
作为另一个例子,让我们检查用户主目录的类型上下文:
$ ls -Z /home
主目录将具有不同的上下文类型:user_home_dir_t
drwx------. guestuser guestuser unconfined_u:object_r:user_home_dir_t:s0 guestuser
drwx------. root root system_u:object_r:lost_found_t:s0 lost+found
drwx------. regularuser regularuser unconfined_u:object_r:user_home_dir_t:s0 regularuser
drwx------. restricteduser restricteduser unconfined_u:object_r:user_home_dir_t:s0 restricteduser
drwx------. switcheduser switcheduser unconfined_u:object_r:user_home_dir_t:s0 switcheduser
drwx------. sysadmin sysadmin unconfined_u:object_r:user_home_dir_t:s0 sysadmin
安全上下文的第四部分s0与多级安全或 MLS 有关。基本上这是强制执行 SELinux 安全策略的另一种方式,这部分显示了资源的敏感性(s0)。稍后我们将简要讨论敏感性和类别。对于 SELinux 的大多数基本 (vanilla) 设置,前三个安全上下文更为重要。
SELinux 进程上下文
现在让我们谈谈进程安全上下文。
启动 Apache 和 SFTP 服务。我们在第一个 SELinux 教程中安装了这些服务。
$ service httpd start
$ service vsftpd start
我们可以运行带有几个标志的ps
命令来显示在我们的服务器上运行的 Apache 和 SFTP 进程:
$ ps -efZ | grep 'httpd\|vsftpd'
-Z 标志再次用于显示 SELinux 上下文。输出显示运行进程的用户、进程 ID 和父进程 ID:
system_u:system_r:httpd_t:s0 root 7126 1 0 16:50 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 7127 7126 0 16:50 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 7128 7126 0 16:50 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 7129 7126 0 16:50 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 7130 7126 0 16:50 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 7131 7126 0 16:50 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:ftpd_t:s0-s0:c0.c1023 root 7209 1 0 16:54 ? 00:00:00 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 7252 2636 0 16:57 pts/0 00:00:00 grep --color=auto httpd\|vsftpd
安全上下文是这部分:
system_u:system_r:httpd_t:s0
安全上下文有四个部分:用户、角色、域和敏感度。用户、角色和敏感度作用和文件对应的上下文一样(在上一节中解释过)。域对于进程是独有的。
在上面的例子中,我们可以看到有几个进程是在httpd_t域中运行,而一个进程是在ftpd_t域内运行。
那么域对进程的作用是什么呢?它为进程提供了一个运行环境。它就像包裹一个进程周围并限制它的气泡。它告诉进程它可以做什么,不能做什么。这种限制确保每个进程域只能作用于某些类型的文件,仅此而已。
使用这个模型,即使一个进程被另一个恶意进程或用户劫持,它所能做的最坏的事情就是破坏它有权访问的文件。例如,vsftp 守护进程将无法访问 sendmail 或 samba 使用的文件。这个限制是从内核级别实现的:它在 SELinux 策略加载到内存中时强制执行,因此访问控制成为强制性的。
命名约定
在我们继续之前,这里有一个关于 SELinux 命名约定的说明。SELinux 用户以“_u”为后缀,角色以“_r”为后缀,类型(对于文件)或域(对于进程)以“_t”为后缀。
进程如何访问资源
到目前为止,我们已经看到文件和进程可以有不同的上下文,并且它们仅限于自己的类型或域。那么一个进程是如何运行的呢?要运行,进程需要访问其文件并对其执行一些操作(打开、读取、修改或执行)。我们还了解到,每个进程只能访问某些类型的资源(文件、目录、端口等)。
SELinux 在策略中规定了这些访问规则。访问规则遵循标准的允许语句结构:
allow <domain> <type>:<class> { <permissions> };
我们已经讨论过域和类型。类定义资源实际代表什么(文件、目录、符号链接、设备、端口、游标等)
下面是这个通用的 allow 语句的含义:
- 如果进程属于某个域
- 它试图访问的资源对象是特定的类和类型
- 然后允许访问
- 否则拒绝访问
要了解其工作原理,让我们考虑在 CentOS 7 系统上运行的 httpd 守护程序的安全上下文:
system_u:system_r:httpd_t:s0 7126 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 7127 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 7128 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 7129 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 7130 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 7131 ? 00:00:00 httpd
Web 服务器的默认主目录是/var/www/html
。让我们在该目录中创建一个文件并检查其上下文:
$ touch /var/www/html/index.html
$ ls -Z /var/www/html/*
我们的 Web 内容的文件上下文将是httpd_sys_content_t:
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html
我们可以使用sesearch
命令来检查 httpd 守护进程允许的访问类型:
$ sesearch --allow --source httpd_t --target httpd_sys_content_t --class file
与命令一起使用的标志是不言自明的:源域是httpd_t,Apache 运行在这个域中。我们对作为文件并且具有httpd_sys_content_t类型上下文的目标资源感兴趣。您的输出应如下所示:
Found 4 semantic av rules:
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ;
allow httpd_t httpd_content_type : file { ioctl read getattr lock open } ;
allow httpd_t httpdcontent : file { ioctl read write create getattr setattr lock append unlink link rename execute open } ;
注意第一行:
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
这表示 httpd 守护进程(Apache Web 服务器)具有对httpd_sys_content类型文件的 I/O 控制、读取、获取属性、锁定和打开访问权限。在本例中,我们的index.html
文件具有这种类型。 更进一步,让我们首先修改网页(/var/www/html/index.html
)。编辑文件以包含此内容:
<html>
<title>
This is a test web page
</title>
<body>
<h1>This is a test web page</h1>
</body>
</html>
接下来,我们将更改/var/www/文件夹及其内容的权限,然后重新启动 httpd 守护程序:
$ chmod -R 755 /var/www
$ service httpd restart
然后我们将尝试从浏览器访问它:

注意 根据您的服务器的设置方式,您可能必须在 IPTables 防火墙中启用端口 80,以允许来自服务器外部的传入 HTTP 流量。我们不会在这里详细介绍在 IPTables 中启用端口的细节。您可以使用一些关于该主题的优秀 DigitalOcean文章。
到现在为止还挺好。httpd 守护进程被授权访问特定类型的文件,我们可以在通过浏览器访问时看到它。接下来,让我们通过更改文件的上下文来使事情有所不同。我们将使用该chcon
命令。命令的--type
标志允许我们为目标资源指定新类型。在这里,我们将文件类型更改为var_t。
$ chcon --type var_t /var/www/html/index.html
我们可以确认类型更改:
$ ls -Z /var/www/html/
-rwxr-xr-x. root root unconfined_u:object_r:var_t:s0 index.html
接下来,当我们尝试访问网页时(即 httpd 守护进程尝试读取文件),您可能会收到Forbidden错误,或者您可能会看到通用的 CentOS“Testing 123”页面:

那么这里发生了什么?显然现在某些访问被拒绝了,但被拒绝的是谁的访问?就 SELinux 而言,Web 服务器仅被授权访问某些类型的文件,而 var_t 不是这些上下文之一。由于我们将 index.html 文件的上下文更改为 var_t,Apache 无法再读取它并出现错误。
为了让事情再次工作,让我们使用restorecon
命令更改文件类型。-v 开关显示上下文标签的变化:
$ restorecon -v /var/www/html/index.html
restorecon reset /var/www/html/index.html context unconfined_u:object_r:var_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
如果我们现在尝试访问该页面,它将再次显示我们的“This is a test web page”文本。
这是一个需要理解的重要概念:确保文件和目录具有正确的上下文对于确保 SELinux 正常运行至关重要。我们将在本节末尾看到一个实际用例,但在此之前,让我们再谈一些事情。
文件和目录的上下文继承
SELinux 强制执行我们可以称之为“上下文继承”的东西。这意味着除非策略指定,否则进程和文件是使用其父级的上下文创建的。
因此,如果我们有一个名为“proc_a”的进程产生另一个名为“proc_b”的进程,除非 SELinux 策略另有规定,否则产生的进程将在与“proc_a”相同的域中运行。
类似地,如果我们有一个类型为“some_context_t”的目录,除非策略另有说明,否则在其下创建的任何文件或目录都将具有相同的类型上下文。
为了说明这一点,让我们检查/var/www/目录的上下文:
$ ls -Z /var/www
/var/www/
中的html
目录具有httpd_sys_content_t类型上下文。正如我们之前看到的,其中的index.html
文件具有相同的上下文(即父级的上下文):
drwxr-xr-x. root root system_u:object_r:httpd_sys_script_exec_t:s0 cgi-bin
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 html
将文件复制到其他位置时,不会保留此继承。在复制操作中,复制的文件或目录将采用目标位置的类型上下文。在下面的代码片段中,我们将index.html
文件(具有“httpd_sys_content_t”类型上下文)复制到/var/
目录中:
$ cp /var/www/html/index.html /var/
如果我们检查复制后的文件的上下文,我们将看到它已更改为var_t,即其当前父目录的上下文:
$ ls -Z /var/index.html
-rwxr-xr-x. root root unconfined_u:object_r:var_t:s0 /var/index.html
cp
命令中的--preserver=context
子句可以覆盖上下文的这种更改。
移动文件或目录时,会保留原始上下文。在以下命令中,我们将/var/index.html
移动到/etc/
目录:
$ mv /var/index.html /etc/
当我们检查移动后的文件的上下文时,我们看到在/etc/
目录下var_t上下文被保留:
$ ls -Z /etc/index.html
-rwxr-xr-x. root root unconfined_u:object_r:var_t:s0 /etc/index.html
那么为什么我们如此关心文件上下文呢?为什么这个复制和移动概念很重要?想一想:也许您决定将所有 Web 服务器的 HTML 文件复制到root文件夹下的一个单独目录中。您这样做是为了简化备份过程并加强安全性:您不希望任何黑客轻松猜测您网站的文件在哪里。您已更新目录的访问控制,将 Web 配置文件更改为指向新位置,重新启动服务,但它仍然不起作用。也许您可以在接下来的故障排除步骤中查看目录及其文件的上下文。让我们作为一个实际的例子来运行它。
SELinux 实战:测试文件上下文错误
首先,让我们在根目录下创建一个名为www
的目录。我们还将在www
下创建一个名为html
的文件夹。
$ mkdir -p /www/html
如果我们运行ls -Z
命令,我们将看到这些目录已使用default_t上下文创建:
$ ls -Z /www/
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 html
接下来我们将/var/www/html
目录的内容复制到/www/html
:
$ cp /var/www/html/index.html /www/html/
复制的文件将具有default_t上下文。这是父目录的上下文。
我们现在编辑httpd.conf
文件以指向这个新目录作为网站的根文件夹。我们还必须放宽此目录的访问权限。
$ vi /etc/httpd/conf/httpd.conf
首先,我们注释掉文档根目录的现有位置并添加一个新DocumentRoot
指令到/www/html
:
# DocumentRoot "/var/www/html"
DocumentRoot "/www/html"
我们还注释掉现有文档根目录的访问权限部分并添加一个新部分:
#<Directory "/var/www">
# AllowOverride None
# Allow open access:
# Require all granted
#</Directory>
<Directory "/www">
AllowOverride None
# Allow open access:
Require all granted
</Directory>
我们保留cgi-bin
目录的位置。我们不会在这里详细介绍 Apache 配置;我们只是希望我们的网站能够用于 SELinux 目的。
最后,重启 httpd 守护进程:
$ service httpd restart
服务器重新启动后,访问该网页将出现与我们之前看到的相同的“403 Forbidden”错误(或默认的“Testing 123”页面)。
发生错误是因为index.html
文件的上下文在复制操作期间发生了变化。需要将其改回其原始上下文 (httpd_sys_content_t)。
但是我们该怎么做呢?
更改和恢复 SELinux 文件上下文
在之前的代码示例中,我们看到了两个用于更改文件上下文(此处原文为contents,应为contexts拼写错误)的命令:chcon
和restorecon
。运行chcon
是一种临时措施。您可以使用它来临时更改文件或目录上下文,以对访问拒绝错误进行故障排除。但是,这种方法只是暂时的:文件系统重新标记或运行restorecon
命令会将文件恢复到其原始上下文。
此外,运行chcon
需要您知道文件的正确上下文;该--type
标志指定目标的上下文。restorecon
不需要指定这个。如果您运行restorecon
,该文件将重新应用正确的上下文,并且更改将永久生效。
但是如果您不知道文件的正确上下文,系统如何知道在运行restorecon
时应用哪个上下文?
方便的是,SELinux“记住了”服务器中每个文件或目录的上下文。在 CentOS 7 中,文件/etc/selinux/targeted/contexts/files/file_contexts
中列出了系统中已经存在的文件的上下文。这是一个大文件,它列出了与 Linux 发行版支持的每个应用程序相关联的每个文件类型。新目录和文件的上下文记录在/etc/selinux/targeted/contexts/files/file_contexts.local
文件中。因此,当我们运行restorecon
命令时,SELinux 将从这两个文件之一中查找正确的上下文并将其应用于目标。
下面的代码片段显示了其中一个文件的摘录:
$ cat /etc/selinux/targeted/contexts/files/file_contexts
...
/usr/(.*/)?lib(/.*)? system_u:object_r:lib_t:s0
/opt/(.*/)?man(/.*)? system_u:object_r:man_t:s0
/dev/(misc/)?agpgart -c system_u:object_r:agp_device_t:s0
/usr/(.*/)?sbin(/.*)? system_u:object_r:bin_t:s0
/opt/(.*/)?sbin(/.*)? system_u:object_r:bin_t:s0
/etc/(open)?afs(/.*)? system_u:object_r:afs_config_t:s0
...
要永久更改/www/html
下 index.html
文件的上下文,我们必须遵循两步过程。
- 首先我们运行
semanage fcontext
命令。这会将新上下文写入/etc/selinux/targeted/contexts/files/file_contexts.local
文件。但它不会重新标记文件本身。我们将对这两个目录执行此操作。$ semanage fcontext --add --type httpd_sys_content_t "/www(/.*)?" $ semanage fcontext --add --type httpd_sys_content_t "/www/html(/.*)?"
为了确保,我们可以检查文件上下文数据库(注意我们正在使用该file_contexts.local
文件):
$ cat /etc/selinux/targeted/contexts/files/file_contexts.local
您应该会看到更新的上下文:
# This file is auto-generated by libsemanage
# Do not edit directly.
/www(/.*)? system_u:object_r:httpd_sys_content_t:s0
/www/html(/.*)? system_u:object_r:httpd_sys_content_t:s0
- 接下来,我们将运行
restorecon
命令。这将使用上一步中记录的内容重新标记文件或目录:$ restorecon -Rv /www
这应该在三个级别重置上下文:顶级/www
目录,其下的/www/html
目录和/www/html
下的index.html
文件:
restorecon reset /www context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
restorecon reset /www/html context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
restorecon reset /www/html/index.html context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
如果我们现在尝试访问该网页,它应该可以工作。
有一个优雅的工具matchpathcon
可以帮助解决与上下文相关的问题。此命令将查看资源的当前上下文,并将其与 SELinux 上下文数据库下列出的内容进行比较。如果不同,它将建议所需的更改。让我们用/www/html/index.html
文件测试一下。我们将使用-V验证上下文的标志:
$ matchpathcon -V /www/html/index.html
该matchpathcon
输出应显示上下文进行验证。
/www/html/index.html verified.
对于错误标记的文件,该消息将说明上下文应该是什么:
/www/html/index.html has context unconfined_u:object_r:default_t:s0, should be system_u:object_r:httpd_sys_content_t:s0
域转换
到目前为止,我们已经看到了进程如何访问文件系统资源。我们现在将看到进程如何访问其他进程。
域转换是进程将其上下文从一个域更改为另一个域的方法。为了理解它,假设您有一个名为 proc_a 的进程在 contexta_t 的上下文中运行。通过域转换,proc_a 可以运行一个名为 app_x 的应用程序(一个程序或一个可执行脚本),它会产生另一个进程。这个新进程可以称为 proc_b 并且它可以在 contextb_t 域中运行。于是,contexta_t 有效地通过 app_x转换为 contextb_t。app_x 可执行文件用作contextb_t的入口点(Entrypoint)。流程如下图所示:

域转换的情况在 SELinux 中相当普遍。让我们考虑在我们的服务器上运行的 vsftpd 进程。如果它没有运行,我们可以运行service vsftpd start
命令来启动守护进程。 接下来我们考虑 systemd 进程。这是所有进程的祖先。这是 System V init 进程的替代者,并在init_t的上下文中运行。
$ ps -eZ | grep init
system_u:system_r:init_t:s0 1 ? 00:00:02 systemd
system_u:system_r:mdadm_t:s0 773 ? 00:00:00 iprinit
在init_t域中运行的进程是一个短暂的进程:它将调用二进制可执行文件/usr/sbin/vsftpd
,它的类型上下文为ftpd_exec_t。当二进制可执行文件启动时,它成为 vsftpd 守护进程本身并在ftpd_t域中运行。
我们可以检查文件和进程的域上下文:
$ ls -Z /usr/sbin/vsftpd
向我们展示:
-rwxr-xr-x. root root system_u:object_r:ftpd_exec_t:s0 /usr/sbin/vsftpd
检查进程:
$ ps -eZ | grep vsftpd
向我们展示:
system_u:system_r:ftpd_t:s0-s0:c0.c1023 7708 ? 00:00:00 vsftpd
所以这里运行在init_t域中的进程正在执行一个ftpd_exec_t类型的二进制文件。该文件在ftpd_t域中启动一个守护进程。
这种转换不是应用程序或用户可以控制的。这已在 SELinux 策略中规定,该策略在系统启动时加载到内存中。在非 SELinux 服务器中,用户可以通过切换到更高权限的帐户来启动进程(前提是她或他有权这样做)。在 SELinux 中,此类访问由预先编写的策略控制。这也是我们说 SELinux 实施强制访问控制的另一个原因。
域转换受三个严格规则的约束:
- 源域的父进程必须对位于两个域之间的应用程序(可执行文件)具有执行权限(这里指的是入口点)。
- 应用程序的文件上下文必须被标识为目标域的入口点。
- 必须允许原始域过渡到目标域。
以上面vsftpd守护进程为例,让我们用不同的开关运行sesearch
命令,看看守护进程是否符合这三个规则。
首先,源域 init_t 需要对具有 ftpd_exec_t 上下文的入口点应用程序拥有执行权限。因此,如果我们运行以下命令:
$ sesearch -s init_t -t ftpd_exec_t -c file -p execute -Ad
结果表明init_t域内的进程可以读取、获取属性、执行和打开ftpd_exec_t上下文的文件:
Found 1 semantic av rules:
allow init_t ftpd_exec_t : file { read getattr execute open } ;
接下来,我们检查二进制文件是否是目标域 ftpd_t 的入口点:
sesearch -s ftpd_t -t ftpd_exec_t -c file -p entrypoint -Ad
确实是这样:
Found 1 semantic av rules:
allow ftpd_t ftpd_exec_t : file { ioctl read getattr lock execute execute_no_trans entrypoint open } ;
最后,源域 init_t 需要具有过渡到目标域 ftpd_t 的权限:
$ sesearch -s init_t -t ftpd_t -c process -p transition -Ad
正如我们在下面看到的,源域具有该权限:
Found 1 semantic av rules:
allow init_t ftpd_t : process transition ;
无限制域
当我们引入域的概念时,我们将其与围绕进程的假想的泡沫进行了比较:规定进程可以做什么和不能做什么的东西。这就是进程的限制。
SELinux 也有在不受限制的域中运行的进程。可以想象,不受限制的进程在系统中具有所有类型的访问权限。即便如此,这种完全访问也不是任意的:SELinux 策略中也指定了完全访问。
无限制进程域的示例是 unconfined_t。默认情况下,这就是登录用户运行其进程的域。我们将在后续部分讨论用户及其对进程域的访问。
总结
我们今天在这里介绍了一些非常重要的 SELinux 概念。管理文件和进程上下文是成功实施 SELinux 的核心。正如我们将在本系列的下一部分也是最后一部分中看到的,还有另一块难题:SELinux 用户。
留言