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