Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions libbpf-tools/opensnoop.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,18 @@ int trace_exit(struct syscall_trace_exit* ctx)
if (full_path && eventp->fname[0] != '/') {
int depth;
struct task_struct *task;
struct dentry *dentry, *parent_dentry;
struct dentry *dentry, *parent_dentry, *mnt_root;
struct vfsmount *vfsmnt;
struct mount *mnt;
size_t filepart_length;
void *payload = eventp->fname;
char *payload = eventp->fname;


task = (struct task_struct *)bpf_get_current_task_btf();
dentry = BPF_CORE_READ(task, fs, pwd.dentry);
vfsmnt = BPF_CORE_READ(task, fs, pwd.mnt);
mnt = container_of(vfsmnt, struct mount, mnt);
mnt_root = BPF_CORE_READ(vfsmnt, mnt_root);

for (depth = 1, payload += NAME_MAX; depth < MAX_PATH_DEPTH; depth++) {
filepart_length =
Expand All @@ -173,13 +178,32 @@ int trace_exit(struct syscall_trace_exit* ctx)
break;
}

parent_dentry = BPF_CORE_READ(dentry, d_parent);
if (dentry == parent_dentry)
break;

if (filepart_length > NAME_MAX)
break;

parent_dentry = BPF_CORE_READ(dentry, d_parent);

if (dentry == parent_dentry || dentry == mnt_root) {
struct mount *mnt_parent;
mnt_parent = BPF_CORE_READ(mnt, mnt_parent);

if (mnt != mnt_parent) {
dentry = BPF_CORE_READ(mnt, mnt_mountpoint);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, correctly, dentry here is a 'hidden' dentry to facilitate path traversal. So after this, we should do dentry = BPF_CORE_READ(dentry, d_parent);?

Please look at this upstream patch https://lore.kernel.org/bpf/20250611220220.3681382-2-song@kernel.org/ to double check.

Copy link
Contributor Author

@Rtoax Rtoax Jun 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried, but tracking the wrong path

diff --git a/libbpf-tools/opensnoop.bpf.c b/libbpf-tools/opensnoop.bpf.c
index 64d931a8..08510e42 100644
--- a/libbpf-tools/opensnoop.bpf.c
+++ b/libbpf-tools/opensnoop.bpf.c
@@ -189,6 +189,7 @@ int trace_exit(struct syscall_trace_exit* ctx)
 
                                if (mnt != mnt_parent) {
                                        dentry = BPF_CORE_READ(mnt, mnt_mountpoint);
+                                       dentry = BPF_CORE_READ(dentry, d_parent);
 
                                        mnt = mnt_parent;
                                        vfsmnt = &mnt->mnt;

For example:

    $ mount | grep sda
    /dev/sda on /home/sda type xfs ...

    /home/sda/rongtao/a.out
          ^^^
          [1]

    /* get 'rongtao' mount point 'sda' */
[1] dentry = BPF_CORE_READ(mnt, mnt_mountpoint);
[2] dentry = BPF_CORE_READ(dentry, d_parent);

so, i think there is no need [2] after [1], right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried a nested mount example. You are right, the [2] is not needed.


mnt = mnt_parent;
vfsmnt = &mnt->mnt;

mnt_root = BPF_CORE_READ(vfsmnt, mnt_root);

eventp->path_depth++;
payload += NAME_MAX;
continue;
} else {
/* Real root directory */
break;
}
}

payload += NAME_MAX;

dentry = parent_dentry;
Expand Down
14 changes: 12 additions & 2 deletions libbpf-tools/opensnoop.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,16 @@ int handle_event(void *ctx, void *data, size_t data_sz)
sps_cnt += 9;
}
if (env.full_path) {
for (int depth = e.path_depth; depth >= 0; depth--)
for (int depth = e.path_depth; depth >= 0; depth--) {
char *fname = (char *)&e.fname[NAME_MAX * depth];

/**
* If it is a mount point, there will be a '/', because
* the '/' will be added below, so just skip this '/'.
*/
if (fname[0] == '/' && fname[1] == '\0')
continue;

/**
* 1. If the file/path name starts with '/', do not
* print the '/' prefix.
Expand All @@ -281,7 +290,8 @@ int handle_event(void *ctx, void *data, size_t data_sz)
"/\0" + (e.fname[NAME_MAX * depth] == '/' ||
((e.get_path_failed || e.path_depth == MAX_PATH_DEPTH - 1) &&
depth == e.path_depth)),
(char *)&e.fname[NAME_MAX * depth]);
fname);
}
printf("\n");
} else
printf("%s\n", e.fname);
Expand Down
Loading