1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ 3 4 #include <vmlinux.h> 5 #include <bpf/bpf_helpers.h> 6 #include <bpf/bpf_tracing.h> 7 #include <bpf/bpf_core_read.h> 8 #include "bpf_misc.h" 9 #include "xdp_metadata.h" 10 #include "bpf_kfuncs.h" 11 12 extern struct task_struct *bpf_task_acquire(struct task_struct *p) __ksym __weak; 13 extern void bpf_task_release(struct task_struct *p) __ksym __weak; 14 15 __weak int subprog_trusted_task_nullable(struct task_struct *task __arg_trusted __arg_nullable) 16 { 17 if (!task) 18 return 0; 19 return task->pid + task->tgid; 20 } 21 22 __weak int subprog_trusted_task_nullable_extra_layer(struct task_struct *task __arg_trusted __arg_nullable) 23 { 24 return subprog_trusted_task_nullable(task) + subprog_trusted_task_nullable(NULL); 25 } 26 27 SEC("?tp_btf/task_newtask") 28 __success __log_level(2) 29 __msg("Validating subprog_trusted_task_nullable() func#1...") 30 __msg(": R1=trusted_ptr_or_null_task_struct(") 31 int trusted_task_arg_nullable(void *ctx) 32 { 33 struct task_struct *t1 = bpf_get_current_task_btf(); 34 struct task_struct *t2 = bpf_task_acquire(t1); 35 int res = 0; 36 37 /* known NULL */ 38 res += subprog_trusted_task_nullable(NULL); 39 40 /* known non-NULL */ 41 res += subprog_trusted_task_nullable(t1); 42 res += subprog_trusted_task_nullable_extra_layer(t1); 43 44 /* unknown if NULL or not */ 45 res += subprog_trusted_task_nullable(t2); 46 res += subprog_trusted_task_nullable_extra_layer(t2); 47 48 if (t2) { 49 /* known non-NULL after explicit NULL check, just in case */ 50 res += subprog_trusted_task_nullable(t2); 51 res += subprog_trusted_task_nullable_extra_layer(t2); 52 53 bpf_task_release(t2); 54 } 55 56 return res; 57 } 58 59 __weak int subprog_trusted_task_nonnull(struct task_struct *task __arg_trusted) 60 { 61 return task->pid + task->tgid; 62 } 63 64 SEC("?kprobe") 65 __failure __log_level(2) 66 __msg("R1 type=scalar expected=ptr_, trusted_ptr_, rcu_ptr_") 67 __msg("Caller passes invalid args into func#1 ('subprog_trusted_task_nonnull')") 68 int trusted_task_arg_nonnull_fail1(void *ctx) 69 { 70 return subprog_trusted_task_nonnull(NULL); 71 } 72 73 SEC("?tp_btf/task_newtask") 74 __failure __log_level(2) 75 __msg("R1 type=ptr_or_null_ expected=ptr_, trusted_ptr_, rcu_ptr_") 76 __msg("Caller passes invalid args into func#1 ('subprog_trusted_task_nonnull')") 77 int trusted_task_arg_nonnull_fail2(void *ctx) 78 { 79 struct task_struct *t = bpf_get_current_task_btf(); 80 struct task_struct *nullable; 81 int res; 82 83 nullable = bpf_task_acquire(t); 84 85 /* should fail, PTR_TO_BTF_ID_OR_NULL */ 86 res = subprog_trusted_task_nonnull(nullable); 87 88 if (nullable) 89 bpf_task_release(nullable); 90 91 return res; 92 } 93 94 SEC("?kprobe") 95 __success __log_level(2) 96 __msg("Validating subprog_trusted_task_nonnull() func#1...") 97 __msg(": R1=trusted_ptr_task_struct(") 98 int trusted_task_arg_nonnull(void *ctx) 99 { 100 struct task_struct *t = bpf_get_current_task_btf(); 101 102 return subprog_trusted_task_nonnull(t); 103 } 104 105 struct task_struct___local {} __attribute__((preserve_access_index)); 106 107 __weak int subprog_nullable_task_flavor( 108 struct task_struct___local *task __arg_trusted __arg_nullable) 109 { 110 char buf[16]; 111 112 if (!task) 113 return 0; 114 115 return bpf_copy_from_user_task(&buf, sizeof(buf), NULL, (void *)task, 0); 116 } 117 118 SEC("?uprobe.s") 119 __success __log_level(2) 120 __msg("Validating subprog_nullable_task_flavor() func#1...") 121 __msg(": R1=trusted_ptr_or_null_task_struct(") 122 int flavor_ptr_nullable(void *ctx) 123 { 124 struct task_struct___local *t = (void *)bpf_get_current_task_btf(); 125 126 return subprog_nullable_task_flavor(t); 127 } 128 129 __weak int subprog_nonnull_task_flavor(struct task_struct___local *task __arg_trusted) 130 { 131 char buf[16]; 132 133 return bpf_copy_from_user_task(&buf, sizeof(buf), NULL, (void *)task, 0); 134 } 135 136 SEC("?uprobe.s") 137 __success __log_level(2) 138 __msg("Validating subprog_nonnull_task_flavor() func#1...") 139 __msg(": R1=trusted_ptr_task_struct(") 140 int flavor_ptr_nonnull(void *ctx) 141 { 142 struct task_struct *t = bpf_get_current_task_btf(); 143 144 return subprog_nonnull_task_flavor((void *)t); 145 } 146 147 __weak int subprog_trusted_destroy(struct task_struct *task __arg_trusted) 148 { 149 bpf_task_release(task); /* should be rejected */ 150 151 return 0; 152 } 153 154 SEC("?tp_btf/task_newtask") 155 __failure __log_level(2) 156 __msg("release kernel function bpf_task_release expects refcounted PTR_TO_BTF_ID") 157 int BPF_PROG(trusted_destroy_fail, struct task_struct *task, u64 clone_flags) 158 { 159 return subprog_trusted_destroy(task); 160 } 161 162 __weak int subprog_trusted_acq_rel(struct task_struct *task __arg_trusted) 163 { 164 struct task_struct *owned; 165 166 owned = bpf_task_acquire(task); 167 if (!owned) 168 return 0; 169 170 bpf_task_release(owned); /* this one is OK, we acquired it locally */ 171 172 return 0; 173 } 174 175 SEC("?tp_btf/task_newtask") 176 __success __log_level(2) 177 int BPF_PROG(trusted_acq_rel, struct task_struct *task, u64 clone_flags) 178 { 179 return subprog_trusted_acq_rel(task); 180 } 181 182 __weak int subprog_untrusted_bad_tags(struct task_struct *task __arg_untrusted __arg_nullable) 183 { 184 return task->pid; 185 } 186 187 SEC("tp_btf/sys_enter") 188 __failure 189 __msg("arg#0 untrusted cannot be combined with any other tags") 190 int untrusted_bad_tags(void *ctx) 191 { 192 return subprog_untrusted_bad_tags(0); 193 } 194 195 struct local_type_wont_be_accepted {}; 196 197 __weak int subprog_untrusted_bad_type(struct local_type_wont_be_accepted *p __arg_untrusted) 198 { 199 return 0; 200 } 201 202 SEC("tp_btf/sys_enter") 203 __failure 204 __msg("arg#0 reference type('STRUCT local_type_wont_be_accepted') has no matches") 205 int untrusted_bad_type(void *ctx) 206 { 207 return subprog_untrusted_bad_type(bpf_rdonly_cast(0, 0)); 208 } 209 210 __weak int subprog_untrusted(const volatile struct task_struct *restrict task __arg_untrusted) 211 { 212 return task->pid; 213 } 214 215 SEC("tp_btf/sys_enter") 216 __success 217 __log_level(2) 218 __msg("r1 = {{.*}}; {{.*}}R1_w=trusted_ptr_task_struct()") 219 __msg("Func#1 ('subprog_untrusted') is global and assumed valid.") 220 __msg("Validating subprog_untrusted() func#1...") 221 __msg(": R1=untrusted_ptr_task_struct") 222 int trusted_to_untrusted(void *ctx) 223 { 224 return subprog_untrusted(bpf_get_current_task_btf()); 225 } 226 227 char mem[16]; 228 u32 off; 229 230 SEC("tp_btf/sys_enter") 231 __success 232 int anything_to_untrusted(void *ctx) 233 { 234 /* untrusted to untrusted */ 235 subprog_untrusted(bpf_core_cast(0, struct task_struct)); 236 /* wrong type to untrusted */ 237 subprog_untrusted((void *)bpf_core_cast(0, struct bpf_verifier_env)); 238 /* map value to untrusted */ 239 subprog_untrusted((void *)mem); 240 /* scalar to untrusted */ 241 subprog_untrusted(0); 242 /* variable offset to untrusted (map) */ 243 subprog_untrusted((void *)mem + off); 244 /* variable offset to untrusted (trusted) */ 245 subprog_untrusted((void *)bpf_get_current_task_btf() + off); 246 return 0; 247 } 248 249 __weak int subprog_untrusted2(struct task_struct *task __arg_untrusted) 250 { 251 return subprog_trusted_task_nullable(task); 252 } 253 254 SEC("tp_btf/sys_enter") 255 __failure 256 __msg("R1 type=untrusted_ptr_ expected=ptr_, trusted_ptr_, rcu_ptr_") 257 __msg("Caller passes invalid args into func#{{.*}} ('subprog_trusted_task_nullable')") 258 int untrusted_to_trusted(void *ctx) 259 { 260 return subprog_untrusted2(bpf_get_current_task_btf()); 261 } 262 263 __weak int subprog_void_untrusted(void *p __arg_untrusted) 264 { 265 return *(int *)p; 266 } 267 268 __weak int subprog_char_untrusted(char *p __arg_untrusted) 269 { 270 return *(int *)p; 271 } 272 273 __weak int subprog_enum_untrusted(enum bpf_attach_type *p __arg_untrusted) 274 { 275 return *(int *)p; 276 } 277 278 SEC("tp_btf/sys_enter") 279 __success 280 __log_level(2) 281 __msg("r1 = {{.*}}; {{.*}}R1_w=trusted_ptr_task_struct()") 282 __msg("Func#1 ('subprog_void_untrusted') is global and assumed valid.") 283 __msg("Validating subprog_void_untrusted() func#1...") 284 __msg(": R1=rdonly_untrusted_mem(sz=0)") 285 int trusted_to_untrusted_mem(void *ctx) 286 { 287 return subprog_void_untrusted(bpf_get_current_task_btf()); 288 } 289 290 SEC("tp_btf/sys_enter") 291 __success 292 int anything_to_untrusted_mem(void *ctx) 293 { 294 /* untrusted to untrusted mem */ 295 subprog_void_untrusted(bpf_core_cast(0, struct task_struct)); 296 /* map value to untrusted mem */ 297 subprog_void_untrusted(mem); 298 /* scalar to untrusted mem */ 299 subprog_void_untrusted(0); 300 /* variable offset to untrusted mem (map) */ 301 subprog_void_untrusted((void *)mem + off); 302 /* variable offset to untrusted mem (trusted) */ 303 subprog_void_untrusted(bpf_get_current_task_btf() + off); 304 /* variable offset to untrusted char/enum (map) */ 305 subprog_char_untrusted(mem + off); 306 subprog_enum_untrusted((void *)mem + off); 307 return 0; 308 } 309 310 char _license[] SEC("license") = "GPL"; 311