1 // SPDX-License-Identifier: GPL-2.0 2 #include <vmlinux.h> 3 #include <bpf/bpf_tracing.h> 4 #include <bpf/bpf_helpers.h> 5 #include <bpf/bpf_core_read.h> 6 7 #include "bpf_misc.h" 8 #include "bpf_experimental.h" 9 10 extern void bpf_rcu_read_lock(void) __ksym; 11 extern void bpf_rcu_read_unlock(void) __ksym; 12 extern void bpf_preempt_disable(void) __ksym; 13 extern void bpf_preempt_enable(void) __ksym; 14 extern void bpf_local_irq_save(unsigned long *) __ksym; 15 extern void bpf_local_irq_restore(unsigned long *) __ksym; 16 17 #define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8))) 18 19 struct foo { 20 struct bpf_rb_node node; 21 }; 22 23 struct hmap_elem { 24 struct bpf_timer timer; 25 }; 26 27 struct { 28 __uint(type, BPF_MAP_TYPE_HASH); 29 __uint(max_entries, 64); 30 __type(key, int); 31 __type(value, struct hmap_elem); 32 } hmap SEC(".maps"); 33 34 private(A) struct bpf_spin_lock lock; 35 private(A) struct bpf_rb_root rbtree __contains(foo, node); 36 37 __noinline void *exception_cb_bad_ret_type(u64 cookie) 38 { 39 return NULL; 40 } 41 42 __noinline int exception_cb_bad_arg_0(void) 43 { 44 return 0; 45 } 46 47 __noinline int exception_cb_bad_arg_2(int a, int b) 48 { 49 return 0; 50 } 51 52 __noinline int exception_cb_ok_arg_small(int a) 53 { 54 return 0; 55 } 56 57 SEC("?tc") 58 __exception_cb(exception_cb_bad_ret_type) 59 __failure __msg("Global function exception_cb_bad_ret_type() doesn't return scalar.") 60 int reject_exception_cb_type_1(struct __sk_buff *ctx) 61 { 62 bpf_throw(0); 63 return 0; 64 } 65 66 SEC("?tc") 67 __exception_cb(exception_cb_bad_arg_0) 68 __failure __msg("exception cb only supports single integer argument") 69 int reject_exception_cb_type_2(struct __sk_buff *ctx) 70 { 71 bpf_throw(0); 72 return 0; 73 } 74 75 SEC("?tc") 76 __exception_cb(exception_cb_bad_arg_2) 77 __failure __msg("exception cb only supports single integer argument") 78 int reject_exception_cb_type_3(struct __sk_buff *ctx) 79 { 80 bpf_throw(0); 81 return 0; 82 } 83 84 SEC("?tc") 85 __exception_cb(exception_cb_ok_arg_small) 86 __success 87 int reject_exception_cb_type_4(struct __sk_buff *ctx) 88 { 89 bpf_throw(0); 90 return 0; 91 } 92 93 __noinline 94 static int timer_cb(void *map, int *key, struct bpf_timer *timer) 95 { 96 bpf_throw(0); 97 return 0; 98 } 99 100 SEC("?tc") 101 __failure __msg("cannot be called from callback subprog") 102 int reject_async_callback_throw(struct __sk_buff *ctx) 103 { 104 struct hmap_elem *elem; 105 106 elem = bpf_map_lookup_elem(&hmap, &(int){0}); 107 if (!elem) 108 return 0; 109 return bpf_timer_set_callback(&elem->timer, timer_cb); 110 } 111 112 __noinline static int subprog_lock(struct __sk_buff *ctx) 113 { 114 volatile int ret = 0; 115 116 bpf_spin_lock(&lock); 117 if (ctx->len) 118 bpf_throw(0); 119 return ret; 120 } 121 122 SEC("?tc") 123 __failure __msg("function calls are not allowed while holding a lock") 124 int reject_with_lock(void *ctx) 125 { 126 bpf_spin_lock(&lock); 127 bpf_throw(0); 128 return 0; 129 } 130 131 SEC("?tc") 132 __failure __msg("function calls are not allowed while holding a lock") 133 int reject_subprog_with_lock(void *ctx) 134 { 135 return subprog_lock(ctx); 136 } 137 138 SEC("?tc") 139 __failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region") 140 int reject_with_rcu_read_lock(void *ctx) 141 { 142 bpf_rcu_read_lock(); 143 bpf_throw(0); 144 return 0; 145 } 146 147 __noinline static int throwing_subprog(struct __sk_buff *ctx) 148 { 149 if (ctx->len) 150 bpf_throw(0); 151 return 0; 152 } 153 154 SEC("?tc") 155 __failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region") 156 int reject_subprog_with_rcu_read_lock(void *ctx) 157 { 158 bpf_rcu_read_lock(); 159 throwing_subprog(ctx); 160 bpf_rcu_read_unlock(); 161 return 0; 162 } 163 164 static bool rbless(struct bpf_rb_node *n1, const struct bpf_rb_node *n2) 165 { 166 bpf_throw(0); 167 return true; 168 } 169 170 SEC("?tc") 171 __failure __msg("function calls are not allowed while holding a lock") 172 int reject_with_rbtree_add_throw(void *ctx) 173 { 174 struct foo *f; 175 176 f = bpf_obj_new(typeof(*f)); 177 if (!f) 178 return 0; 179 bpf_spin_lock(&lock); 180 bpf_rbtree_add(&rbtree, &f->node, rbless); 181 bpf_spin_unlock(&lock); 182 return 0; 183 } 184 185 SEC("?tc") 186 __failure __msg("Unreleased reference") 187 int reject_with_reference(void *ctx) 188 { 189 struct foo *f; 190 191 f = bpf_obj_new(typeof(*f)); 192 if (!f) 193 return 0; 194 bpf_throw(0); 195 return 0; 196 } 197 198 __noinline static int subprog_ref(struct __sk_buff *ctx) 199 { 200 struct foo *f; 201 202 f = bpf_obj_new(typeof(*f)); 203 if (!f) 204 return 0; 205 bpf_throw(0); 206 return 0; 207 } 208 209 __noinline static int subprog_cb_ref(u32 i, void *ctx) 210 { 211 bpf_throw(0); 212 return 0; 213 } 214 215 SEC("?tc") 216 __failure __msg("Unreleased reference") 217 int reject_with_cb_reference(void *ctx) 218 { 219 struct foo *f; 220 221 f = bpf_obj_new(typeof(*f)); 222 if (!f) 223 return 0; 224 bpf_loop(5, subprog_cb_ref, NULL, 0); 225 bpf_obj_drop(f); 226 return 0; 227 } 228 229 SEC("?tc") 230 __failure __msg("cannot be called from callback") 231 int reject_with_cb(void *ctx) 232 { 233 bpf_loop(5, subprog_cb_ref, NULL, 0); 234 return 0; 235 } 236 237 SEC("?tc") 238 __failure __msg("Unreleased reference") 239 int reject_with_subprog_reference(void *ctx) 240 { 241 return subprog_ref(ctx) + 1; 242 } 243 244 __noinline int throwing_exception_cb(u64 c) 245 { 246 bpf_throw(0); 247 return c; 248 } 249 250 __noinline int exception_cb1(u64 c) 251 { 252 return c; 253 } 254 255 __noinline int exception_cb2(u64 c) 256 { 257 return c; 258 } 259 260 static __noinline int static_func(struct __sk_buff *ctx) 261 { 262 return exception_cb1(ctx->tstamp); 263 } 264 265 __noinline int global_func(struct __sk_buff *ctx) 266 { 267 return exception_cb1(ctx->tstamp); 268 } 269 270 SEC("?tc") 271 __exception_cb(throwing_exception_cb) 272 __failure __msg("cannot be called from callback subprog") 273 int reject_throwing_exception_cb(struct __sk_buff *ctx) 274 { 275 return 0; 276 } 277 278 SEC("?tc") 279 __exception_cb(exception_cb1) 280 __failure __msg("cannot call exception cb directly") 281 int reject_exception_cb_call_global_func(struct __sk_buff *ctx) 282 { 283 return global_func(ctx); 284 } 285 286 SEC("?tc") 287 __exception_cb(exception_cb1) 288 __failure __msg("cannot call exception cb directly") 289 int reject_exception_cb_call_static_func(struct __sk_buff *ctx) 290 { 291 return static_func(ctx); 292 } 293 294 SEC("?tc") 295 __exception_cb(exception_cb1) 296 __exception_cb(exception_cb2) 297 __failure __msg("multiple exception callback tags for main subprog") 298 int reject_multiple_exception_cb(struct __sk_buff *ctx) 299 { 300 bpf_throw(0); 301 return 16; 302 } 303 304 __noinline int exception_cb_bad_ret(u64 c) 305 { 306 return c; 307 } 308 309 SEC("?fentry/bpf_check") 310 __exception_cb(exception_cb_bad_ret) 311 __failure __msg("At program exit the register R0 has unknown scalar value should") 312 int reject_set_exception_cb_bad_ret1(void *ctx) 313 { 314 return 0; 315 } 316 317 SEC("?fentry/bpf_check") 318 __failure __msg("At program exit the register R1 has smin=64 smax=64 should") 319 int reject_set_exception_cb_bad_ret2(void *ctx) 320 { 321 bpf_throw(64); 322 return 0; 323 } 324 325 __noinline static int loop_cb1(u32 index, int *ctx) 326 { 327 bpf_throw(0); 328 return 0; 329 } 330 331 __noinline static int loop_cb2(u32 index, int *ctx) 332 { 333 bpf_throw(0); 334 return 0; 335 } 336 337 SEC("?tc") 338 __failure __msg("cannot be called from callback") 339 int reject_exception_throw_cb(struct __sk_buff *ctx) 340 { 341 bpf_loop(5, loop_cb1, NULL, 0); 342 return 0; 343 } 344 345 SEC("?tc") 346 __failure __msg("cannot be called from callback") 347 int reject_exception_throw_cb_diff(struct __sk_buff *ctx) 348 { 349 if (ctx->protocol) 350 bpf_loop(5, loop_cb1, NULL, 0); 351 else 352 bpf_loop(5, loop_cb2, NULL, 0); 353 return 0; 354 } 355 356 __noinline static int always_throws(void) 357 { 358 bpf_throw(0); 359 return 0; 360 } 361 362 __noinline static int rcu_lock_then_throw(void) 363 { 364 bpf_rcu_read_lock(); 365 bpf_throw(0); 366 return 0; 367 } 368 369 SEC("?tc") 370 __failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region") 371 int reject_subprog_rcu_lock_throw(void *ctx) 372 { 373 rcu_lock_then_throw(); 374 return 0; 375 } 376 377 SEC("?tc") 378 __failure __msg("bpf_throw cannot be used inside bpf_preempt_disable-ed region") 379 int reject_subprog_throw_preempt_lock(void *ctx) 380 { 381 bpf_preempt_disable(); 382 always_throws(); 383 bpf_preempt_enable(); 384 return 0; 385 } 386 387 SEC("?tc") 388 __failure __msg("bpf_throw cannot be used inside bpf_local_irq_save-ed region") 389 int reject_subprog_throw_irq_lock(void *ctx) 390 { 391 unsigned long flags; 392 393 bpf_local_irq_save(&flags); 394 always_throws(); 395 bpf_local_irq_restore(&flags); 396 return 0; 397 } 398 399 char _license[] SEC("license") = "GPL"; 400