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 bpf_task_release(acquired); 44 45 return 0; 46 } 47 48 SEC("tp_btf/task_newtask") 49 __failure __msg("arg#0 pointer type STRUCT task_struct must point") 50 int BPF_PROG(task_kfunc_acquire_fp, struct task_struct *task, u64 clone_flags) 51 { 52 struct task_struct *acquired, *stack_task = (struct task_struct *)&clone_flags; 53 54 /* Can't invoke bpf_task_acquire() on a random frame pointer. */ 55 acquired = bpf_task_acquire((struct task_struct *)&stack_task); 56 bpf_task_release(acquired); 57 58 return 0; 59 } 60 61 SEC("kretprobe/free_task") 62 __failure __msg("reg type unsupported for arg#0 function") 63 int BPF_PROG(task_kfunc_acquire_unsafe_kretprobe, struct task_struct *task, u64 clone_flags) 64 { 65 struct task_struct *acquired; 66 67 acquired = bpf_task_acquire(task); 68 /* Can't release a bpf_task_acquire()'d task without a NULL check. */ 69 bpf_task_release(acquired); 70 71 return 0; 72 } 73 74 SEC("tp_btf/task_newtask") 75 __failure __msg("R1 must be referenced or trusted") 76 int BPF_PROG(task_kfunc_acquire_trusted_walked, struct task_struct *task, u64 clone_flags) 77 { 78 struct task_struct *acquired; 79 80 /* Can't invoke bpf_task_acquire() on a trusted pointer obtained from walking a struct. */ 81 acquired = bpf_task_acquire(task->group_leader); 82 bpf_task_release(acquired); 83 84 return 0; 85 } 86 87 88 SEC("tp_btf/task_newtask") 89 __failure __msg("Possibly NULL pointer passed to trusted arg0") 90 int BPF_PROG(task_kfunc_acquire_null, struct task_struct *task, u64 clone_flags) 91 { 92 struct task_struct *acquired; 93 94 /* Can't invoke bpf_task_acquire() on a NULL pointer. */ 95 acquired = bpf_task_acquire(NULL); 96 if (!acquired) 97 return 0; 98 bpf_task_release(acquired); 99 100 return 0; 101 } 102 103 SEC("tp_btf/task_newtask") 104 __failure __msg("Unreleased reference") 105 int BPF_PROG(task_kfunc_acquire_unreleased, struct task_struct *task, u64 clone_flags) 106 { 107 struct task_struct *acquired; 108 109 acquired = bpf_task_acquire(task); 110 111 /* Acquired task is never released. */ 112 113 return 0; 114 } 115 116 SEC("tp_btf/task_newtask") 117 __failure __msg("arg#0 expected pointer to map value") 118 int BPF_PROG(task_kfunc_get_non_kptr_param, struct task_struct *task, u64 clone_flags) 119 { 120 struct task_struct *kptr; 121 122 /* Cannot use bpf_task_kptr_get() on a non-kptr, even on a valid task. */ 123 kptr = bpf_task_kptr_get(&task); 124 if (!kptr) 125 return 0; 126 127 bpf_task_release(kptr); 128 129 return 0; 130 } 131 132 SEC("tp_btf/task_newtask") 133 __failure __msg("arg#0 expected pointer to map value") 134 int BPF_PROG(task_kfunc_get_non_kptr_acquired, struct task_struct *task, u64 clone_flags) 135 { 136 struct task_struct *kptr, *acquired; 137 138 acquired = bpf_task_acquire(task); 139 140 /* Cannot use bpf_task_kptr_get() on a non-kptr, even if it was acquired. */ 141 kptr = bpf_task_kptr_get(&acquired); 142 bpf_task_release(acquired); 143 if (!kptr) 144 return 0; 145 146 bpf_task_release(kptr); 147 148 return 0; 149 } 150 151 SEC("tp_btf/task_newtask") 152 __failure __msg("arg#0 expected pointer to map value") 153 int BPF_PROG(task_kfunc_get_null, struct task_struct *task, u64 clone_flags) 154 { 155 struct task_struct *kptr; 156 157 /* Cannot use bpf_task_kptr_get() on a NULL pointer. */ 158 kptr = bpf_task_kptr_get(NULL); 159 if (!kptr) 160 return 0; 161 162 bpf_task_release(kptr); 163 164 return 0; 165 } 166 167 SEC("tp_btf/task_newtask") 168 __failure __msg("Unreleased reference") 169 int BPF_PROG(task_kfunc_xchg_unreleased, struct task_struct *task, u64 clone_flags) 170 { 171 struct task_struct *kptr; 172 struct __tasks_kfunc_map_value *v; 173 174 v = insert_lookup_task(task); 175 if (!v) 176 return 0; 177 178 kptr = bpf_kptr_xchg(&v->task, NULL); 179 if (!kptr) 180 return 0; 181 182 /* Kptr retrieved from map is never released. */ 183 184 return 0; 185 } 186 187 SEC("tp_btf/task_newtask") 188 __failure __msg("Unreleased reference") 189 int BPF_PROG(task_kfunc_get_unreleased, struct task_struct *task, u64 clone_flags) 190 { 191 struct task_struct *kptr; 192 struct __tasks_kfunc_map_value *v; 193 194 v = insert_lookup_task(task); 195 if (!v) 196 return 0; 197 198 kptr = bpf_task_kptr_get(&v->task); 199 if (!kptr) 200 return 0; 201 202 /* Kptr acquired above is never released. */ 203 204 return 0; 205 } 206 207 SEC("tp_btf/task_newtask") 208 __failure __msg("arg#0 is untrusted_ptr_or_null_ expected ptr_ or socket") 209 int BPF_PROG(task_kfunc_release_untrusted, struct task_struct *task, u64 clone_flags) 210 { 211 struct __tasks_kfunc_map_value *v; 212 213 v = insert_lookup_task(task); 214 if (!v) 215 return 0; 216 217 /* Can't invoke bpf_task_release() on an untrusted pointer. */ 218 bpf_task_release(v->task); 219 220 return 0; 221 } 222 223 SEC("tp_btf/task_newtask") 224 __failure __msg("arg#0 pointer type STRUCT task_struct must point") 225 int BPF_PROG(task_kfunc_release_fp, struct task_struct *task, u64 clone_flags) 226 { 227 struct task_struct *acquired = (struct task_struct *)&clone_flags; 228 229 /* Cannot release random frame pointer. */ 230 bpf_task_release(acquired); 231 232 return 0; 233 } 234 235 SEC("tp_btf/task_newtask") 236 __failure __msg("arg#0 is ptr_or_null_ expected ptr_ or socket") 237 int BPF_PROG(task_kfunc_release_null, struct task_struct *task, u64 clone_flags) 238 { 239 struct __tasks_kfunc_map_value local, *v; 240 long status; 241 struct task_struct *acquired, *old; 242 s32 pid; 243 244 status = bpf_probe_read_kernel(&pid, sizeof(pid), &task->pid); 245 if (status) 246 return 0; 247 248 local.task = NULL; 249 status = bpf_map_update_elem(&__tasks_kfunc_map, &pid, &local, BPF_NOEXIST); 250 if (status) 251 return status; 252 253 v = bpf_map_lookup_elem(&__tasks_kfunc_map, &pid); 254 if (!v) 255 return -ENOENT; 256 257 acquired = bpf_task_acquire(task); 258 259 old = bpf_kptr_xchg(&v->task, acquired); 260 261 /* old cannot be passed to bpf_task_release() without a NULL check. */ 262 bpf_task_release(old); 263 bpf_task_release(old); 264 265 return 0; 266 } 267 268 SEC("tp_btf/task_newtask") 269 __failure __msg("release kernel function bpf_task_release expects") 270 int BPF_PROG(task_kfunc_release_unacquired, struct task_struct *task, u64 clone_flags) 271 { 272 /* Cannot release trusted task pointer which was not acquired. */ 273 bpf_task_release(task); 274 275 return 0; 276 } 277 278 SEC("tp_btf/task_newtask") 279 __failure __msg("arg#0 is ptr_or_null_ expected ptr_ or socket") 280 int BPF_PROG(task_kfunc_from_pid_no_null_check, struct task_struct *task, u64 clone_flags) 281 { 282 struct task_struct *acquired; 283 284 acquired = bpf_task_from_pid(task->pid); 285 286 /* Releasing bpf_task_from_pid() lookup without a NULL check. */ 287 bpf_task_release(acquired); 288 289 return 0; 290 } 291 292 SEC("lsm/task_free") 293 __failure __msg("reg type unsupported for arg#0 function") 294 int BPF_PROG(task_kfunc_from_lsm_task_free, struct task_struct *task) 295 { 296 struct task_struct *acquired; 297 298 /* the argument of lsm task_free hook is untrusted. */ 299 acquired = bpf_task_acquire(task); 300 bpf_task_release(acquired); 301 return 0; 302 } 303