1 #include "bpf_experimental.h" 2 #include "bpf_misc.h" 3 4 struct val_t { 5 long b, c, d; 6 }; 7 8 struct val2_t { 9 long b; 10 }; 11 12 struct val_with_ptr_t { 13 char *p; 14 }; 15 16 struct val_with_rb_root_t { 17 struct bpf_spin_lock lock; 18 }; 19 20 struct val_600b_t { 21 char b[600]; 22 }; 23 24 struct elem { 25 long sum; 26 struct val_t __percpu_kptr *pc; 27 }; 28 29 struct { 30 __uint(type, BPF_MAP_TYPE_ARRAY); 31 __uint(max_entries, 1); 32 __type(key, int); 33 __type(value, struct elem); 34 } array SEC(".maps"); 35 36 struct kernel_percpu_elem { 37 struct task_struct __percpu_kptr *task; 38 }; 39 40 struct { 41 __uint(type, BPF_MAP_TYPE_ARRAY); 42 __uint(max_entries, 1); 43 __type(key, int); 44 __type(value, struct kernel_percpu_elem); 45 } kernel_percpu_array SEC(".maps"); 46 47 struct task_struct *bpf_task_from_pid(s32 pid) __ksym; 48 void bpf_task_release(struct task_struct *p) __ksym; 49 50 long ret; 51 52 SEC("?fentry/bpf_fentry_test1") 53 __failure __msg("store to referenced kptr disallowed") 54 int BPF_PROG(test_array_map_1) 55 { 56 struct val_t __percpu_kptr *p; 57 struct elem *e; 58 int index = 0; 59 60 e = bpf_map_lookup_elem(&array, &index); 61 if (!e) 62 return 0; 63 64 p = bpf_percpu_obj_new(struct val_t); 65 if (!p) 66 return 0; 67 68 p = bpf_kptr_xchg(&e->pc, p); 69 if (p) 70 bpf_percpu_obj_drop(p); 71 72 e->pc = (struct val_t __percpu_kptr *)ret; 73 return 0; 74 } 75 76 SEC("?fentry/bpf_fentry_test1") 77 __failure __msg("invalid kptr access, R2 type=percpu_ptr_val2_t expected=ptr_val_t") 78 int BPF_PROG(test_array_map_2) 79 { 80 struct val2_t __percpu_kptr *p2; 81 struct val_t __percpu_kptr *p; 82 struct elem *e; 83 int index = 0; 84 85 e = bpf_map_lookup_elem(&array, &index); 86 if (!e) 87 return 0; 88 89 p2 = bpf_percpu_obj_new(struct val2_t); 90 if (!p2) 91 return 0; 92 93 p = bpf_kptr_xchg(&e->pc, p2); 94 if (p) 95 bpf_percpu_obj_drop(p); 96 97 return 0; 98 } 99 100 SEC("?fentry.s/bpf_fentry_test1") 101 __failure __msg("R1 type=scalar expected=percpu_ptr_, percpu_rcu_ptr_, percpu_trusted_ptr_") 102 int BPF_PROG(test_array_map_3) 103 { 104 struct val_t __percpu_kptr *p, *p1; 105 struct val_t *v; 106 struct elem *e; 107 int index = 0; 108 109 e = bpf_map_lookup_elem(&array, &index); 110 if (!e) 111 return 0; 112 113 p = bpf_percpu_obj_new(struct val_t); 114 if (!p) 115 return 0; 116 117 p1 = bpf_kptr_xchg(&e->pc, p); 118 if (p1) 119 bpf_percpu_obj_drop(p1); 120 121 v = bpf_this_cpu_ptr(p); 122 ret = v->b; 123 return 0; 124 } 125 126 SEC("?fentry.s/bpf_fentry_test1") 127 __failure __msg("R1 expected for bpf_percpu_obj_drop()") 128 int BPF_PROG(test_array_map_4) 129 { 130 struct val_t __percpu_kptr *p; 131 132 p = bpf_percpu_obj_new(struct val_t); 133 if (!p) 134 return 0; 135 136 bpf_obj_drop(p); 137 return 0; 138 } 139 140 SEC("?fentry.s/bpf_fentry_test1") 141 __failure __msg("R1 expected for bpf_obj_drop()") 142 int BPF_PROG(test_array_map_5) 143 { 144 struct val_t *p; 145 146 p = bpf_obj_new(struct val_t); 147 if (!p) 148 return 0; 149 150 bpf_percpu_obj_drop(p); 151 return 0; 152 } 153 154 SEC("?syscall") 155 __failure __msg("invalid kptr access, R2 type=trusted_ptr_ expected=ptr_task_struct") 156 int reject_kernel_ptr_into_percpu_kptr(void *ctx) 157 { 158 struct kernel_percpu_elem *e; 159 struct task_struct *p, *old; 160 int index = 0; 161 162 e = bpf_map_lookup_elem(&kernel_percpu_array, &index); 163 if (!e) 164 return 0; 165 166 p = bpf_task_from_pid(1); 167 if (!p) 168 return 0; 169 170 old = bpf_kptr_xchg(&e->task, p); 171 if (old) 172 bpf_task_release(old); 173 return 0; 174 } 175 176 SEC("?fentry.s/bpf_fentry_test1") 177 __failure __msg("invalid kptr access, R2 type=ptr_ expected=ptr_val_t") 178 int BPF_PROG(reject_plain_alloc_into_percpu_kptr) 179 { 180 struct val_t __percpu_kptr *old; 181 struct val_t *p; 182 struct elem *e; 183 int index = 0; 184 185 e = bpf_map_lookup_elem(&array, &index); 186 if (!e) 187 return 0; 188 189 p = bpf_obj_new(struct val_t); 190 if (!p) 191 return 0; 192 193 old = bpf_kptr_xchg(&e->pc, p); 194 if (old) 195 bpf_percpu_obj_drop(old); 196 return 0; 197 } 198 199 SEC("?fentry.s/bpf_fentry_test1") 200 __failure __msg("bpf_percpu_obj_new type ID argument must be of a struct of scalars") 201 int BPF_PROG(test_array_map_6) 202 { 203 struct val_with_ptr_t __percpu_kptr *p; 204 205 p = bpf_percpu_obj_new(struct val_with_ptr_t); 206 if (!p) 207 return 0; 208 209 bpf_percpu_obj_drop(p); 210 return 0; 211 } 212 213 SEC("?fentry.s/bpf_fentry_test1") 214 __failure __msg("bpf_percpu_obj_new type ID argument must not contain special fields") 215 int BPF_PROG(test_array_map_7) 216 { 217 struct val_with_rb_root_t __percpu_kptr *p; 218 219 p = bpf_percpu_obj_new(struct val_with_rb_root_t); 220 if (!p) 221 return 0; 222 223 bpf_percpu_obj_drop(p); 224 return 0; 225 } 226 227 SEC("?fentry.s/bpf_fentry_test1") 228 __failure __msg("bpf_percpu_obj_new type size (600) is greater than 512") 229 int BPF_PROG(test_array_map_8) 230 { 231 struct val_600b_t __percpu_kptr *p; 232 233 p = bpf_percpu_obj_new(struct val_600b_t); 234 if (!p) 235 return 0; 236 237 bpf_percpu_obj_drop(p); 238 return 0; 239 } 240 241 char _license[] SEC("license") = "GPL"; 242