~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/bpf/progs/task_kfunc_failure.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
  3 
  4 #include <vmlinux.h>
  5 #include <bpf/bpf_tracing.h>
  6 #include <bpf/bpf_helpers.h>
  7 
  8 #include "bpf_misc.h"
  9 #include "task_kfunc_common.h"
 10 
 11 char _license[] SEC("license") = "GPL";
 12 
 13 /* Prototype for all of the program trace events below:
 14  *
 15  * TRACE_EVENT(task_newtask,
 16  *         TP_PROTO(struct task_struct *p, u64 clone_flags)
 17  */
 18 
 19 static struct __tasks_kfunc_map_value *insert_lookup_task(struct task_struct *task)
 20 {
 21         int status;
 22 
 23         status = tasks_kfunc_map_insert(task);
 24         if (status)
 25                 return NULL;
 26 
 27         return tasks_kfunc_map_value_lookup(task);
 28 }
 29 
 30 SEC("tp_btf/task_newtask")
 31 __failure __msg("Possibly NULL pointer passed to trusted arg0")
 32 int BPF_PROG(task_kfunc_acquire_untrusted, struct task_struct *task, u64 clone_flags)
 33 {
 34         struct task_struct *acquired;
 35         struct __tasks_kfunc_map_value *v;
 36 
 37         v = insert_lookup_task(task);
 38         if (!v)
 39                 return 0;
 40 
 41         /* Can't invoke bpf_task_acquire() on an untrusted pointer. */
 42         acquired = bpf_task_acquire(v->task);
 43         if (!acquired)
 44                 return 0;
 45 
 46         bpf_task_release(acquired);
 47 
 48         return 0;
 49 }
 50 
 51 SEC("tp_btf/task_newtask")
 52 __failure __msg("arg#0 pointer type STRUCT task_struct must point")
 53 int BPF_PROG(task_kfunc_acquire_fp, struct task_struct *task, u64 clone_flags)
 54 {
 55         struct task_struct *acquired, *stack_task = (struct task_struct *)&clone_flags;
 56 
 57         /* Can't invoke bpf_task_acquire() on a random frame pointer. */
 58         acquired = bpf_task_acquire((struct task_struct *)&stack_task);
 59         if (!acquired)
 60                 return 0;
 61 
 62         bpf_task_release(acquired);
 63 
 64         return 0;
 65 }
 66 
 67 SEC("kretprobe/free_task")
 68 __failure __msg("calling kernel function bpf_task_acquire is not allowed")
 69 int BPF_PROG(task_kfunc_acquire_unsafe_kretprobe, struct task_struct *task, u64 clone_flags)
 70 {
 71         struct task_struct *acquired;
 72 
 73         /* Can't call bpf_task_acquire() or bpf_task_release() in an untrusted prog. */
 74         acquired = bpf_task_acquire(task);
 75         if (!acquired)
 76                 return 0;
 77         bpf_task_release(acquired);
 78 
 79         return 0;
 80 }
 81 
 82 SEC("kretprobe/free_task")
 83 __failure __msg("calling kernel function bpf_task_acquire is not allowed")
 84 int BPF_PROG(task_kfunc_acquire_unsafe_kretprobe_rcu, struct task_struct *task, u64 clone_flags)
 85 {
 86         struct task_struct *acquired;
 87 
 88         bpf_rcu_read_lock();
 89         if (!task) {
 90                 bpf_rcu_read_unlock();
 91                 return 0;
 92         }
 93         /* Can't call bpf_task_acquire() or bpf_task_release() in an untrusted prog. */
 94         acquired = bpf_task_acquire(task);
 95         if (acquired)
 96                 bpf_task_release(acquired);
 97         bpf_rcu_read_unlock();
 98 
 99         return 0;
100 }
101 
102 SEC("tp_btf/task_newtask")
103 __failure __msg("Possibly NULL pointer passed to trusted arg0")
104 int BPF_PROG(task_kfunc_acquire_null, struct task_struct *task, u64 clone_flags)
105 {
106         struct task_struct *acquired;
107 
108         /* Can't invoke bpf_task_acquire() on a NULL pointer. */
109         acquired = bpf_task_acquire(NULL);
110         if (!acquired)
111                 return 0;
112         bpf_task_release(acquired);
113 
114         return 0;
115 }
116 
117 SEC("tp_btf/task_newtask")
118 __failure __msg("Unreleased reference")
119 int BPF_PROG(task_kfunc_acquire_unreleased, struct task_struct *task, u64 clone_flags)
120 {
121         struct task_struct *acquired;
122 
123         acquired = bpf_task_acquire(task);
124 
125         /* Acquired task is never released. */
126         __sink(acquired);
127 
128         return 0;
129 }
130 
131 SEC("tp_btf/task_newtask")
132 __failure __msg("Unreleased reference")
133 int BPF_PROG(task_kfunc_xchg_unreleased, struct task_struct *task, u64 clone_flags)
134 {
135         struct task_struct *kptr;
136         struct __tasks_kfunc_map_value *v;
137 
138         v = insert_lookup_task(task);
139         if (!v)
140                 return 0;
141 
142         kptr = bpf_kptr_xchg(&v->task, NULL);
143         if (!kptr)
144                 return 0;
145 
146         /* Kptr retrieved from map is never released. */
147 
148         return 0;
149 }
150 
151 SEC("tp_btf/task_newtask")
152 __failure __msg("Possibly NULL pointer passed to trusted arg0")
153 int BPF_PROG(task_kfunc_acquire_release_no_null_check, struct task_struct *task, u64 clone_flags)
154 {
155         struct task_struct *acquired;
156 
157         acquired = bpf_task_acquire(task);
158         /* Can't invoke bpf_task_release() on an acquired task without a NULL check. */
159         bpf_task_release(acquired);
160 
161         return 0;
162 }
163 
164 SEC("tp_btf/task_newtask")
165 __failure __msg("Possibly NULL pointer passed to trusted arg0")
166 int BPF_PROG(task_kfunc_release_untrusted, struct task_struct *task, u64 clone_flags)
167 {
168         struct __tasks_kfunc_map_value *v;
169 
170         v = insert_lookup_task(task);
171         if (!v)
172                 return 0;
173 
174         /* Can't invoke bpf_task_release() on an untrusted pointer. */
175         bpf_task_release(v->task);
176 
177         return 0;
178 }
179 
180 SEC("tp_btf/task_newtask")
181 __failure __msg("arg#0 pointer type STRUCT task_struct must point")
182 int BPF_PROG(task_kfunc_release_fp, struct task_struct *task, u64 clone_flags)
183 {
184         struct task_struct *acquired = (struct task_struct *)&clone_flags;
185 
186         /* Cannot release random frame pointer. */
187         bpf_task_release(acquired);
188 
189         return 0;
190 }
191 
192 SEC("tp_btf/task_newtask")
193 __failure __msg("Possibly NULL pointer passed to trusted arg0")
194 int BPF_PROG(task_kfunc_release_null, struct task_struct *task, u64 clone_flags)
195 {
196         struct __tasks_kfunc_map_value local, *v;
197         long status;
198         struct task_struct *acquired, *old;
199         s32 pid;
200 
201         status = bpf_probe_read_kernel(&pid, sizeof(pid), &task->pid);
202         if (status)
203                 return 0;
204 
205         local.task = NULL;
206         status = bpf_map_update_elem(&__tasks_kfunc_map, &pid, &local, BPF_NOEXIST);
207         if (status)
208                 return status;
209 
210         v = bpf_map_lookup_elem(&__tasks_kfunc_map, &pid);
211         if (!v)
212                 return -ENOENT;
213 
214         acquired = bpf_task_acquire(task);
215         if (!acquired)
216                 return -EEXIST;
217 
218         old = bpf_kptr_xchg(&v->task, acquired);
219 
220         /* old cannot be passed to bpf_task_release() without a NULL check. */
221         bpf_task_release(old);
222 
223         return 0;
224 }
225 
226 SEC("tp_btf/task_newtask")
227 __failure __msg("release kernel function bpf_task_release expects")
228 int BPF_PROG(task_kfunc_release_unacquired, struct task_struct *task, u64 clone_flags)
229 {
230         /* Cannot release trusted task pointer which was not acquired. */
231         bpf_task_release(task);
232 
233         return 0;
234 }
235 
236 SEC("tp_btf/task_newtask")
237 __failure __msg("Possibly NULL pointer passed to trusted arg0")
238 int BPF_PROG(task_kfunc_from_pid_no_null_check, struct task_struct *task, u64 clone_flags)
239 {
240         struct task_struct *acquired;
241 
242         acquired = bpf_task_from_pid(task->pid);
243 
244         /* Releasing bpf_task_from_pid() lookup without a NULL check. */
245         bpf_task_release(acquired);
246 
247         return 0;
248 }
249 
250 SEC("lsm/task_free")
251 __failure __msg("R1 must be a rcu pointer")
252 int BPF_PROG(task_kfunc_from_lsm_task_free, struct task_struct *task)
253 {
254         struct task_struct *acquired;
255 
256         /* the argument of lsm task_free hook is untrusted. */
257         acquired = bpf_task_acquire(task);
258         if (!acquired)
259                 return 0;
260 
261         bpf_task_release(acquired);
262         return 0;
263 }
264 
265 SEC("tp_btf/task_newtask")
266 __failure __msg("access beyond the end of member comm")
267 int BPF_PROG(task_access_comm1, struct task_struct *task, u64 clone_flags)
268 {
269         bpf_strncmp(task->comm, 17, "foo");
270         return 0;
271 }
272 
273 SEC("tp_btf/task_newtask")
274 __failure __msg("access beyond the end of member comm")
275 int BPF_PROG(task_access_comm2, struct task_struct *task, u64 clone_flags)
276 {
277         bpf_strncmp(task->comm + 1, 16, "foo");
278         return 0;
279 }
280 
281 SEC("tp_btf/task_newtask")
282 __failure __msg("write into memory")
283 int BPF_PROG(task_access_comm3, struct task_struct *task, u64 clone_flags)
284 {
285         bpf_probe_read_kernel(task->comm, 16, task->comm);
286         return 0;
287 }
288 
289 SEC("fentry/__set_task_comm")
290 __failure __msg("R1 type=ptr_ expected")
291 int BPF_PROG(task_access_comm4, struct task_struct *task, const char *buf, bool exec)
292 {
293         /*
294          * task->comm is a legacy ptr_to_btf_id. The verifier cannot guarantee
295          * its safety. Hence it cannot be accessed with normal load insns.
296          */
297         bpf_strncmp(task->comm, 16, "foo");
298         return 0;
299 }
300 
301 SEC("tp_btf/task_newtask")
302 __failure __msg("R1 must be referenced or trusted")
303 int BPF_PROG(task_kfunc_release_in_map, struct task_struct *task, u64 clone_flags)
304 {
305         struct task_struct *local;
306         struct __tasks_kfunc_map_value *v;
307 
308         if (tasks_kfunc_map_insert(task))
309                 return 0;
310 
311         v = tasks_kfunc_map_value_lookup(task);
312         if (!v)
313                 return 0;
314 
315         bpf_rcu_read_lock();
316         local = v->task;
317         if (!local) {
318                 bpf_rcu_read_unlock();
319                 return 0;
320         }
321         /* Can't release a kptr that's still stored in a map. */
322         bpf_task_release(local);
323         bpf_rcu_read_unlock();
324 
325         return 0;
326 }
327 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php