Linux 安全模块:有没有办法检查/审核共享库加载?

问题描述 投票:0回答:1

我正在开发一个基于xattr(文件的扩展属性)的linux安全模块,我想实施安全措施来防止加载没有某些xattr的共享库。这需要我hook file_open检查文件的幻数以确定它是否是共享库,然后进行基于xattr的安全检查。

以下代码是我的实现(尚未完全完成)。挂钩的 file_open

xattracl_file_open(struct file *file)
调用
xattracl_magic_check_elf(struct file* file)
通过读取前 4 个字节来检查
file
是否为 ELF 格式。

但是我发现了两个问题。首先,我无法直接从这个结构

file
获取文件路径,它总是打印为
(efault)
,因此我使用了自定义的
xattracl_get_realpath(struct path *path)
(类似于tomoyo LSM模块的做法)。其次,每次读取4个字节时,它们似乎都有不同的值,我完全无法理解。

然后我尝试调用

flip_open()
因为我可以获取真实的路径名并获取“真实”结构文件来读取其 4 个字节,但这将不起作用,因为挂钩的 file_open() 将递归地调用自身并导致内核恐慌。

代码(为了便于阅读,省略了部分内容):

// ............

// Read magic number from a file's first 4B
// Param:
//  struct file *file: the file to be checked
// Return:
//  (int)-ENOMEM/-ENOENT/0/1 for memory allocation error/file reading error/being ELF/not ELF
int xattracl_file_magic_check_elf(struct file *file){
    const char *realpath=xattracl_get_realpath(&file->f_path);
    if(!realpath){
        return -ENOMEM;
    }
    char *value=(char*)kmalloc(4,GFP_NOFS);
    if(!value){
        return -ENOMEM;
    }
    kernel_read(file,value,4,0)==-1);
    int iself=(value[0]==0x7F)&&(value[1]==0x45)&&(value[2]==0x4C)&&(value[3]==0x46);
    printk(KERN_INFO"[xattracl] (file_magic_check_elf) file:%s magic:%02X%02X%02X%02X iself:%d\n",realpath,value[0],value[1],value[2],value[3],iself);
    filp_close(realfile,NULL);
    kfree(realpath);
    kfree(value);
    return iself;
}

// Hooked file_open for ELF loading control
// Param:
//  struct file *file: the file to be checked
// Return:
//  (static int)-ENOMEM/-EPERM/0 for memory allocation error/denying loading/allowing loading
static int xattracl_file_open(struct file *file){
    // If file is not ELF, allow loading.
    int iself=xattracl_file_magic_check_elf(file);
    if(!iself){
        // Only return 0 for testing
        // return -EPERM;
        return 0;
    }
    // Get the file's xattr
    struct dentry *dentry=file->f_path.dentry;
    struct inode *inode=d_backing_inode(dentry);
    char *value=(char*)kmalloc(XATTRACL_XATTR_VALUE_SIZE,GFP_NOFS);
    if(!value){
        return -ENOMEM;
    }
    int size=__vfs_getxattr(dentry,inode,XATTRACL_XATTR_NAME,value,XATTRACL_XATTR_VALUE_SIZE);
    value[MAX(size,0)]=0;
    // Users can only load shared libraries with XATTRACL_XATTR_NAME:XATTRACL_XATTR_ACTION_ALLOW
    int action=strcmp(value,XATTRACL_XATTR_ACTION_ALLOW)?-EPERM:0;
    printk(KERN_INFO"[xattracl] (file_open) file:%s type:%s "XATTRACL_XATTR_NAME":%s action:%s\n",dentry->d_name.name,iself?"OTHER":"ELF",value,action?"deny":"allow");
    kfree(value);
    // Only return 0 for testing
    // return action;
    return 0;
}

// ............

static struct security_hook_list xattracl_hooks[] __lsm_ro_after_init={
    // ............
    LSM_HOOK_INIT(file_open,xattracl_file_open),
    // ............
};

// ............

dmesg 日志记录了这种奇怪的现象:



[pairman@fedora Downloads]$ dmesg | grep /usr/lib64/libc.so.6

[  176.002714] [xattracl] (file_magic_check_elf) file:/usr/lib64/libc.so.6, magic:35205B31 elf:0

[  176.006182] [xattracl] (file_magic_check_elf) file:/usr/lib64/libc.so.6, magic:CDDF5D32 elf:0

[  177.045407] [xattracl] (file_magic_check_elf) file:/usr/lib64/libc.so.6, magic:4DA46A31 elf:0

[  177.045412] [xattracl] (file_magic_check_elf) file:/usr/lib64/libc.so.6, magic:354E8438 elf:0

[  177.050782] [xattracl] (file_magic_check_elf) file:/usr/lib64/libc.so.6, magic:CDDF5D32 elf:0

[  177.053388] [xattracl] (file_magic_check_elf) file:/usr/lib64/libc.so.6, magic:5DDB5E31 elf:0

[  179.175885] [xattracl] (file_magic_check_elf) file:/usr/lib64/libc.so.6, magic:4DA46A31 elf:0

[  179.175907] [xattracl] (file_magic_check_elf) file:/usr/lib64/libc.so.6, magic:354E8438 elf:0

[pairman@fedora Downloads]$ xxd /usr/lib64/libc.so.6 | head -1

00000000: 7f45 4c46 0201 0103 0000 0000 0000 0000  .ELF............



我一直在寻找selinux和apparnor的类似场景和源代码,但没有找到任何有用的东西。

  1. 解释为什么我无法直接从

    file
    (即
    (efault)
    )获取文件路径,以及为什么它的内容看起来随机、不正确并且每次都会变化,以及如何正确获取文件的幻数无需打电话
    file_open

  2. 是否有以正确的linux安全模块方式检查和审核共享库加载的其他方法?这样我就不用被这种痛苦淹没了。

file linux-kernel shared-libraries xattr linux-security-module
1个回答
0
投票

感谢 Marco Bonelli,几个月后我现在记得我还没有正确回答。挂钩 mmap_file() 并通过 PERM_EXEC 参数检查文件是否是可执行文件解决了这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.