CentOS7上的SELinux简介-第2部分:文件和进程
介绍
在我们 SELinux 系列 的 第一部分中,我们看到了如何启用和禁用 SELinux,以及如何使用布尔值更改一些策略设置。 在第二部分中,我们将讨论文件和进程安全上下文。
回顾上一个教程,文件安全上下文是 类型 ,进程安全上下文是 域 。
注意 本教程中显示的命令、包和文件是在 CentOS 7 上测试的。 其他发行版的概念保持不变。
在本教程中,除非另有说明,否则我们将以 root 用户身份运行命令。 如果您无权访问 root 帐户并使用具有 sudo 权限的其他帐户,则需要在命令前加上 sudo
关键字。
创建测试用户帐户
首先,让我们创建四个用户帐户来演示 SELinux 的功能。
- 普通用户
- 切换用户
- 来宾用户
- 受限用户
您当前应该是 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 contexts 和 domains 的含义开始讨论本教程的这一部分。
安全性的第一部分在 Linux 系统中的每个实体上放置一个 标签。 标签类似于任何其他文件或进程属性(所有者、组、创建日期等); 它显示资源的 context。 那么什么是上下文? 简而言之,上下文是帮助 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 ...
此列显示文件的安全上下文。 当您有此信息可用时,该文件被称为 labelled 及其安全上下文。 让我们仔细看看其中一个安全上下文。
-rw-r--r--. root root system_u:object_r:etc_t:s0 /etc/logrotate.conf
安全上下文是这部分:
system_u:object_r:etc_t:s0
安全上下文有四个部分,每个部分用冒号 (:) 分隔。 第一部分是文件的 SELinux user 上下文。 我们稍后会讨论 SELinux 用户,但现在,我们可以看到它是 system_u。 每个 Linux 用户帐户都映射到一个 SELinux 用户,在这种情况下,拥有该文件的 root 用户映射到 system_u SELinux 用户。 此映射由 SELinux 策略完成。
第二部分指定 SELinux role,即 object_r。 要复习 SELinux 角色,请回顾第一篇 SELinux 文章。
这里最重要的是第三部分,即此处列为 etc_t 的文件的 type。 这是定义文件或目录所属的 type 的部分。 我们可以看到大部分文件属于/etc
目录下的etc_t类型。 假设,您可以将类型视为文件的一种“组”或 属性 :它是对文件进行分类的一种方式。
我们还可以看到一些文件可能属于其他类型,例如具有 locale_t 类型的 locale.conf
。 即使此处列出的所有文件都具有相同的用户和组所有者,它们的类型也可能不同。
作为另一个示例,让我们检查用户主目录的类型上下文:
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 的大多数普通设置,前三个安全上下文更为重要。
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 语句 结构:
allow <domain> <type>:<class> { <permissions> };
我们已经讨论过域和类型。 Class 定义资源实际代表的内容(文件、目录、符号链接、设备、端口、光标等)
下面是这个通用允许语句的含义:
- 如果一个进程属于某个域
- 它试图访问的资源对象是特定的类和类型
- 然后允许访问
- 否则拒绝访问
要了解它是如何工作的,让我们考虑在我们的 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[X68X]:
-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[X106X] 类型上下文。 您的输出应如下所示:
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
如果我们现在尝试访问该页面,它将再次显示我们的“这是一个测试网页”文本。
这是一个需要理解的重要概念:确保文件和目录具有正确的上下文是确保 SELinux 正常运行的关键。 我们将在本节末尾看到一个实际用例,但在此之前,让我们再谈几件事。
文件和目录的上下文继承
SELinux 强制执行我们可以称之为“上下文继承”的东西。 这意味着除非策略指定,否则进程和文件是使用其父级的上下文创建的。
因此,如果我们有一个名为“proc_a”的进程生成另一个名为“proc_b”的进程,则生成的进程将与“proc_a”在同一个域中运行,除非 SELinux 策略另有规定。
类似地,如果我们有一个类型为“some_context_t”的目录,则在其下创建的任何文件或目录都将具有相同的类型上下文,除非策略另有说明。
为了说明这一点,让我们检查 /var/www/
目录的上下文:
ls -Z /var/www
/var/www/
中的 html
目录具有 httpd_sys_content_t[X72X] 类型上下文。 正如我们之前看到的,其中的 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/
当我们检查移动文件的上下文时,我们看到 var_t 上下文已保存在 /etc/
目录下:
ls -Z /etc/index.html
-rwxr-xr-x. root root unconfined_u:object_r:var_t:s0 /etc/index.html
那么为什么我们如此关注文件上下文呢? 为什么这个复制和移动概念很重要? 想一想:也许您决定将所有 Web 服务器的 HTML 文件复制到根文件夹下的单独目录中。 您这样做是为了简化备份过程并加强安全性:您不希望任何黑客轻易猜测您网站的文件在哪里。 您已经更新了目录的访问控制,更改了 web 配置文件以指向新位置,重新启动服务,但它仍然无法正常工作。 也许您可以查看目录及其文件的上下文作为下一个故障排除步骤。 让我们作为一个实际的例子来运行它。
SELinux 实战:测试文件上下文错误
首先,让我们在根目录下创建一个名为 www
的目录。 我们还将在 www
下创建一个名为 html
的文件夹。
mkdir -p /www/html
如果我们运行 ls -Z
命令,我们将看到这些目录是使用 default_t[X103X] 上下文创建的:
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[X52X] 的上下文。 那是父目录的上下文。
我们现在编辑 httpd.conf
文件以指向这个新目录作为网站的根文件夹。 我们还必须放宽对该目录的访问权限。
vi /etc/httpd/conf/httpd.conf
首先,我们注释掉文档根目录的现有位置,并在 /www/html
中添加一个新的 DocumentRoot
指令:
# 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 文件上下文
在之前的代码示例中,我们看到了两个用于更改文件内容的命令: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[X92X] 的上下文中运行。 :
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[X41X] 域中运行的进程是短暂的:它将调用二进制可执行文件 /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[X45X] 域中的进程正在执行一个具有 ftpd_exec_t 类型的二进制文件。 该文件在 ftpd_t 域中启动一个守护进程。
这种转换不是应用程序或用户可以控制的。 这已在系统启动时加载到内存中的 SELinux 策略中进行了规定。 在非 SELinux 服务器中,用户可以通过切换到更强大的帐户来启动进程(前提是她或他有权这样做)。 在 SELinux 中,此类访问由预先编写的策略控制。 这也是据说 SELinux 实施强制访问控制的另一个原因。
域转换遵循三个严格的规则:
- 源域的父进程必须对位于两个域之间的应用程序具有执行权限(这是入口点)。
- 应用程序的文件上下文必须标识为目标域的 entrypoint。
- 必须允许原始域转换到目标域。
以上面的 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 用户。