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("type=sock_common_or_null expected=sock_common") 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("type=sock_common_or_null expected=sock_common") 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(bpf_sk_fullsock(skb->sk)): tp->snd_cwnd") 616 __success __success_unpriv __retval(0) 617 __naked void skb_sk_tp_snd_cwnd_2(void) 618 { 619 asm volatile (" \ 620 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 621 if r1 != 0 goto l0_%=; \ 622 r0 = 0; \ 623 exit; \ 624 l0_%=: call %[bpf_sk_fullsock]; \ 625 if r0 != 0 goto l1_%=; \ 626 exit; \ 627 l1_%=: r1 = r0; \ 628 call %[bpf_tcp_sock]; \ 629 if r0 != 0 goto l2_%=; \ 630 exit; \ 631 l2_%=: r0 = *(u32*)(r0 + %[bpf_tcp_sock_snd_cwnd]); \ 632 r0 = 0; \ 633 exit; \ 634 " : 635 : __imm(bpf_sk_fullsock), 636 __imm(bpf_tcp_sock), 637 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)), 638 __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd)) 639 : __clobber_all); 640 } 641 642 SEC("tc") 643 __description("bpf_sk_release(skb->sk)") 644 __failure __msg("release helper bpf_sk_release expects referenced PTR_TO_BTF_ID passed to R1") 645 __naked void bpf_sk_release_skb_sk(void) 646 { 647 asm volatile (" \ 648 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 649 if r1 == 0 goto l0_%=; \ 650 call %[bpf_sk_release]; \ 651 l0_%=: r0 = 0; \ 652 exit; \ 653 " : 654 : __imm(bpf_sk_release), 655 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 656 : __clobber_all); 657 } 658 659 SEC("tc") 660 __description("bpf_sk_release(bpf_sk_fullsock(skb->sk))") 661 __failure __msg("release helper bpf_sk_release expects referenced PTR_TO_BTF_ID passed to R1") 662 __naked void bpf_sk_fullsock_skb_sk(void) 663 { 664 asm volatile (" \ 665 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 666 if r1 != 0 goto l0_%=; \ 667 r0 = 0; \ 668 exit; \ 669 l0_%=: call %[bpf_sk_fullsock]; \ 670 if r0 != 0 goto l1_%=; \ 671 exit; \ 672 l1_%=: r1 = r0; \ 673 call %[bpf_sk_release]; \ 674 r0 = 1; \ 675 exit; \ 676 " : 677 : __imm(bpf_sk_fullsock), 678 __imm(bpf_sk_release), 679 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 680 : __clobber_all); 681 } 682 683 SEC("tc") 684 __description("bpf_sk_release(bpf_tcp_sock(skb->sk))") 685 __failure __msg("release helper bpf_sk_release expects referenced PTR_TO_BTF_ID passed to R1") 686 __naked void bpf_tcp_sock_skb_sk(void) 687 { 688 asm volatile (" \ 689 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 690 if r1 != 0 goto l0_%=; \ 691 r0 = 0; \ 692 exit; \ 693 l0_%=: call %[bpf_tcp_sock]; \ 694 if r0 != 0 goto l1_%=; \ 695 exit; \ 696 l1_%=: r1 = r0; \ 697 call %[bpf_sk_release]; \ 698 r0 = 1; \ 699 exit; \ 700 " : 701 : __imm(bpf_sk_release), 702 __imm(bpf_tcp_sock), 703 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 704 : __clobber_all); 705 } 706 707 SEC("tc") 708 __description("sk_storage_get(map, skb->sk, NULL, 0): value == NULL") 709 __success __retval(0) 710 __naked void sk_null_0_value_null(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 r0 = 0; \ 720 exit; \ 721 l1_%=: r4 = 0; \ 722 r3 = 0; \ 723 r2 = r0; \ 724 r1 = %[sk_storage_map] ll; \ 725 call %[bpf_sk_storage_get]; \ 726 r0 = 0; \ 727 exit; \ 728 " : 729 : __imm(bpf_sk_fullsock), 730 __imm(bpf_sk_storage_get), 731 __imm_addr(sk_storage_map), 732 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 733 : __clobber_all); 734 } 735 736 SEC("tc") 737 __description("sk_storage_get(map, skb->sk, 1, 1): value == 1") 738 __failure __msg("R3 type=scalar expected=fp") 739 __naked void sk_1_1_value_1(void) 740 { 741 asm volatile (" \ 742 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 743 if r1 != 0 goto l0_%=; \ 744 r0 = 0; \ 745 exit; \ 746 l0_%=: call %[bpf_sk_fullsock]; \ 747 if r0 != 0 goto l1_%=; \ 748 r0 = 0; \ 749 exit; \ 750 l1_%=: r4 = 1; \ 751 r3 = 1; \ 752 r2 = r0; \ 753 r1 = %[sk_storage_map] ll; \ 754 call %[bpf_sk_storage_get]; \ 755 r0 = 0; \ 756 exit; \ 757 " : 758 : __imm(bpf_sk_fullsock), 759 __imm(bpf_sk_storage_get), 760 __imm_addr(sk_storage_map), 761 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 762 : __clobber_all); 763 } 764 765 SEC("tc") 766 __description("sk_storage_get(map, skb->sk, &stack_value, 1): stack_value") 767 __success __retval(0) 768 __naked void stack_value_1_stack_value(void) 769 { 770 asm volatile (" \ 771 r2 = 0; \ 772 *(u64*)(r10 - 8) = r2; \ 773 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 774 if r1 != 0 goto l0_%=; \ 775 r0 = 0; \ 776 exit; \ 777 l0_%=: call %[bpf_sk_fullsock]; \ 778 if r0 != 0 goto l1_%=; \ 779 r0 = 0; \ 780 exit; \ 781 l1_%=: r4 = 1; \ 782 r3 = r10; \ 783 r3 += -8; \ 784 r2 = r0; \ 785 r1 = %[sk_storage_map] ll; \ 786 call %[bpf_sk_storage_get]; \ 787 r0 = 0; \ 788 exit; \ 789 " : 790 : __imm(bpf_sk_fullsock), 791 __imm(bpf_sk_storage_get), 792 __imm_addr(sk_storage_map), 793 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 794 : __clobber_all); 795 } 796 797 SEC("tc") 798 __description("bpf_map_lookup_elem(smap, &key)") 799 __failure __msg("cannot pass map_type 24 into func bpf_map_lookup_elem") 800 __naked void map_lookup_elem_smap_key(void) 801 { 802 asm volatile (" \ 803 r1 = 0; \ 804 *(u32*)(r10 - 4) = r1; \ 805 r2 = r10; \ 806 r2 += -4; \ 807 r1 = %[sk_storage_map] ll; \ 808 call %[bpf_map_lookup_elem]; \ 809 r0 = 0; \ 810 exit; \ 811 " : 812 : __imm(bpf_map_lookup_elem), 813 __imm_addr(sk_storage_map) 814 : __clobber_all); 815 } 816 817 SEC("xdp") 818 __description("bpf_map_lookup_elem(xskmap, &key); xs->queue_id") 819 __success __retval(0) 820 __naked void xskmap_key_xs_queue_id(void) 821 { 822 asm volatile (" \ 823 r1 = 0; \ 824 *(u32*)(r10 - 8) = r1; \ 825 r2 = r10; \ 826 r2 += -8; \ 827 r1 = %[map_xskmap] ll; \ 828 call %[bpf_map_lookup_elem]; \ 829 if r0 != 0 goto l0_%=; \ 830 exit; \ 831 l0_%=: r0 = *(u32*)(r0 + %[bpf_xdp_sock_queue_id]); \ 832 r0 = 0; \ 833 exit; \ 834 " : 835 : __imm(bpf_map_lookup_elem), 836 __imm_addr(map_xskmap), 837 __imm_const(bpf_xdp_sock_queue_id, offsetof(struct bpf_xdp_sock, queue_id)) 838 : __clobber_all); 839 } 840 841 SEC("sk_skb") 842 __description("bpf_map_lookup_elem(sockmap, &key)") 843 __failure __msg("Unreleased reference id=2 alloc_insn=6") 844 __naked void map_lookup_elem_sockmap_key(void) 845 { 846 asm volatile (" \ 847 r1 = 0; \ 848 *(u32*)(r10 - 4) = r1; \ 849 r2 = r10; \ 850 r2 += -4; \ 851 r1 = %[map_sockmap] ll; \ 852 call %[bpf_map_lookup_elem]; \ 853 r0 = 0; \ 854 exit; \ 855 " : 856 : __imm(bpf_map_lookup_elem), 857 __imm_addr(map_sockmap) 858 : __clobber_all); 859 } 860 861 SEC("sk_skb") 862 __description("bpf_map_lookup_elem(sockhash, &key)") 863 __failure __msg("Unreleased reference id=2 alloc_insn=6") 864 __naked void map_lookup_elem_sockhash_key(void) 865 { 866 asm volatile (" \ 867 r1 = 0; \ 868 *(u32*)(r10 - 4) = r1; \ 869 r2 = r10; \ 870 r2 += -4; \ 871 r1 = %[map_sockhash] ll; \ 872 call %[bpf_map_lookup_elem]; \ 873 r0 = 0; \ 874 exit; \ 875 " : 876 : __imm(bpf_map_lookup_elem), 877 __imm_addr(map_sockhash) 878 : __clobber_all); 879 } 880 881 SEC("sk_skb") 882 __description("bpf_map_lookup_elem(sockmap, &key); sk->type [fullsock field]; bpf_sk_release(sk)") 883 __success 884 __naked void field_bpf_sk_release_sk_1(void) 885 { 886 asm volatile (" \ 887 r1 = 0; \ 888 *(u32*)(r10 - 4) = r1; \ 889 r2 = r10; \ 890 r2 += -4; \ 891 r1 = %[map_sockmap] ll; \ 892 call %[bpf_map_lookup_elem]; \ 893 if r0 != 0 goto l0_%=; \ 894 exit; \ 895 l0_%=: r1 = r0; \ 896 r0 = *(u32*)(r0 + %[bpf_sock_type]); \ 897 call %[bpf_sk_release]; \ 898 exit; \ 899 " : 900 : __imm(bpf_map_lookup_elem), 901 __imm(bpf_sk_release), 902 __imm_addr(map_sockmap), 903 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)) 904 : __clobber_all); 905 } 906 907 SEC("sk_skb") 908 __description("bpf_map_lookup_elem(sockhash, &key); sk->type [fullsock field]; bpf_sk_release(sk)") 909 __success 910 __naked void field_bpf_sk_release_sk_2(void) 911 { 912 asm volatile (" \ 913 r1 = 0; \ 914 *(u32*)(r10 - 4) = r1; \ 915 r2 = r10; \ 916 r2 += -4; \ 917 r1 = %[map_sockhash] ll; \ 918 call %[bpf_map_lookup_elem]; \ 919 if r0 != 0 goto l0_%=; \ 920 exit; \ 921 l0_%=: r1 = r0; \ 922 r0 = *(u32*)(r0 + %[bpf_sock_type]); \ 923 call %[bpf_sk_release]; \ 924 exit; \ 925 " : 926 : __imm(bpf_map_lookup_elem), 927 __imm(bpf_sk_release), 928 __imm_addr(map_sockhash), 929 __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type)) 930 : __clobber_all); 931 } 932 933 SEC("sk_reuseport") 934 __description("bpf_sk_select_reuseport(ctx, reuseport_array, &key, flags)") 935 __success 936 __naked void ctx_reuseport_array_key_flags(void) 937 { 938 asm volatile (" \ 939 r4 = 0; \ 940 r2 = 0; \ 941 *(u32*)(r10 - 4) = r2; \ 942 r3 = r10; \ 943 r3 += -4; \ 944 r2 = %[map_reuseport_array] ll; \ 945 call %[bpf_sk_select_reuseport]; \ 946 exit; \ 947 " : 948 : __imm(bpf_sk_select_reuseport), 949 __imm_addr(map_reuseport_array) 950 : __clobber_all); 951 } 952 953 SEC("sk_reuseport") 954 __description("bpf_sk_select_reuseport(ctx, sockmap, &key, flags)") 955 __success 956 __naked void reuseport_ctx_sockmap_key_flags(void) 957 { 958 asm volatile (" \ 959 r4 = 0; \ 960 r2 = 0; \ 961 *(u32*)(r10 - 4) = r2; \ 962 r3 = r10; \ 963 r3 += -4; \ 964 r2 = %[map_sockmap] ll; \ 965 call %[bpf_sk_select_reuseport]; \ 966 exit; \ 967 " : 968 : __imm(bpf_sk_select_reuseport), 969 __imm_addr(map_sockmap) 970 : __clobber_all); 971 } 972 973 SEC("sk_reuseport") 974 __description("bpf_sk_select_reuseport(ctx, sockhash, &key, flags)") 975 __success 976 __naked void reuseport_ctx_sockhash_key_flags(void) 977 { 978 asm volatile (" \ 979 r4 = 0; \ 980 r2 = 0; \ 981 *(u32*)(r10 - 4) = r2; \ 982 r3 = r10; \ 983 r3 += -4; \ 984 r2 = %[map_sockmap] ll; \ 985 call %[bpf_sk_select_reuseport]; \ 986 exit; \ 987 " : 988 : __imm(bpf_sk_select_reuseport), 989 __imm_addr(map_sockmap) 990 : __clobber_all); 991 } 992 993 SEC("tc") 994 __description("mark null check on return value of bpf_skc_to helpers") 995 __failure __msg("invalid mem access") 996 __naked void of_bpf_skc_to_helpers(void) 997 { 998 asm volatile (" \ 999 r1 = *(u64*)(r1 + %[__sk_buff_sk]); \ 1000 if r1 != 0 goto l0_%=; \ 1001 r0 = 0; \ 1002 exit; \ 1003 l0_%=: r6 = r1; \ 1004 call %[bpf_skc_to_tcp_sock]; \ 1005 r7 = r0; \ 1006 r1 = r6; \ 1007 call %[bpf_skc_to_tcp_request_sock]; \ 1008 r8 = r0; \ 1009 if r8 != 0 goto l1_%=; \ 1010 r0 = 0; \ 1011 exit; \ 1012 l1_%=: r0 = *(u8*)(r7 + 0); \ 1013 exit; \ 1014 " : 1015 : __imm(bpf_skc_to_tcp_request_sock), 1016 __imm(bpf_skc_to_tcp_sock), 1017 __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)) 1018 : __clobber_all); 1019 } 1020 1021 SEC("cgroup/post_bind4") 1022 __description("sk->src_ip6[0] [load 1st byte]") 1023 __failure __msg("invalid bpf_context access off=28 size=2") 1024 __naked void post_bind4_read_src_ip6(void) 1025 { 1026 asm volatile (" \ 1027 r6 = r1; \ 1028 r7 = *(u16*)(r6 + %[bpf_sock_src_ip6_0]); \ 1029 r0 = 1; \ 1030 exit; \ 1031 " : 1032 : __imm_const(bpf_sock_src_ip6_0, offsetof(struct bpf_sock, src_ip6[0])) 1033 : __clobber_all); 1034 } 1035 1036 SEC("cgroup/post_bind4") 1037 __description("sk->mark [load mark]") 1038 __failure __msg("invalid bpf_context access off=16 size=2") 1039 __naked void post_bind4_read_mark(void) 1040 { 1041 asm volatile (" \ 1042 r6 = r1; \ 1043 r7 = *(u16*)(r6 + %[bpf_sock_mark]); \ 1044 r0 = 1; \ 1045 exit; \ 1046 " : 1047 : __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)) 1048 : __clobber_all); 1049 } 1050 1051 SEC("cgroup/post_bind6") 1052 __description("sk->src_ip4 [load src_ip4]") 1053 __failure __msg("invalid bpf_context access off=24 size=2") 1054 __naked void post_bind6_read_src_ip4(void) 1055 { 1056 asm volatile (" \ 1057 r6 = r1; \ 1058 r7 = *(u16*)(r6 + %[bpf_sock_src_ip4]); \ 1059 r0 = 1; \ 1060 exit; \ 1061 " : 1062 : __imm_const(bpf_sock_src_ip4, offsetof(struct bpf_sock, src_ip4)) 1063 : __clobber_all); 1064 } 1065 1066 SEC("cgroup/sock_create") 1067 __description("sk->src_port [word load]") 1068 __failure __msg("invalid bpf_context access off=44 size=2") 1069 __naked void sock_create_read_src_port(void) 1070 { 1071 asm volatile (" \ 1072 r6 = r1; \ 1073 r7 = *(u16*)(r6 + %[bpf_sock_src_port]); \ 1074 r0 = 1; \ 1075 exit; \ 1076 " : 1077 : __imm_const(bpf_sock_src_port, offsetof(struct bpf_sock, src_port)) 1078 : __clobber_all); 1079 } 1080 1081 __noinline 1082 long skb_pull_data2(struct __sk_buff *sk, __u32 len) 1083 { 1084 return bpf_skb_pull_data(sk, len); 1085 } 1086 1087 __noinline 1088 long skb_pull_data1(struct __sk_buff *sk, __u32 len) 1089 { 1090 return skb_pull_data2(sk, len); 1091 } 1092 1093 /* global function calls bpf_skb_pull_data(), which invalidates packet 1094 * pointers established before global function call. 1095 */ 1096 SEC("tc") 1097 __failure __msg("invalid mem access") 1098 int invalidate_pkt_pointers_from_global_func(struct __sk_buff *sk) 1099 { 1100 int *p = (void *)(long)sk->data; 1101 1102 if ((void *)(p + 1) > (void *)(long)sk->data_end) 1103 return TCX_DROP; 1104 skb_pull_data1(sk, 0); 1105 *p = 42; /* this is unsafe */ 1106 return TCX_PASS; 1107 } 1108 1109 __noinline 1110 long xdp_pull_data2(struct xdp_md *x, __u32 len) 1111 { 1112 return bpf_xdp_pull_data(x, len); 1113 } 1114 1115 __noinline 1116 long xdp_pull_data1(struct xdp_md *x, __u32 len) 1117 { 1118 return xdp_pull_data2(x, len); 1119 } 1120 1121 /* global function calls bpf_xdp_pull_data(), which invalidates packet 1122 * pointers established before global function call. 1123 */ 1124 SEC("xdp") 1125 __failure __msg("invalid mem access") 1126 int invalidate_xdp_pkt_pointers_from_global_func(struct xdp_md *x) 1127 { 1128 int *p = (void *)(long)x->data; 1129 1130 if ((void *)(p + 1) > (void *)(long)x->data_end) 1131 return XDP_DROP; 1132 xdp_pull_data1(x, 0); 1133 *p = 42; /* this is unsafe */ 1134 return XDP_PASS; 1135 } 1136 1137 /* XDP packet changing kfunc calls invalidate packet pointers */ 1138 SEC("xdp") 1139 __failure __msg("invalid mem access") 1140 int invalidate_xdp_pkt_pointers(struct xdp_md *x) 1141 { 1142 int *p = (void *)(long)x->data; 1143 1144 if ((void *)(p + 1) > (void *)(long)x->data_end) 1145 return XDP_DROP; 1146 bpf_xdp_pull_data(x, 0); 1147 *p = 42; /* this is unsafe */ 1148 return XDP_PASS; 1149 } 1150 1151 __noinline 1152 int tail_call(struct __sk_buff *sk) 1153 { 1154 bpf_tail_call_static(sk, &jmp_table, 0); 1155 return 0; 1156 } 1157 1158 static __noinline 1159 int static_tail_call(struct __sk_buff *sk) 1160 { 1161 int ret = 0; 1162 1163 bpf_tail_call_static(sk, &jmp_table, 0); 1164 barrier_var(ret); 1165 return ret; 1166 } 1167 1168 /* Tail calls in sub-programs invalidate packet pointers. */ 1169 SEC("tc") 1170 __failure __msg("invalid mem access") 1171 int invalidate_pkt_pointers_by_global_tail_call(struct __sk_buff *sk) 1172 { 1173 int *p = (void *)(long)sk->data; 1174 1175 if ((void *)(p + 1) > (void *)(long)sk->data_end) 1176 return TCX_DROP; 1177 tail_call(sk); 1178 *p = 42; /* this is unsafe */ 1179 return TCX_PASS; 1180 } 1181 1182 /* Tail calls in static sub-programs invalidate packet pointers. */ 1183 SEC("tc") 1184 __failure __msg("invalid mem access") 1185 int invalidate_pkt_pointers_by_static_tail_call(struct __sk_buff *sk) 1186 { 1187 int *p = (void *)(long)sk->data; 1188 int ret; 1189 1190 if ((void *)(p + 1) > (void *)(long)sk->data_end) 1191 return TCX_DROP; 1192 ret = static_tail_call(sk); 1193 __sink(ret); 1194 *p = 42; /* this is unsafe */ 1195 return TCX_PASS; 1196 } 1197 1198 /* Direct tail calls do not invalidate packet pointers. */ 1199 SEC("tc") 1200 __success 1201 int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk) 1202 { 1203 int *p = (void *)(long)sk->data; 1204 1205 if ((void *)(p + 1) > (void *)(long)sk->data_end) 1206 return TCX_DROP; 1207 bpf_tail_call_static(sk, &jmp_table, 0); 1208 *p = 42; /* this is NOT unsafe: tail calls don't return */ 1209 return TCX_PASS; 1210 } 1211 1212 char _license[] SEC("license") = "GPL"; 1213