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