SELinux permission denied error通过RPM包安装内核模块时出现错误 &



我正在尝试创建一个RPM安装程序,该安装程序使用调用insmod的安装脚本加载内核模块。它安装到的目录是/opt/nfast,看看/etc/selinux/targeted/contexts/files/file_context,我注意到这里安装的文件得到默认上下文:

/opt/nfast(/.*)?        system_u:object_r:pki_common_t:s0

我看到rpm安装程序完成了它的工作:

[root@localhost nfast]# ls -laZ
total 12
drwxr-xr-x. 2 root root system_u:object_r:pki_common_t:s0   37 May 12 00:47 .
drwxr-xr-x. 3 root root system_u:object_r:usr_t:s0          19 May 12 00:44 ..
-rw-r--r--. 1 root root system_u:object_r:pki_common_t:s0 4296 May 12 00:46 hello.ko
-rwxr-xr-x. 1 root root system_u:object_r:pki_common_t:s0   48 May 12 00:46 install

我创建了一个最小的示例,如下所示,我不知道为什么通过RPM安装程序安装失败,但是当我随后通过命令行直接调用脚本时,它可以正常工作。

[root@localhost ~]# rpm -ivh hello-1-1.el8.x86_64.rpm
Verifying...                          ################################# [100%]
Preparing...                          ################################# [100%]
Updating / installing...
1:hello-1-1.el8                    ################################# [100%]
insmod: ERROR: could not insert module /opt/nfast/hello.ko: Permission denied
warning: %post(hello-1-1.el8.x86_64) scriptlet failed, exit status 1

发生了什么事?为什么我的RPM不允许这样做?

规格/hello.spec

Name:           hello
Version:        1
Release:        1%{?dist}
Summary:        none
License:    none
Source0:        %{name}-%{version}.tar.gz
BuildRequires:  gcc make
%define debug_package %{nil}
%description
none
%prep
%autosetup
%build
%make_build
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p %{buildroot}/opt/nfast
cp %{_builddir}/%{name}-%{version}/hello.ko %{buildroot}/opt/nfast
install -D -m 0755 %{_builddir}/%{name}-%{version}/install %{buildroot}/opt/nfast
%post
/opt/nfast/install
%files
/opt/nfast/hello.ko
/opt/nfast/install
%changelog
* Thu May 12 2022 Sam
- 

来源/hello-1/安全

#include <linux/module.h>
#include <linux/kernel.h>
int init_module(void)
{
printk(KERN_INFO "hello worldn");
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "goodbye worldn");
}

来源/hello-1/Makefile

obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

源/hello-1/安装

#!/bin/sh
dos="/opt/nfast/hello.ko"
insmod $dos

好了,我终于弄明白了。有一些工具是我不知道的,而且我对SELinux的理解也不够全面,不足以调试这个问题。

首先,我注意到我的安装脚本在安装到/opt而不是/opt/nfast时工作,所以我查看了标签,注意到每个目录的类型不同:usr_t, pki_common_t。

$ ls -laZ /opt
total 4
drwxr-xr-x. 1 root root system_u:object_r:usr_t:s0         58 Jun  9 15:59 .
$ ls -laZ /opt/nfast
total 64
drwxr-xr-x. 1 root root system_u:object_r:pki_common_t:s0    16 Jun  9 15:59

然后我查看了默认情况下应用于这些目录和子目录的上下文,认为可能是一个nfast子目录目录被错误地标记:

sudo semanage fcontext -l | ag /opt/nfast
/opt/nfast(/.*)?                                   all files          system_u:object_r:pki_common_t:s0
/opt/nfast/sbin/init.d-ncipher                     all files          system_u:object_r:initrc_exec_t:s0
/opt/nfast/scripts/init.d/(.*)                     all files          system_u:object_r:initrc_exec_t:s0
$ sudo semanage fcontext -l | ag -Q '/opt/.*'
/opt/.*                                            all files          system_u:object_r:usr_t:s0 

所以我再次运行RPM安装程序,在系统日志中提示拒绝,这次运行ausearch工具来获得一些更详细的信息,并看到(显然)module_load正在被拒绝,并且源上下文需要访问目标上下文:kmod_t需要能够对pki_common_t对象做一些事情。

$ sudo ausearch -m avc -ts recent | grep hello
type=AVC msg=audit(1654759755.359:184): avc: denied { module_load } for
pid=3859 comm="insmod" path="/opt/nfast/hello.ko" dev="dm-0" ino=134637031
scontext=unconfined_u:unconfined_r:kmod_t:s0-s0:c0.c1023
tcontext=system_u:object_r:pki_common_t:s0 tcla ss=system permissive=0

audit2why可以帮助进一步详细说明这个错误:

➜ sudo ausearch -m avc -ts recent | grep hello | sudo audit2why
type=AVC msg=audit(1654828902.311:733): avc:  denied  { module_load } for  pid=21558 comm="insmod" path="/opt/nfast/hello.ko" dev="dm-0" ino=67723333 scontext=unconfined_u:unconfined_r:kmod_t:s0-s0:c0.c1023 tcontext=system_u:object_r:pki_common_t:s0 tclass=system permissive=0
Was caused by:
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access.

谢天谢地,我了解到audit2allow工具可以创建这种类型强制策略规则,然后可以将其安装到selinux中。

sudo ausearch -m avc -ts recent | grep hello | sudo audit2allow -R -m local > local.te

➜ cat local.te                                                                                                    
                                            
policy_module(local, 1.0)                                                                                         
                                            
require {                                                                                                         
type pki_common_t;                                                                                        
type kmod_t;                                                                                              
class system module_load;                                                                                 
}                                                                                                                 
                                            
#============= kmod_t ==============                                                                              
allow kmod_t pki_common_t:system module_load; 

使用手册页中描述的audit2allow的步骤,我在本地编译了结果。文件给了我一个地方。页文件。

➜ make -f /usr/share/selinux/devel/Makefile local.pp                                                              
Compiling targeted local module                                                                                   
Creating targeted local.pp policy package                                                                         
rm tmp/local.mod.fc tmp/local.mod 

最后,我添加了一个semodule -i /opt/nfast/local.pp来在RPM的%post install阶段安装模块(在运行安装脚本之前)。这个工作!

在构建rpmspec文件之前尝试这样做:

%邮报》

chcon -t module_object_t/opt/nfast/hello.ko

最新更新