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 char _license[] SEC("license") = "GPL"; 183