1 // SPDX-License-Identifier: GPL-2.0 2 /* Converted from tools/testing/selftests/bpf/verifier/sock.c */ 3 4 #include "vmlinux.h" 5 #include <bpf/bpf_helpers.h> 6 #include "bpf_misc.h" 7 8 struct { 9 __uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY); 10 __uint(max_entries, 1); 11 __type(key, __u32); 12 __type(value, __u64); 13 } map_reuseport_array SEC(".maps"); 14 15 struct { 16 __uint(type, BPF_MAP_TYPE_SOCKHASH); 17 __uint(max_entries, 1); 18 __type(key, int); 19 __type(value, int); 20 } map_sockhash SEC(".maps"); 21 22 struct { 23 __uint(type, BPF_MAP_TYPE_SOCKMAP); 24 __uint(max_entries, 1); 25 __type(key, int); 26 __type(value, int); 27 } map_sockmap SEC(".maps"); 28 29 struct { 30 __uint(type, BPF_MAP_TYPE_XSKMAP); 31 __uint(max_entries, 1); 32 __type(key, int); 33 __type(value, int); 34 } map_xskmap SEC(".maps"); 35 36 struct val { 37 int cnt; 38 struct bpf_spin_lock l; 39 }; 40 41 struct { 42 __uint(type, BPF_MAP_TYPE_SK_STORAGE); 43 __uint(max_entries, 0); 44 __type(key, int); 45 __type(value, struct val); 46 __uint(map_flags, BPF_F_NO_PREALLOC); 47 } sk_storage_map SEC(".maps"); 48 49 struct { 50 __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 51 __uint(max_entries, 1); 52 __uint(key_size, sizeof(__u32)); 53 __uint(value_size, sizeof(__u32)); 54 } jmp_table SEC(".maps"); 55 56 SEC("cgroup/skb") 57 __description("skb->sk: no NULL check") 58 __failure __msg("invalid mem access 'sock_common_or_null'") 59 __failure_unpriv 60 __naked void skb_sk_no_null_check(void) 61 { 62 asm volatile (" \ 63 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 64 r0 = *(u32*)(r1 + 0); \ 65 r0 = 0; \ 66 exit; \ 67 " : 68 : __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 69 : __clobber_all); 70 } 71 72 SEC("cgroup/skb") 73 __description("skb->sk: sk->family [non fullsock field]") 74 __success __success_unpriv __retval(0) 75 __naked void sk_family_non_fullsock_field_1(void) 76 { 77 asm volatile (" \ 78 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 79 if r1 != 0 goto l0_%=; \ 80 r0 = 0; \ 81 exit; \ 82 l0_%=: r0 = *(u32*)(r1 + %[bpf_sock_family]); \ 83 r0 = 0; \ 84 exit; \ 85 " : 86 : __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 87 __imm_const(bpf_sock_family, offsetof(struct bpf_sock, family)) 88 : __clobber_all); 89 } 90 91 SEC("socket") 92 __description("skb->sk: sk->rx_queue_mapping [no sign extension]") 93 __success __success_unpriv __retval(0) 94 __naked void sk_rx_queue_mapping_no_sign_ext(void) 95 { 96 asm volatile (" \ 97 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 98 if r1 != 0 goto l0_%=; \ 99 r0 = 0xdead; \ 100 exit; \ 101 l0_%=: r0 = *(u32*)(r1 + %[bpf_sock_rx_queue_mapping]); \ 102 r0 >>= 32; \ 103 exit; \ 104 " : 105 : __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 106 __imm_const(bpf_sock_rx_queue_mapping, offsetof(struct bpf_sock, rx_queue_mapping)) 107 : __clobber_all); 108 } 109 110 SEC("socket") 111 __description("skb->sk: sk->rx_queue_mapping [narrow load mask]") 112 __success __success_unpriv __retval(0) 113 __naked void sk_rx_queue_mapping_narrow_load_mask(void) 114 { 115 asm volatile (" \ 116 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 117 if r1 != 0 goto l0_%=; \ 118 r0 = 0xdead; \ 119 exit; \ 120 l0_%=: r0 = *(u16*)(r1 + %[bpf_sock_rx_queue_mapping]); \ 121 r0 >>= 16; \ 122 exit; \ 123 " : 124 : __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 125 __imm_const(bpf_sock_rx_queue_mapping, offsetof(struct bpf_sock, rx_queue_mapping)) 126 : __clobber_all); 127 } 128 129 SEC("cgroup/skb") 130 __description("skb->sk: sk->type [fullsock field]") 131 __failure __msg("invalid sock_common access") 132 __failure_unpriv 133 __naked void sk_sk_type_fullsock_field_1(void) 134 { 135 asm volatile (" \ 136 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 137 if r1 != 0 goto l0_%=; \ 138 r0 = 0; \ 139 exit; \ 140 l0_%=: r0 = *(u32*)(r1 + %[bpf_sock_type]); \ 141 r0 = 0; \ 142 exit; \ 143 " : 144 : __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 145 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)) 146 : __clobber_all); 147 } 148 149 SEC("cgroup/skb") 150 __description("bpf_sk_fullsock(skb->sk): no !skb->sk check") 151 __failure __msg("Possibly NULL pointer passed to trusted R1") 152 __failure_unpriv 153 __naked void sk_no_skb_sk_check_1(void) 154 { 155 asm volatile (" \ 156 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 157 call %[bpf_sk_fullsock]; \ 158 r0 = 0; \ 159 exit; \ 160 " : 161 : __imm(bpf_sk_fullsock), 162 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 163 : __clobber_all); 164 } 165 166 SEC("cgroup/skb") 167 __description("sk_fullsock(skb->sk): no NULL check on ret") 168 __failure __msg("invalid mem access 'sock_or_null'") 169 __failure_unpriv 170 __naked void no_null_check_on_ret_1(void) 171 { 172 asm volatile (" \ 173 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 174 if r1 != 0 goto l0_%=; \ 175 r0 = 0; \ 176 exit; \ 177 l0_%=: call %[bpf_sk_fullsock]; \ 178 r0 = *(u32*)(r0 + %[bpf_sock_type]); \ 179 r0 = 0; \ 180 exit; \ 181 " : 182 : __imm(bpf_sk_fullsock), 183 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 184 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)) 185 : __clobber_all); 186 } 187 188 SEC("cgroup/skb") 189 __description("sk_fullsock(skb->sk): sk->type [fullsock field]") 190 __success __success_unpriv __retval(0) 191 __naked void sk_sk_type_fullsock_field_2(void) 192 { 193 asm volatile (" \ 194 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 195 if r1 != 0 goto l0_%=; \ 196 r0 = 0; \ 197 exit; \ 198 l0_%=: call %[bpf_sk_fullsock]; \ 199 if r0 != 0 goto l1_%=; \ 200 r0 = 0; \ 201 exit; \ 202 l1_%=: r0 = *(u32*)(r0 + %[bpf_sock_type]); \ 203 r0 = 0; \ 204 exit; \ 205 " : 206 : __imm(bpf_sk_fullsock), 207 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 208 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)) 209 : __clobber_all); 210 } 211 212 SEC("cgroup/skb") 213 __description("sk_fullsock(skb->sk): sk->family [non fullsock field]") 214 __success __success_unpriv __retval(0) 215 __naked void sk_family_non_fullsock_field_2(void) 216 { 217 asm volatile (" \ 218 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 219 if r1 != 0 goto l0_%=; \ 220 r0 = 0; \ 221 exit; \ 222 l0_%=: call %[bpf_sk_fullsock]; \ 223 if r0 != 0 goto l1_%=; \ 224 exit; \ 225 l1_%=: r0 = *(u32*)(r0 + %[bpf_sock_family]); \ 226 r0 = 0; \ 227 exit; \ 228 " : 229 : __imm(bpf_sk_fullsock), 230 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 231 __imm_const(bpf_sock_family, offsetof(struct bpf_sock, family)) 232 : __clobber_all); 233 } 234 235 SEC("cgroup/skb") 236 __description("sk_fullsock(skb->sk): sk->state [narrow load]") 237 __success __success_unpriv __retval(0) 238 __naked void sk_sk_state_narrow_load(void) 239 { 240 asm volatile (" \ 241 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 242 if r1 != 0 goto l0_%=; \ 243 r0 = 0; \ 244 exit; \ 245 l0_%=: call %[bpf_sk_fullsock]; \ 246 if r0 != 0 goto l1_%=; \ 247 r0 = 0; \ 248 exit; \ 249 l1_%=: r0 = *(u8*)(r0 + %[bpf_sock_state]); \ 250 r0 = 0; \ 251 exit; \ 252 " : 253 : __imm(bpf_sk_fullsock), 254 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 255 __imm_const(bpf_sock_state, offsetof(struct bpf_sock, state)) 256 : __clobber_all); 257 } 258 259 SEC("cgroup/skb") 260 __description("sk_fullsock(skb->sk): sk->dst_port [word load] (backward compatibility)") 261 __success __success_unpriv __retval(0) 262 __naked void port_word_load_backward_compatibility(void) 263 { 264 asm volatile (" \ 265 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 266 if r1 != 0 goto l0_%=; \ 267 r0 = 0; \ 268 exit; \ 269 l0_%=: call %[bpf_sk_fullsock]; \ 270 if r0 != 0 goto l1_%=; \ 271 r0 = 0; \ 272 exit; \ 273 l1_%=: r0 = *(u32*)(r0 + %[bpf_sock_dst_port]); \ 274 r0 = 0; \ 275 exit; \ 276 " : 277 : __imm(bpf_sk_fullsock), 278 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 279 __imm_const(bpf_sock_dst_port, offsetof(struct bpf_sock, dst_port)) 280 : __clobber_all); 281 } 282 283 SEC("cgroup/skb") 284 __description("sk_fullsock(skb->sk): sk->dst_port [half load]") 285 __success __success_unpriv __retval(0) 286 __naked void sk_dst_port_half_load(void) 287 { 288 asm volatile (" \ 289 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 290 if r1 != 0 goto l0_%=; \ 291 r0 = 0; \ 292 exit; \ 293 l0_%=: call %[bpf_sk_fullsock]; \ 294 if r0 != 0 goto l1_%=; \ 295 r0 = 0; \ 296 exit; \ 297 l1_%=: r0 = *(u16*)(r0 + %[bpf_sock_dst_port]); \ 298 r0 = 0; \ 299 exit; \ 300 " : 301 : __imm(bpf_sk_fullsock), 302 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 303 __imm_const(bpf_sock_dst_port, offsetof(struct bpf_sock, dst_port)) 304 : __clobber_all); 305 } 306 307 SEC("cgroup/skb") 308 __description("sk_fullsock(skb->sk): sk->dst_port [half load] (invalid)") 309 __failure __msg("invalid sock access") 310 __failure_unpriv 311 __naked void dst_port_half_load_invalid_1(void) 312 { 313 asm volatile (" \ 314 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 315 if r1 != 0 goto l0_%=; \ 316 r0 = 0; \ 317 exit; \ 318 l0_%=: call %[bpf_sk_fullsock]; \ 319 if r0 != 0 goto l1_%=; \ 320 r0 = 0; \ 321 exit; \ 322 l1_%=: r0 = *(u16*)(r0 + %[__imm_0]); \ 323 r0 = 0; \ 324 exit; \ 325 " : 326 : __imm(bpf_sk_fullsock), 327 __imm_const(__imm_0, offsetof(struct bpf_sock, dst_port) + 2), 328 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 329 : __clobber_all); 330 } 331 332 SEC("cgroup/skb") 333 __description("sk_fullsock(skb->sk): sk->dst_port [byte load]") 334 __success __success_unpriv __retval(0) 335 __naked void sk_dst_port_byte_load(void) 336 { 337 asm volatile (" \ 338 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 339 if r1 != 0 goto l0_%=; \ 340 r0 = 0; \ 341 exit; \ 342 l0_%=: call %[bpf_sk_fullsock]; \ 343 if r0 != 0 goto l1_%=; \ 344 r0 = 0; \ 345 exit; \ 346 l1_%=: r2 = *(u8*)(r0 + %[bpf_sock_dst_port]); \ 347 r2 = *(u8*)(r0 + %[__imm_0]); \ 348 r0 = 0; \ 349 exit; \ 350 " : 351 : __imm(bpf_sk_fullsock), 352 __imm_const(__imm_0, offsetof(struct bpf_sock, dst_port) + 1), 353 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 354 __imm_const(bpf_sock_dst_port, offsetof(struct bpf_sock, dst_port)) 355 : __clobber_all); 356 } 357 358 SEC("cgroup/skb") 359 __description("sk_fullsock(skb->sk): sk->dst_port [byte load] (invalid)") 360 __failure __msg("invalid sock access") 361 __failure_unpriv 362 __naked void dst_port_byte_load_invalid(void) 363 { 364 asm volatile (" \ 365 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 366 if r1 != 0 goto l0_%=; \ 367 r0 = 0; \ 368 exit; \ 369 l0_%=: call %[bpf_sk_fullsock]; \ 370 if r0 != 0 goto l1_%=; \ 371 r0 = 0; \ 372 exit; \ 373 l1_%=: r0 = *(u8*)(r0 + %[__imm_0]); \ 374 r0 = 0; \ 375 exit; \ 376 " : 377 : __imm(bpf_sk_fullsock), 378 __imm_const(__imm_0, offsetof(struct bpf_sock, dst_port) + 2), 379 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 380 : __clobber_all); 381 } 382 383 SEC("cgroup/skb") 384 __description("sk_fullsock(skb->sk): past sk->dst_port [half load] (invalid)") 385 __failure __msg("invalid sock access") 386 __failure_unpriv 387 __naked void dst_port_half_load_invalid_2(void) 388 { 389 asm volatile (" \ 390 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 391 if r1 != 0 goto l0_%=; \ 392 r0 = 0; \ 393 exit; \ 394 l0_%=: call %[bpf_sk_fullsock]; \ 395 if r0 != 0 goto l1_%=; \ 396 r0 = 0; \ 397 exit; \ 398 l1_%=: r0 = *(u16*)(r0 + %[bpf_sock_dst_port__end]); \ 399 r0 = 0; \ 400 exit; \ 401 " : 402 : __imm(bpf_sk_fullsock), 403 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 404 __imm_const(bpf_sock_dst_port__end, offsetofend(struct bpf_sock, dst_port)) 405 : __clobber_all); 406 } 407 408 SEC("cgroup/skb") 409 __description("sk_fullsock(skb->sk): sk->dst_ip6 [load 2nd byte]") 410 __success __success_unpriv __retval(0) 411 __naked void dst_ip6_load_2nd_byte(void) 412 { 413 asm volatile (" \ 414 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 415 if r1 != 0 goto l0_%=; \ 416 r0 = 0; \ 417 exit; \ 418 l0_%=: call %[bpf_sk_fullsock]; \ 419 if r0 != 0 goto l1_%=; \ 420 r0 = 0; \ 421 exit; \ 422 l1_%=: r0 = *(u8*)(r0 + %[__imm_0]); \ 423 r0 = 0; \ 424 exit; \ 425 " : 426 : __imm(bpf_sk_fullsock), 427 __imm_const(__imm_0, offsetof(struct bpf_sock, dst_ip6[0]) + 1), 428 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 429 : __clobber_all); 430 } 431 432 SEC("cgroup/skb") 433 __description("sk_fullsock(skb->sk): sk->type [narrow load]") 434 __success __success_unpriv __retval(0) 435 __naked void sk_sk_type_narrow_load(void) 436 { 437 asm volatile (" \ 438 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 439 if r1 != 0 goto l0_%=; \ 440 r0 = 0; \ 441 exit; \ 442 l0_%=: call %[bpf_sk_fullsock]; \ 443 if r0 != 0 goto l1_%=; \ 444 r0 = 0; \ 445 exit; \ 446 l1_%=: r0 = *(u8*)(r0 + %[bpf_sock_type]); \ 447 r0 = 0; \ 448 exit; \ 449 " : 450 : __imm(bpf_sk_fullsock), 451 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 452 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)) 453 : __clobber_all); 454 } 455 456 SEC("cgroup/skb") 457 __description("sk_fullsock(skb->sk): sk->protocol [narrow load]") 458 __success __success_unpriv __retval(0) 459 __naked void sk_sk_protocol_narrow_load(void) 460 { 461 asm volatile (" \ 462 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 463 if r1 != 0 goto l0_%=; \ 464 r0 = 0; \ 465 exit; \ 466 l0_%=: call %[bpf_sk_fullsock]; \ 467 if r0 != 0 goto l1_%=; \ 468 r0 = 0; \ 469 exit; \ 470 l1_%=: r0 = *(u8*)(r0 + %[bpf_sock_protocol]); \ 471 r0 = 0; \ 472 exit; \ 473 " : 474 : __imm(bpf_sk_fullsock), 475 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 476 __imm_const(bpf_sock_protocol, offsetof(struct bpf_sock, protocol)) 477 : __clobber_all); 478 } 479 480 SEC("cgroup/skb") 481 __description("sk_fullsock(skb->sk): beyond last field") 482 __failure __msg("invalid sock access") 483 __failure_unpriv 484 __naked void skb_sk_beyond_last_field_1(void) 485 { 486 asm volatile (" \ 487 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 488 if r1 != 0 goto l0_%=; \ 489 r0 = 0; \ 490 exit; \ 491 l0_%=: call %[bpf_sk_fullsock]; \ 492 if r0 != 0 goto l1_%=; \ 493 r0 = 0; \ 494 exit; \ 495 l1_%=: r0 = *(u32*)(r0 + %[bpf_sock_rx_queue_mapping__end]);\ 496 r0 = 0; \ 497 exit; \ 498 " : 499 : __imm(bpf_sk_fullsock), 500 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 501 __imm_const(bpf_sock_rx_queue_mapping__end, offsetofend(struct bpf_sock, rx_queue_mapping)) 502 : __clobber_all); 503 } 504 505 SEC("cgroup/skb") 506 __description("bpf_tcp_sock(skb->sk): no !skb->sk check") 507 __failure __msg("Possibly NULL pointer passed to trusted R1") 508 __failure_unpriv 509 __naked void sk_no_skb_sk_check_2(void) 510 { 511 asm volatile (" \ 512 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 513 call %[bpf_tcp_sock]; \ 514 r0 = 0; \ 515 exit; \ 516 " : 517 : __imm(bpf_tcp_sock), 518 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 519 : __clobber_all); 520 } 521 522 SEC("cgroup/skb") 523 __description("bpf_tcp_sock(skb->sk): no NULL check on ret") 524 __failure __msg("invalid mem access 'tcp_sock_or_null'") 525 __failure_unpriv 526 __naked void no_null_check_on_ret_2(void) 527 { 528 asm volatile (" \ 529 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 530 if r1 != 0 goto l0_%=; \ 531 r0 = 0; \ 532 exit; \ 533 l0_%=: call %[bpf_tcp_sock]; \ 534 r0 = *(u32*)(r0 + %[bpf_tcp_sock_snd_cwnd]); \ 535 r0 = 0; \ 536 exit; \ 537 " : 538 : __imm(bpf_tcp_sock), 539 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 540 __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd)) 541 : __clobber_all); 542 } 543 544 SEC("cgroup/skb") 545 __description("bpf_tcp_sock(skb->sk): tp->snd_cwnd") 546 __success __success_unpriv __retval(0) 547 __naked void skb_sk_tp_snd_cwnd_1(void) 548 { 549 asm volatile (" \ 550 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 551 if r1 != 0 goto l0_%=; \ 552 r0 = 0; \ 553 exit; \ 554 l0_%=: call %[bpf_tcp_sock]; \ 555 if r0 != 0 goto l1_%=; \ 556 exit; \ 557 l1_%=: r0 = *(u32*)(r0 + %[bpf_tcp_sock_snd_cwnd]); \ 558 r0 = 0; \ 559 exit; \ 560 " : 561 : __imm(bpf_tcp_sock), 562 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 563 __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd)) 564 : __clobber_all); 565 } 566 567 SEC("cgroup/skb") 568 __description("bpf_tcp_sock(skb->sk): tp->bytes_acked") 569 __success __success_unpriv __retval(0) 570 __naked void skb_sk_tp_bytes_acked(void) 571 { 572 asm volatile (" \ 573 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 574 if r1 != 0 goto l0_%=; \ 575 r0 = 0; \ 576 exit; \ 577 l0_%=: call %[bpf_tcp_sock]; \ 578 if r0 != 0 goto l1_%=; \ 579 exit; \ 580 l1_%=: r0 = *(u64*)(r0 + %[bpf_tcp_sock_bytes_acked]); \ 581 r0 = 0; \ 582 exit; \ 583 " : 584 : __imm(bpf_tcp_sock), 585 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 586 __imm_const(bpf_tcp_sock_bytes_acked, offsetof(struct bpf_tcp_sock, bytes_acked)) 587 : __clobber_all); 588 } 589 590 SEC("cgroup/skb") 591 __description("bpf_tcp_sock(skb->sk): beyond last field") 592 __failure __msg("invalid tcp_sock access") 593 __failure_unpriv 594 __naked void skb_sk_beyond_last_field_2(void) 595 { 596 asm volatile (" \ 597 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 598 if r1 != 0 goto l0_%=; \ 599 r0 = 0; \ 600 exit; \ 601 l0_%=: call %[bpf_tcp_sock]; \ 602 if r0 != 0 goto l1_%=; \ 603 exit; \ 604 l1_%=: r0 = *(u64*)(r0 + %[bpf_tcp_sock_bytes_acked__end]);\ 605 r0 = 0; \ 606 exit; \ 607 " : 608 : __imm(bpf_tcp_sock), 609 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 610 __imm_const(bpf_tcp_sock_bytes_acked__end, offsetofend(struct bpf_tcp_sock, bytes_acked)) 611 : __clobber_all); 612 } 613 614 SEC("cgroup/skb") 615 __description("bpf_tcp_sock(skb->sk): narrow load of tp->bytes_received") 616 __failure __msg("invalid tcp_sock access") 617 __failure_unpriv 618 __naked void skb_sk_tp_bytes_received_narrow(void) 619 { 620 asm volatile (" \ 621 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 622 if r1 != 0 goto l0_%=; \ 623 r0 = 0; \ 624 exit; \ 625 l0_%=: call %[bpf_tcp_sock]; \ 626 if r0 != 0 goto l1_%=; \ 627 exit; \ 628 l1_%=: r0 = *(u32*)(r0 + %[off]); \ 629 r0 = 0; \ 630 exit; \ 631 " : 632 : __imm(bpf_tcp_sock), 633 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 634 __imm_const(off, offsetof(struct bpf_tcp_sock, bytes_received) + 4) 635 : __clobber_all); 636 } 637 638 SEC("cgroup/skb") 639 __description("bpf_tcp_sock(skb->sk): narrow load of tp->bytes_acked") 640 __failure __msg("invalid tcp_sock access") 641 __failure_unpriv 642 __naked void skb_sk_tp_bytes_acked_narrow(void) 643 { 644 asm volatile (" \ 645 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 646 if r1 != 0 goto l0_%=; \ 647 r0 = 0; \ 648 exit; \ 649 l0_%=: call %[bpf_tcp_sock]; \ 650 if r0 != 0 goto l1_%=; \ 651 exit; \ 652 l1_%=: r0 = *(u32*)(r0 + %[off]); \ 653 r0 = 0; \ 654 exit; \ 655 " : 656 : __imm(bpf_tcp_sock), 657 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 658 __imm_const(off, offsetof(struct bpf_tcp_sock, bytes_acked) + 4) 659 : __clobber_all); 660 } 661 662 SEC("cgroup/skb") 663 __description("bpf_tcp_sock(bpf_sk_fullsock(skb->sk)): tp->snd_cwnd") 664 __success __success_unpriv __retval(0) 665 __naked void skb_sk_tp_snd_cwnd_2(void) 666 { 667 asm volatile (" \ 668 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 669 if r1 != 0 goto l0_%=; \ 670 r0 = 0; \ 671 exit; \ 672 l0_%=: call %[bpf_sk_fullsock]; \ 673 if r0 != 0 goto l1_%=; \ 674 exit; \ 675 l1_%=: r1 = r0; \ 676 call %[bpf_tcp_sock]; \ 677 if r0 != 0 goto l2_%=; \ 678 exit; \ 679 l2_%=: r0 = *(u32*)(r0 + %[bpf_tcp_sock_snd_cwnd]); \ 680 r0 = 0; \ 681 exit; \ 682 " : 683 : __imm(bpf_sk_fullsock), 684 __imm(bpf_tcp_sock), 685 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 686 __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd)) 687 : __clobber_all); 688 } 689 690 SEC("tc") 691 __description("bpf_sk_release(skb->sk)") 692 __failure __msg("release function bpf_sk_release expects referenced PTR_TO_BTF_ID passed to R1") 693 __naked void bpf_sk_release_skb_sk(void) 694 { 695 asm volatile (" \ 696 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 697 if r1 == 0 goto l0_%=; \ 698 call %[bpf_sk_release]; \ 699 l0_%=: r0 = 0; \ 700 exit; \ 701 " : 702 : __imm(bpf_sk_release), 703 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 704 : __clobber_all); 705 } 706 707 SEC("tc") 708 __description("bpf_sk_release(bpf_sk_fullsock(skb->sk))") 709 __failure __msg("release function bpf_sk_release expects referenced PTR_TO_BTF_ID passed to R1") 710 __naked void bpf_sk_fullsock_skb_sk(void) 711 { 712 asm volatile (" \ 713 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 714 if r1 != 0 goto l0_%=; \ 715 r0 = 0; \ 716 exit; \ 717 l0_%=: call %[bpf_sk_fullsock]; \ 718 if r0 != 0 goto l1_%=; \ 719 exit; \ 720 l1_%=: r1 = r0; \ 721 call %[bpf_sk_release]; \ 722 r0 = 1; \ 723 exit; \ 724 " : 725 : __imm(bpf_sk_fullsock), 726 __imm(bpf_sk_release), 727 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 728 : __clobber_all); 729 } 730 731 SEC("tc") 732 __description("bpf_sk_release(bpf_tcp_sock(skb->sk))") 733 __failure __msg("release function bpf_sk_release expects referenced PTR_TO_BTF_ID passed to R1") 734 __naked void bpf_tcp_sock_skb_sk(void) 735 { 736 asm volatile (" \ 737 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 738 if r1 != 0 goto l0_%=; \ 739 r0 = 0; \ 740 exit; \ 741 l0_%=: call %[bpf_tcp_sock]; \ 742 if r0 != 0 goto l1_%=; \ 743 exit; \ 744 l1_%=: r1 = r0; \ 745 call %[bpf_sk_release]; \ 746 r0 = 1; \ 747 exit; \ 748 " : 749 : __imm(bpf_sk_release), 750 __imm(bpf_tcp_sock), 751 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 752 : __clobber_all); 753 } 754 755 SEC("tc") 756 __description("sk_storage_get(map, skb->sk, NULL, 0): value == NULL") 757 __success __retval(0) 758 __naked void sk_null_0_value_null(void) 759 { 760 asm volatile (" \ 761 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 762 if r1 != 0 goto l0_%=; \ 763 r0 = 0; \ 764 exit; \ 765 l0_%=: call %[bpf_sk_fullsock]; \ 766 if r0 != 0 goto l1_%=; \ 767 r0 = 0; \ 768 exit; \ 769 l1_%=: r4 = 0; \ 770 r3 = 0; \ 771 r2 = r0; \ 772 r1 = %[sk_storage_map] ll; \ 773 call %[bpf_sk_storage_get]; \ 774 r0 = 0; \ 775 exit; \ 776 " : 777 : __imm(bpf_sk_fullsock), 778 __imm(bpf_sk_storage_get), 779 __imm_addr(sk_storage_map), 780 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 781 : __clobber_all); 782 } 783 784 SEC("tc") 785 __description("sk_storage_get(map, skb->sk, 1, 1): value == 1") 786 __failure __msg("R3 type=scalar expected=fp") 787 __naked void sk_1_1_value_1(void) 788 { 789 asm volatile (" \ 790 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 791 if r1 != 0 goto l0_%=; \ 792 r0 = 0; \ 793 exit; \ 794 l0_%=: call %[bpf_sk_fullsock]; \ 795 if r0 != 0 goto l1_%=; \ 796 r0 = 0; \ 797 exit; \ 798 l1_%=: r4 = 1; \ 799 r3 = 1; \ 800 r2 = r0; \ 801 r1 = %[sk_storage_map] ll; \ 802 call %[bpf_sk_storage_get]; \ 803 r0 = 0; \ 804 exit; \ 805 " : 806 : __imm(bpf_sk_fullsock), 807 __imm(bpf_sk_storage_get), 808 __imm_addr(sk_storage_map), 809 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 810 : __clobber_all); 811 } 812 813 SEC("tc") 814 __description("sk_storage_get(map, skb->sk, &stack_value, 1): stack_value") 815 __success __retval(0) 816 __naked void stack_value_1_stack_value(void) 817 { 818 asm volatile (" \ 819 r2 = 0; \ 820 *(u64*)(r10 - 8) = r2; \ 821 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 822 if r1 != 0 goto l0_%=; \ 823 r0 = 0; \ 824 exit; \ 825 l0_%=: call %[bpf_sk_fullsock]; \ 826 if r0 != 0 goto l1_%=; \ 827 r0 = 0; \ 828 exit; \ 829 l1_%=: r4 = 1; \ 830 r3 = r10; \ 831 r3 += -8; \ 832 r2 = r0; \ 833 r1 = %[sk_storage_map] ll; \ 834 call %[bpf_sk_storage_get]; \ 835 r0 = 0; \ 836 exit; \ 837 " : 838 : __imm(bpf_sk_fullsock), 839 __imm(bpf_sk_storage_get), 840 __imm_addr(sk_storage_map), 841 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 842 : __clobber_all); 843 } 844 845 SEC("tc") 846 __description("bpf_map_lookup_elem(smap, &key)") 847 __failure __msg("cannot pass map_type 24 into func bpf_map_lookup_elem") 848 __naked void map_lookup_elem_smap_key(void) 849 { 850 asm volatile (" \ 851 r1 = 0; \ 852 *(u32*)(r10 - 4) = r1; \ 853 r2 = r10; \ 854 r2 += -4; \ 855 r1 = %[sk_storage_map] ll; \ 856 call %[bpf_map_lookup_elem]; \ 857 r0 = 0; \ 858 exit; \ 859 " : 860 : __imm(bpf_map_lookup_elem), 861 __imm_addr(sk_storage_map) 862 : __clobber_all); 863 } 864 865 SEC("xdp") 866 __description("bpf_map_lookup_elem(xskmap, &key); xs->queue_id") 867 __success __retval(0) 868 __naked void xskmap_key_xs_queue_id(void) 869 { 870 asm volatile (" \ 871 r1 = 0; \ 872 *(u32*)(r10 - 8) = r1; \ 873 r2 = r10; \ 874 r2 += -8; \ 875 r1 = %[map_xskmap] ll; \ 876 call %[bpf_map_lookup_elem]; \ 877 if r0 != 0 goto l0_%=; \ 878 exit; \ 879 l0_%=: r0 = *(u32*)(r0 + %[bpf_xdp_sock_queue_id]); \ 880 r0 = 0; \ 881 exit; \ 882 " : 883 : __imm(bpf_map_lookup_elem), 884 __imm_addr(map_xskmap), 885 __imm_const(bpf_xdp_sock_queue_id, offsetof(struct bpf_xdp_sock, queue_id)) 886 : __clobber_all); 887 } 888 889 SEC("sk_skb") 890 __description("bpf_map_lookup_elem(sockmap, &key)") 891 __failure __msg("Unreleased reference id=2 alloc_insn=6") 892 __naked void map_lookup_elem_sockmap_key(void) 893 { 894 asm volatile (" \ 895 r1 = 0; \ 896 *(u32*)(r10 - 4) = r1; \ 897 r2 = r10; \ 898 r2 += -4; \ 899 r1 = %[map_sockmap] ll; \ 900 call %[bpf_map_lookup_elem]; \ 901 r0 = 0; \ 902 exit; \ 903 " : 904 : __imm(bpf_map_lookup_elem), 905 __imm_addr(map_sockmap) 906 : __clobber_all); 907 } 908 909 SEC("sk_skb") 910 __description("bpf_map_lookup_elem(sockhash, &key)") 911 __failure __msg("Unreleased reference id=2 alloc_insn=6") 912 __naked void map_lookup_elem_sockhash_key(void) 913 { 914 asm volatile (" \ 915 r1 = 0; \ 916 *(u32*)(r10 - 4) = r1; \ 917 r2 = r10; \ 918 r2 += -4; \ 919 r1 = %[map_sockhash] ll; \ 920 call %[bpf_map_lookup_elem]; \ 921 r0 = 0; \ 922 exit; \ 923 " : 924 : __imm(bpf_map_lookup_elem), 925 __imm_addr(map_sockhash) 926 : __clobber_all); 927 } 928 929 SEC("sk_skb") 930 __description("bpf_map_lookup_elem(sockmap, &key); sk->type [fullsock field]; bpf_sk_release(sk)") 931 __success 932 __naked void field_bpf_sk_release_sk_1(void) 933 { 934 asm volatile (" \ 935 r1 = 0; \ 936 *(u32*)(r10 - 4) = r1; \ 937 r2 = r10; \ 938 r2 += -4; \ 939 r1 = %[map_sockmap] ll; \ 940 call %[bpf_map_lookup_elem]; \ 941 if r0 != 0 goto l0_%=; \ 942 exit; \ 943 l0_%=: r1 = r0; \ 944 r0 = *(u32*)(r0 + %[bpf_sock_type]); \ 945 call %[bpf_sk_release]; \ 946 exit; \ 947 " : 948 : __imm(bpf_map_lookup_elem), 949 __imm(bpf_sk_release), 950 __imm_addr(map_sockmap), 951 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)) 952 : __clobber_all); 953 } 954 955 SEC("sk_skb") 956 __description("bpf_map_lookup_elem(sockhash, &key); sk->type [fullsock field]; bpf_sk_release(sk)") 957 __success 958 __naked void field_bpf_sk_release_sk_2(void) 959 { 960 asm volatile (" \ 961 r1 = 0; \ 962 *(u32*)(r10 - 4) = r1; \ 963 r2 = r10; \ 964 r2 += -4; \ 965 r1 = %[map_sockhash] ll; \ 966 call %[bpf_map_lookup_elem]; \ 967 if r0 != 0 goto l0_%=; \ 968 exit; \ 969 l0_%=: r1 = r0; \ 970 r0 = *(u32*)(r0 + %[bpf_sock_type]); \ 971 call %[bpf_sk_release]; \ 972 exit; \ 973 " : 974 : __imm(bpf_map_lookup_elem), 975 __imm(bpf_sk_release), 976 __imm_addr(map_sockhash), 977 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)) 978 : __clobber_all); 979 } 980 981 SEC("sk_reuseport") 982 __description("bpf_sk_select_reuseport(ctx, reuseport_array, &key, flags)") 983 __success 984 __naked void ctx_reuseport_array_key_flags(void) 985 { 986 asm volatile (" \ 987 r4 = 0; \ 988 r2 = 0; \ 989 *(u32*)(r10 - 4) = r2; \ 990 r3 = r10; \ 991 r3 += -4; \ 992 r2 = %[map_reuseport_array] ll; \ 993 call %[bpf_sk_select_reuseport]; \ 994 exit; \ 995 " : 996 : __imm(bpf_sk_select_reuseport), 997 __imm_addr(map_reuseport_array) 998 : __clobber_all); 999 } 1000 1001 SEC("sk_reuseport") 1002 __description("bpf_sk_select_reuseport(ctx, sockmap, &key, flags)") 1003 __success 1004 __naked void reuseport_ctx_sockmap_key_flags(void) 1005 { 1006 asm volatile (" \ 1007 r4 = 0; \ 1008 r2 = 0; \ 1009 *(u32*)(r10 - 4) = r2; \ 1010 r3 = r10; \ 1011 r3 += -4; \ 1012 r2 = %[map_sockmap] ll; \ 1013 call %[bpf_sk_select_reuseport]; \ 1014 exit; \ 1015 " : 1016 : __imm(bpf_sk_select_reuseport), 1017 __imm_addr(map_sockmap) 1018 : __clobber_all); 1019 } 1020 1021 SEC("sk_reuseport") 1022 __description("bpf_sk_select_reuseport(ctx, sockhash, &key, flags)") 1023 __success 1024 __naked void reuseport_ctx_sockhash_key_flags(void) 1025 { 1026 asm volatile (" \ 1027 r4 = 0; \ 1028 r2 = 0; \ 1029 *(u32*)(r10 - 4) = r2; \ 1030 r3 = r10; \ 1031 r3 += -4; \ 1032 r2 = %[map_sockmap] ll; \ 1033 call %[bpf_sk_select_reuseport]; \ 1034 exit; \ 1035 " : 1036 : __imm(bpf_sk_select_reuseport), 1037 __imm_addr(map_sockmap) 1038 : __clobber_all); 1039 } 1040 1041 SEC("tc") 1042 __description("mark null check on return value of bpf_skc_to helpers") 1043 __failure __msg("invalid mem access") 1044 __naked void of_bpf_skc_to_helpers(void) 1045 { 1046 asm volatile (" \ 1047 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 1048 if r1 != 0 goto l0_%=; \ 1049 r0 = 0; \ 1050 exit; \ 1051 l0_%=: r6 = r1; \ 1052 call %[bpf_skc_to_tcp_sock]; \ 1053 r7 = r0; \ 1054 r1 = r6; \ 1055 call %[bpf_skc_to_tcp_request_sock]; \ 1056 r8 = r0; \ 1057 if r8 != 0 goto l1_%=; \ 1058 r0 = 0; \ 1059 exit; \ 1060 l1_%=: r0 = *(u8*)(r7 + 0); \ 1061 exit; \ 1062 " : 1063 : __imm(bpf_skc_to_tcp_request_sock), 1064 __imm(bpf_skc_to_tcp_sock), 1065 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 1066 : __clobber_all); 1067 } 1068 1069 SEC("cgroup/post_bind4") 1070 __description("sk->src_ip6[0] [load 1st byte]") 1071 __failure __msg("invalid bpf_context access off=28 size=2") 1072 __naked void post_bind4_read_src_ip6(void) 1073 { 1074 asm volatile (" \ 1075 r6 = r1; \ 1076 r7 = *(u16*)(r6 + %[bpf_sock_src_ip6_0]); \ 1077 r0 = 1; \ 1078 exit; \ 1079 " : 1080 : __imm_const(bpf_sock_src_ip6_0, offsetof(struct bpf_sock, src_ip6[0])) 1081 : __clobber_all); 1082 } 1083 1084 SEC("cgroup/post_bind4") 1085 __description("sk->mark [load mark]") 1086 __failure __msg("invalid bpf_context access off=16 size=2") 1087 __naked void post_bind4_read_mark(void) 1088 { 1089 asm volatile (" \ 1090 r6 = r1; \ 1091 r7 = *(u16*)(r6 + %[bpf_sock_mark]); \ 1092 r0 = 1; \ 1093 exit; \ 1094 " : 1095 : __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)) 1096 : __clobber_all); 1097 } 1098 1099 SEC("cgroup/post_bind6") 1100 __description("sk->src_ip4 [load src_ip4]") 1101 __failure __msg("invalid bpf_context access off=24 size=2") 1102 __naked void post_bind6_read_src_ip4(void) 1103 { 1104 asm volatile (" \ 1105 r6 = r1; \ 1106 r7 = *(u16*)(r6 + %[bpf_sock_src_ip4]); \ 1107 r0 = 1; \ 1108 exit; \ 1109 " : 1110 : __imm_const(bpf_sock_src_ip4, offsetof(struct bpf_sock, src_ip4)) 1111 : __clobber_all); 1112 } 1113 1114 SEC("cgroup/sock_create") 1115 __description("sk->src_port [word load]") 1116 __failure __msg("invalid bpf_context access off=44 size=2") 1117 __naked void sock_create_read_src_port(void) 1118 { 1119 asm volatile (" \ 1120 r6 = r1; \ 1121 r7 = *(u16*)(r6 + %[bpf_sock_src_port]); \ 1122 r0 = 1; \ 1123 exit; \ 1124 " : 1125 : __imm_const(bpf_sock_src_port, offsetof(struct bpf_sock, src_port)) 1126 : __clobber_all); 1127 } 1128 1129 __noinline 1130 long skb_pull_data2(struct __sk_buff *sk, __u32 len) 1131 { 1132 return bpf_skb_pull_data(sk, len); 1133 } 1134 1135 __noinline 1136 long skb_pull_data1(struct __sk_buff *sk, __u32 len) 1137 { 1138 return skb_pull_data2(sk, len); 1139 } 1140 1141 /* global function calls bpf_skb_pull_data(), which invalidates packet 1142 * pointers established before global function call. 1143 */ 1144 SEC("tc") 1145 __failure __msg("invalid mem access") 1146 int invalidate_pkt_pointers_from_global_func(struct __sk_buff *sk) 1147 { 1148 int *p = (void *)(long)sk->data; 1149 1150 if ((void *)(p + 1) > (void *)(long)sk->data_end) 1151 return TCX_DROP; 1152 skb_pull_data1(sk, 0); 1153 *p = 42; /* this is unsafe */ 1154 return TCX_PASS; 1155 } 1156 1157 __noinline 1158 long xdp_pull_data2(struct xdp_md *x, __u32 len) 1159 { 1160 return bpf_xdp_pull_data(x, len); 1161 } 1162 1163 __noinline 1164 long xdp_pull_data1(struct xdp_md *x, __u32 len) 1165 { 1166 return xdp_pull_data2(x, len); 1167 } 1168 1169 /* global function calls bpf_xdp_pull_data(), which invalidates packet 1170 * pointers established before global function call. 1171 */ 1172 SEC("xdp") 1173 __failure __msg("invalid mem access") 1174 int invalidate_xdp_pkt_pointers_from_global_func(struct xdp_md *x) 1175 { 1176 int *p = (void *)(long)x->data; 1177 1178 if ((void *)(p + 1) > (void *)(long)x->data_end) 1179 return XDP_DROP; 1180 xdp_pull_data1(x, 0); 1181 *p = 42; /* this is unsafe */ 1182 return XDP_PASS; 1183 } 1184 1185 /* XDP packet changing kfunc calls invalidate packet pointers */ 1186 SEC("xdp") 1187 __failure __msg("invalid mem access") 1188 int invalidate_xdp_pkt_pointers(struct xdp_md *x) 1189 { 1190 int *p = (void *)(long)x->data; 1191 1192 if ((void *)(p + 1) > (void *)(long)x->data_end) 1193 return XDP_DROP; 1194 bpf_xdp_pull_data(x, 0); 1195 *p = 42; /* this is unsafe */ 1196 return XDP_PASS; 1197 } 1198 1199 __noinline 1200 int tail_call(struct __sk_buff *sk) 1201 { 1202 bpf_tail_call_static(sk, &jmp_table, 0); 1203 return 0; 1204 } 1205 1206 static __noinline 1207 int static_tail_call(struct __sk_buff *sk) 1208 { 1209 int ret = 0; 1210 1211 bpf_tail_call_static(sk, &jmp_table, 0); 1212 barrier_var(ret); 1213 return ret; 1214 } 1215 1216 /* Tail calls in sub-programs invalidate packet pointers. */ 1217 SEC("tc") 1218 __failure __msg("invalid mem access") 1219 int invalidate_pkt_pointers_by_global_tail_call(struct __sk_buff *sk) 1220 { 1221 int *p = (void *)(long)sk->data; 1222 1223 if ((void *)(p + 1) > (void *)(long)sk->data_end) 1224 return TCX_DROP; 1225 tail_call(sk); 1226 *p = 42; /* this is unsafe */ 1227 return TCX_PASS; 1228 } 1229 1230 /* Tail calls in static sub-programs invalidate packet pointers. */ 1231 SEC("tc") 1232 __failure __msg("invalid mem access") 1233 int invalidate_pkt_pointers_by_static_tail_call(struct __sk_buff *sk) 1234 { 1235 int *p = (void *)(long)sk->data; 1236 int ret; 1237 1238 if ((void *)(p + 1) > (void *)(long)sk->data_end) 1239 return TCX_DROP; 1240 ret = static_tail_call(sk); 1241 __sink(ret); 1242 *p = 42; /* this is unsafe */ 1243 return TCX_PASS; 1244 } 1245 1246 /* Direct tail calls do not invalidate packet pointers. */ 1247 SEC("tc") 1248 __success 1249 int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk) 1250 { 1251 int *p = (void *)(long)sk->data; 1252 1253 if ((void *)(p + 1) > (void *)(long)sk->data_end) 1254 return TCX_DROP; 1255 bpf_tail_call_static(sk, &jmp_table, 0); 1256 *p = 42; /* this is NOT unsafe: tail calls don't return */ 1257 return TCX_PASS; 1258 } 1259 1260 char _license[] SEC("license") = "GPL"; 1261