【问题标题】:SELinux permission denied error when installing a kernel module via an RPM package通过 RPM 包安装内核模块时出现 SELinux 权限被拒绝错误
【发布时间】:2022-10-18 16:20:39
【问题描述】:

我正在尝试创建一个 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/hello.c

#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void)
{
    printk(KERN_INFO "hello world\n");
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "goodbye world\n");
}

来源/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

【问题讨论】:

    标签: kernel rpm rpmbuild selinux


    【解决方案1】:

    好的,我最终想通了。有一些我不知道的工具,而且我对 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 手册页中描述的步骤,我编译了生成的 local.te 文件,它给了我一个 local.pp 文件。

    ➜ 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 阶段(以及在运行安装脚本之前)安装模块。这行得通!

    【讨论】:

      【解决方案2】:

      在构建 rpmspec 文件之前尝试这种方式:

      %邮政

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

      【讨论】:

        猜你喜欢
        • 2018-06-15
        • 2018-01-13
        • 2017-11-14
        • 1970-01-01
        • 2011-07-05
        • 2016-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多