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