使用 EBPF 挂钩文件删除

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

如果文件名以“t”开头,我想拒绝在 Linux 计算机上删除文件。

这是我所做的:

#define __TARGET_ARCH_arm64 

#include <linux/ptrace.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>

char LICENSE[] SEC("license") = "Dual BSD/GPL";

typedef struct {
        int counter;
} atomic_t;

struct filename {
        const char *name;
        const char *uptr;
        atomic_t refcnt;
        struct audit_names *aname;
        const char iname[0];
};

SEC("kprobe/do_unlinkat")
int BPF_KPROBE(do_unlinkat, int dfd, struct filename *name)
{
    char filename[128];
    const char *ptr_filename = BPF_CORE_READ(name, name);
    int ret = bpf_probe_read_kernel_str(filename, sizeof(filename), ptr_filename);
    if (filename[0]=='t')
    {
        bpf_printk("This file starts by 't'");

        // return 1;   <- returning 1 or -1 does not "cancel" the syscall...

        // I have also tried to change filename on the fly...
        filename[0]='w';
        bpf_copy_from_user((void *) ptr_filename, 1, filename);
        // bpf_copy_from_user((void *) name->name, 1, filename); // Also tried this...
   }

    bpf_printk("Deleting this file:%s", filename);
    return 0;
}

我首先不明白的是 BPF_KPROBE 的返回值是什么? 我原以为返回 0 以外的值会取消系统调用。 但我的文件还是被删除了...

我尝试过更改文件名。但是当我尝试编译 eBPF 时 bpf_copy_from_user 会导致错误:

libbpf: prog 'do_unlinkat': BPF program load failed: Permission denied
libbpf: prog 'do_unlinkat': -- BEGIN PROG LOAD LOG -- arg#0 reference
type('FWD pt_regs') size cannot be determined: -22 0: R1=ctx() R10=fp0

有什么想法吗?

ebpf
1个回答
0
投票

我首先不明白的是 BPF_KPROBE 的返回值是什么? 我原以为返回 0 以外的值会取消系统调用。但我的文件还是被删除了...

kprobe的返回值是没有意义的,没有任何作用。 kprobe 是一个观察工具,而不是实现功能,因此这样的设计。

一些异常进入了 eBPF,例如

bpf_override_return
,它是一个帮助器,可以设置返回值并提前退出被探测的函数。它确实需要使用
CONFIG_BPF_KPROBE_OVERRIDE=y
kconfig 编译内核。这是一种已知有效的技术,https://tetragon.io/也使用它来实现运行时安全强制。

如果以上方法因任何原因不能满足您的需求,您可以考虑LSM 计划。 LSM 程序允许您将 eBPF 代码挂钩到 SELinux/AppArmor 也使用的 LSM 挂钩中。这些是为了强制执行,根据特定的钩子,您可以返回布尔值或错误代码。此功能至少需要内核版本 v5.7,并且您的内核需要使用

CONFIG_BPF_LSM=y
kconfig 进行编译。

我认为

path_unlink
钩子就是你想要的。它的描述

@path_unlink:
 Check the permission to remove a hard link to a file.
 @dir contains the path structure of parent directory of the file.
 @dentry contains the dentry structure for file to be unlinked.
 Return 0 if permission is granted.

它被控制在

CONFIG_SECURITY_PATH
kconfig 后面。如果你的内核没有它,它们
inode_unlink
是一个类似的钩子,但不会直接给你路径,所以更多的工作。

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