I am in the process of writing an eBPF probe for the nfs_getattr
function in which one of the parameters passed is a path
struct that represents the path whose attributes are being queried.
Given the path
struct, I need to determine the mount point from the client's perspective.
I've tried getting the value via the vfsmount
structure (path->mnt->mnt_root
), and by traversing the main dentry
up the tree (path->dentry->d_parent->...->d_parent
). Both approaches result in the nfs share being returned, not the mount point.
For instance, if I have the following mount command:
mount 127.0.0.1:/nfs-share /mnt/nfs-mount
The returned value from those aforementioned references is nfs-share
, but I'm interested in retrieving nfs-mount
.
What are the available approaches or solutions to achieve this? Any pointers or guidance would be greatly appreciated.
If it is a namespaced value, then I want to retrieve some id that I could resolve to the mount point in user-space.
I'm targeting kernel version 6.3.0 if it's relevant.
Thanks to this answer I've found a kernel function named follow_up that does what I need. Though I cannot use this function directly because it's not an eBPF function, it gave me the direction for the solution.
Using the container_of
macro it's possible to get the mount
struct, and inside it there is an mnt_mountpoint
dentry that points to the mount point.
struct mount* get_mount(const struct path *path)
{
if (!path)
return NULL;
struct vfsmount *vfsmount = BPF_CORE_READ(path, mnt);
if (!vfsmount)
return NULL;
struct mount *mnt = container_of(vfsmount, struct mount, mnt);
return mnt;
}
void get_mount_root(const struct path *path, char *buf, size_t size)
{
struct mount *mnt = get_mount(path);
if (!mnt)
return;
struct dentry *mnt_mountpoint = BPF_CORE_READ(mnt, mnt_mountpoint);
if (!mnt_mountpoint)
return;
struct qstr dname = BPF_CORE_READ(mnt_mountpoint, d_name);
bpf_probe_read_kernel(buf, size, dname.name);
}