11#pragma once
22
33// clang-format off
4- #include "maps.h"
54#include "vmlinux.h"
65
6+ #include "maps.h"
7+
78#include <bpf/bpf_helpers.h>
89#include <bpf/bpf_core_read.h>
910// clang-format on
1011
12+ struct d_path_ctx {
13+ struct helper_t * helper ;
14+ struct path root ;
15+ struct mount * mnt ;
16+ struct dentry * dentry ;
17+ int offset ;
18+ int buflen ;
19+ bool success ;
20+ };
21+
22+ static long __d_path_inner (uint32_t index , void * _ctx ) {
23+ struct d_path_ctx * ctx = (struct d_path_ctx * )_ctx ;
24+ struct dentry * dentry = ctx -> dentry ;
25+ struct dentry * parent = BPF_CORE_READ (dentry , d_parent );
26+ struct mount * mnt = ctx -> mnt ;
27+ struct dentry * mnt_root = BPF_CORE_READ (mnt , mnt .mnt_root );
28+
29+ if (dentry == mnt_root ) {
30+ struct mount * m = BPF_CORE_READ (mnt , mnt_parent );
31+ if (m != mnt ) {
32+ ctx -> dentry = BPF_CORE_READ (mnt , mnt_mountpoint );
33+ ctx -> mnt = m ;
34+ return 0 ;
35+ }
36+ ctx -> success = true;
37+ return 1 ;
38+ }
39+
40+ if (dentry == parent ) {
41+ return 1 ;
42+ }
43+
44+ struct qstr d_name ;
45+ BPF_CORE_READ_INTO (& d_name , dentry , d_name );
46+ int len = d_name .len & (PATH_MAX - 1 );
47+ if (len <= 0 || len >= ctx -> buflen ) {
48+ return 1 ;
49+ }
50+
51+ int offset = ctx -> offset - len ;
52+ if (offset <= 0 ) {
53+ return 1 ;
54+ }
55+ offset &= PATH_MAX - 1 ;
56+
57+ if (bpf_probe_read_kernel (& ctx -> helper -> buf [offset ], len , d_name .name ) != 0 ) {
58+ return 1 ;
59+ }
60+
61+ offset -- ;
62+ if (offset <= 0 ) {
63+ return 1 ;
64+ }
65+ ctx -> helper -> buf [offset ] = '/' ;
66+
67+ ctx -> offset = offset ;
68+ ctx -> dentry = parent ;
69+ return 0 ;
70+ }
71+
1172/**
1273 * Reimplementation of the kernel d_path function.
1374 *
@@ -19,66 +80,30 @@ __always_inline static long __d_path(const struct path* path, char* buf, int buf
1980 return -1 ;
2081 }
2182
22- struct helper_t * helper = get_helper ();
23- if (helper == NULL ) {
83+ struct d_path_ctx ctx = {
84+ .buflen = buflen ,
85+ .helper = get_helper (),
86+ .offset = (buflen - 1 ) & (PATH_MAX - 1 ),
87+ };
88+
89+ if (ctx .helper == NULL ) {
2490 return -1 ;
2591 }
2692
2793 struct task_struct * task = (struct task_struct * )bpf_get_current_task ();
28- int offset = (buflen - 1 ) & (PATH_MAX - 1 );
29- helper -> buf [offset ] = '\0' ; // Ensure null termination
94+ ctx .helper -> buf [ctx .offset & (PATH_MAX - 1 )] = '\0' ; // Ensure null termination
3095
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- }
96+ BPF_CORE_READ_INTO (& ctx .root , task , fs , root );
97+ ctx .mnt = container_of (path -> mnt , struct mount , mnt );
98+ BPF_CORE_READ_INTO (& ctx .dentry , path , dentry );
5499
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 ] = '/' ;
76-
77- dentry = parent ;
100+ long res = bpf_loop (PATH_MAX , __d_path_inner , & ctx , 0 );
101+ if (res <= 0 || !ctx .success ) {
102+ return -1 ;
78103 }
79104
80- bpf_probe_read_str (buf , buflen , & helper -> buf [offset ]);
81- return buflen - offset ;
105+ bpf_probe_read_str (buf , buflen , & ctx . helper -> buf [ctx . offset & ( PATH_MAX - 1 ) ]);
106+ return buflen - ctx . offset ;
82107}
83108
84109__always_inline static long d_path (struct path * path , char * buf , int buflen , bool use_bpf_helper ) {
0 commit comments