cebpflinux-security-module

How to collect filename from eBPF hook while file is creating?


Can somebody help me with retrieving name of file using eBPF when file is creating?

What I’ve done:

  1. We have 2 funcs (helper and Kfunc) for collecting filepath from struct path: bpf_d_path & bpf_path_d_path.
  2. We also have some points where we can attach bpf program: lsm/inode_create, lsm/path_mknod, lsm/inode_mknod, tracepoints to kernel functions «security_*» related to lsm hooks.

Unlike other file-related lsm hooks (full list we can find in https://elixir.bootlin.com/linux/v6.16/source/kernel/bpf/bpf_lsm.c#L286 to 384), I can’t use helper bpf_d_path in path_mknod hook, because this hook is not sleepable. And Kfunc (which is better to use, than helper) is too new. And I don't know how to use hooks, that uses inodes instead of path, to get the full path of the file.

I don’t want to collect info about all files (but this will be better). First, I want to learn how to get the path when creating a regular file.

lsm/inode_link hook isn’t called when file is creating.

Any suggestions?

bpf program:

SEC("lsm/security_path_mknod")
int BPF_PROG(check_new_file_create, const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev)
{
    struct FSEvent *newEvent = bpf_ringbuf_reserve(
        &FSEventMap,
        sizeof(struct FSEvent),
        0);
    if (newEvent == NULL)
    {
        bpf_printk("ERROR: check_new_file_create: Error reserving ringbuf event\n");
        return 0;
    }

    d_path_result = bpf_d_path(dir, newEvent->filepath, sizeof(newEvent->filepath));
    if (d_path_result > 0)
    {
        newEvent->filepathSize = d_path_result;
    }
    else
    {
        newEvent->filepathSize = 0;
    }

    bpf_ringbuf_submit(newEvent, 0);

    return 0;
}

I use go library ebpf-go to load and attach programs to tracepoints.

I tried to use named helper in lsm hook path_mknod. In other lsm hooks this helper works correctly (because of this check), but I was surprised when I try to load my program in kernel and verifier stops me with error "check_new_file_create: load program: invalid argument: helper call is not allowed in probe".


Solution

  • Okay. I found an answer. For those, who need help with this question: read this article.

    Main part of this question is to find struct mount, whose field is struct vfsmount from struct path. To do this, you can use container_of (read this). So, with mount and dentry you can successfully restore path. (Kernel also can restore path to file in other mount namespace, I don't do this)