Can somebody help me with retrieving name of file using eBPF when file is creating?
What I’ve done:
bpf_d_path & bpf_path_d_path.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".
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)