Skip to content

Commit 82a7bc8

Browse files
committed
feat(ebpf): use bpf_loop for local d_path implementation
Part of ROX-32059. The local implementation of d_path now uses bpf_loop, which enables it to iterate further than the previously implemented loop that did at most 16 levels of path.
1 parent 37d5783 commit 82a7bc8

File tree

1 file changed

+70
-50
lines changed

1 file changed

+70
-50
lines changed

fact-ebpf/src/bpf/d_path.h

Lines changed: 70 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,64 @@
88
#include <bpf/bpf_core_read.h>
99
// clang-format on
1010

11+
struct d_path_ctx {
12+
struct helper_t* helper;
13+
struct path root;
14+
struct mount* mnt;
15+
struct dentry* dentry;
16+
int offset;
17+
int buflen;
18+
bool success;
19+
};
20+
21+
static long __d_path_inner(uint32_t index, void* _ctx) {
22+
struct d_path_ctx* ctx = (struct d_path_ctx*)_ctx;
23+
struct dentry* dentry = ctx->dentry;
24+
struct dentry* parent = BPF_CORE_READ(dentry, d_parent);
25+
struct mount* mnt = ctx->mnt;
26+
struct dentry* mnt_root = BPF_CORE_READ(mnt, mnt.mnt_root);
27+
28+
if (dentry == mnt_root) {
29+
struct mount* m = BPF_CORE_READ(mnt, mnt_parent);
30+
if (m != mnt) {
31+
ctx->dentry = BPF_CORE_READ(mnt, mnt_mountpoint);
32+
ctx->mnt = m;
33+
return 0;
34+
}
35+
ctx->success = true;
36+
return 1;
37+
}
38+
39+
if (dentry == parent) {
40+
return 1;
41+
}
42+
43+
struct qstr d_name;
44+
BPF_CORE_READ_INTO(&d_name, dentry, d_name);
45+
int len = d_name.len;
46+
if (len <= 0 || len >= ctx->buflen) {
47+
return 1;
48+
}
49+
50+
ctx->offset -= len;
51+
if (ctx->offset <= 0) {
52+
return 1;
53+
}
54+
55+
if (bpf_probe_read_kernel(&ctx->helper->buf[ctx->offset], len, d_name.name) != 0) {
56+
return 1;
57+
}
58+
59+
ctx->offset--;
60+
if (ctx->offset <= 0) {
61+
return 1;
62+
}
63+
ctx->helper->buf[ctx->offset] = '/';
64+
65+
ctx->dentry = parent;
66+
return 0;
67+
}
68+
1169
/**
1270
* Reimplementation of the kernel d_path function.
1371
*
@@ -19,65 +77,27 @@ __always_inline static long __d_path(const struct path* path, char* buf, int buf
1977
return -1;
2078
}
2179

22-
struct helper_t* helper = get_helper();
23-
if (helper == NULL) {
80+
struct d_path_ctx ctx = {0};
81+
82+
ctx.helper = get_helper();
83+
if (ctx.helper == NULL) {
2484
return -1;
2585
}
2686

2787
struct task_struct* task = (struct task_struct*)bpf_get_current_task();
2888
int offset = (buflen - 1) & (PATH_MAX - 1);
29-
helper->buf[offset] = '\0'; // Ensure null termination
30-
31-
struct path root;
32-
BPF_CORE_READ_INTO(&root, task, fs, root);
33-
struct mount* mnt = container_of(path->mnt, struct mount, mnt);
34-
struct dentry* dentry;
35-
BPF_CORE_READ_INTO(&dentry, path, dentry);
36-
37-
for (int i = 0; i < 16 && (dentry != root.dentry || &mnt->mnt != root.mnt); i++) {
38-
struct dentry* parent = BPF_CORE_READ(dentry, d_parent);
39-
struct dentry* mnt_root = BPF_CORE_READ(mnt, mnt.mnt_root);
40-
41-
if (dentry == mnt_root) {
42-
struct mount* m = BPF_CORE_READ(mnt, mnt_parent);
43-
if (m != mnt) {
44-
dentry = BPF_CORE_READ(mnt, mnt_mountpoint);
45-
mnt = m;
46-
continue;
47-
}
48-
break;
49-
}
50-
51-
if (dentry == parent) {
52-
return -1;
53-
}
89+
ctx.helper->buf[offset] = '\0'; // Ensure null termination
5490

55-
struct qstr d_name;
56-
BPF_CORE_READ_INTO(&d_name, dentry, d_name);
57-
int len = d_name.len;
58-
if (len <= 0 || len >= buflen) {
59-
return -1;
60-
}
61-
62-
offset -= len;
63-
if (offset <= 0) {
64-
return -1;
65-
}
66-
67-
if (bpf_probe_read_kernel(&helper->buf[offset], len, d_name.name) != 0) {
68-
return -1;
69-
}
70-
71-
offset--;
72-
if (offset <= 0) {
73-
return -1;
74-
}
75-
helper->buf[offset] = '/';
91+
BPF_CORE_READ_INTO(&ctx.root, task, fs, root);
92+
ctx.mnt = container_of(path->mnt, struct mount, mnt);
93+
BPF_CORE_READ_INTO(&ctx.dentry, path, dentry);
7694

77-
dentry = parent;
95+
long res = bpf_loop(PATH_MAX, __d_path_inner, &ctx, 0);
96+
if (res <= 0 || !ctx.success) {
97+
return -1;
7898
}
7999

80-
bpf_probe_read_str(buf, buflen, &helper->buf[offset]);
100+
bpf_probe_read_str(buf, buflen, &ctx.helper->buf[offset]);
81101
return buflen - offset;
82102
}
83103

0 commit comments

Comments
 (0)