1// SPDX-License-Identifier: GPL-2.0 2/* Converted from tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c */ 3 4#include <linux/bpf.h> 5#include <bpf/bpf_helpers.h> 6#include "bpf_misc.h" 7 8struct { 9 __uint(type, BPF_MAP_TYPE_HASH); 10 __uint(max_entries, 1); 11 __type(key, long long); 12 __type(value, long long); 13} map_hash_8b SEC(".maps"); 14 15SEC("socket") 16__description("bounds checks mixing signed and unsigned, positive bounds") 17__failure __msg("unbounded min value") 18__failure_unpriv 19__naked void signed_and_unsigned_positive_bounds(void) 20{ 21 asm volatile (" \ 22 call %[bpf_ktime_get_ns]; \ 23 *(u64*)(r10 - 16) = r0; \ 24 r1 = 0; \ 25 *(u64*)(r10 - 8) = r1; \ 26 r2 = r10; \ 27 r2 += -8; \ 28 r1 = %[map_hash_8b] ll; \ 29 call %[bpf_map_lookup_elem]; \ 30 if r0 == 0 goto l0_%=; \ 31 r1 = *(u64*)(r10 - 16); \ 32 r2 = 2; \ 33 if r2 >= r1 goto l0_%=; \ 34 if r1 s> 4 goto l0_%=; \ 35 r0 += r1; \ 36 r1 = 0; \ 37 *(u8*)(r0 + 0) = r1; \ 38l0_%=: r0 = 0; \ 39 exit; \ 40" : 41 : __imm(bpf_ktime_get_ns), 42 __imm(bpf_map_lookup_elem), 43 __imm_addr(map_hash_8b) 44 : __clobber_all); 45} 46 47SEC("socket") 48__description("bounds checks mixing signed and unsigned") 49__failure __msg("unbounded min value") 50__failure_unpriv 51__naked void checks_mixing_signed_and_unsigned(void) 52{ 53 asm volatile (" \ 54 call %[bpf_ktime_get_ns]; \ 55 *(u64*)(r10 - 16) = r0; \ 56 r1 = 0; \ 57 *(u64*)(r10 - 8) = r1; \ 58 r2 = r10; \ 59 r2 += -8; \ 60 r1 = %[map_hash_8b] ll; \ 61 call %[bpf_map_lookup_elem]; \ 62 if r0 == 0 goto l0_%=; \ 63 r1 = *(u64*)(r10 - 16); \ 64 r2 = -1; \ 65 if r1 > r2 goto l0_%=; \ 66 if r1 s> 1 goto l0_%=; \ 67 r0 += r1; \ 68 r1 = 0; \ 69 *(u8*)(r0 + 0) = r1; \ 70l0_%=: r0 = 0; \ 71 exit; \ 72" : 73 : __imm(bpf_ktime_get_ns), 74 __imm(bpf_map_lookup_elem), 75 __imm_addr(map_hash_8b) 76 : __clobber_all); 77} 78 79SEC("socket") 80__description("bounds checks mixing signed and unsigned, variant 2") 81__failure __msg("unbounded min value") 82__failure_unpriv 83__naked void signed_and_unsigned_variant_2(void) 84{ 85 asm volatile (" \ 86 call %[bpf_ktime_get_ns]; \ 87 *(u64*)(r10 - 16) = r0; \ 88 r1 = 0; \ 89 *(u64*)(r10 - 8) = r1; \ 90 r2 = r10; \ 91 r2 += -8; \ 92 r1 = %[map_hash_8b] ll; \ 93 call %[bpf_map_lookup_elem]; \ 94 if r0 == 0 goto l0_%=; \ 95 r1 = *(u64*)(r10 - 16); \ 96 r2 = -1; \ 97 if r1 > r2 goto l0_%=; \ 98 r8 = 0; \ 99 r8 += r1; \ 100 if r8 s> 1 goto l0_%=; \ 101 r0 += r8; \ 102 r0 = 0; \ 103 *(u8*)(r8 + 0) = r0; \ 104l0_%=: r0 = 0; \ 105 exit; \ 106" : 107 : __imm(bpf_ktime_get_ns), 108 __imm(bpf_map_lookup_elem), 109 __imm_addr(map_hash_8b) 110 : __clobber_all); 111} 112 113SEC("socket") 114__description("bounds checks mixing signed and unsigned, variant 3") 115__failure __msg("unbounded min value") 116__failure_unpriv 117__naked void signed_and_unsigned_variant_3(void) 118{ 119 asm volatile (" \ 120 call %[bpf_ktime_get_ns]; \ 121 *(u64*)(r10 - 16) = r0; \ 122 r1 = 0; \ 123 *(u64*)(r10 - 8) = r1; \ 124 r2 = r10; \ 125 r2 += -8; \ 126 r1 = %[map_hash_8b] ll; \ 127 call %[bpf_map_lookup_elem]; \ 128 if r0 == 0 goto l0_%=; \ 129 r1 = *(u64*)(r10 - 16); \ 130 r2 = -1; \ 131 if r1 > r2 goto l0_%=; \ 132 r8 = r1; \ 133 if r8 s> 1 goto l0_%=; \ 134 r0 += r8; \ 135 r0 = 0; \ 136 *(u8*)(r8 + 0) = r0; \ 137l0_%=: r0 = 0; \ 138 exit; \ 139" : 140 : __imm(bpf_ktime_get_ns), 141 __imm(bpf_map_lookup_elem), 142 __imm_addr(map_hash_8b) 143 : __clobber_all); 144} 145 146SEC("socket") 147__description("bounds checks mixing signed and unsigned, variant 4") 148__success __success_unpriv __retval(0) 149__naked void signed_and_unsigned_variant_4(void) 150{ 151 asm volatile (" \ 152 call %[bpf_ktime_get_ns]; \ 153 *(u64*)(r10 - 16) = r0; \ 154 r1 = 0; \ 155 *(u64*)(r10 - 8) = r1; \ 156 r2 = r10; \ 157 r2 += -8; \ 158 r1 = %[map_hash_8b] ll; \ 159 call %[bpf_map_lookup_elem]; \ 160 if r0 == 0 goto l0_%=; \ 161 r1 = *(u64*)(r10 - 16); \ 162 r2 = 1; \ 163 r1 &= r2; \ 164 if r1 s> 1 goto l0_%=; \ 165 r0 += r1; \ 166 r1 = 0; \ 167 *(u8*)(r0 + 0) = r1; \ 168l0_%=: r0 = 0; \ 169 exit; \ 170" : 171 : __imm(bpf_ktime_get_ns), 172 __imm(bpf_map_lookup_elem), 173 __imm_addr(map_hash_8b) 174 : __clobber_all); 175} 176 177SEC("socket") 178__description("bounds checks mixing signed and unsigned, variant 5") 179__failure __msg("unbounded min value") 180__failure_unpriv 181__naked void signed_and_unsigned_variant_5(void) 182{ 183 asm volatile (" \ 184 call %[bpf_ktime_get_ns]; \ 185 *(u64*)(r10 - 16) = r0; \ 186 r1 = 0; \ 187 *(u64*)(r10 - 8) = r1; \ 188 r2 = r10; \ 189 r2 += -8; \ 190 r1 = %[map_hash_8b] ll; \ 191 call %[bpf_map_lookup_elem]; \ 192 if r0 == 0 goto l0_%=; \ 193 r1 = *(u64*)(r10 - 16); \ 194 r2 = -1; \ 195 if r1 > r2 goto l0_%=; \ 196 if r1 s> 1 goto l0_%=; \ 197 r0 += 4; \ 198 r0 -= r1; \ 199 r1 = 0; \ 200 *(u8*)(r0 + 0) = r1; \ 201 r0 = 0; \ 202l0_%=: exit; \ 203" : 204 : __imm(bpf_ktime_get_ns), 205 __imm(bpf_map_lookup_elem), 206 __imm_addr(map_hash_8b) 207 : __clobber_all); 208} 209 210SEC("socket") 211__description("bounds checks mixing signed and unsigned, variant 6") 212__failure __msg("R4 min value is negative, either use unsigned") 213__failure_unpriv 214__naked void signed_and_unsigned_variant_6(void) 215{ 216 asm volatile (" \ 217 r9 = r1; \ 218 call %[bpf_ktime_get_ns]; \ 219 *(u64*)(r10 - 16) = r0; \ 220 r1 = r9; \ 221 r2 = 0; \ 222 r3 = r10; \ 223 r3 += -512; \ 224 r4 = *(u64*)(r10 - 16); \ 225 r6 = -1; \ 226 if r4 > r6 goto l0_%=; \ 227 if r4 s> 1 goto l0_%=; \ 228 r4 += 1; \ 229 r5 = 0; \ 230 r6 = 0; \ 231 *(u16*)(r10 - 512) = r6; \ 232 call %[bpf_skb_load_bytes]; \ 233l0_%=: r0 = 0; \ 234 exit; \ 235" : 236 : __imm(bpf_ktime_get_ns), 237 __imm(bpf_skb_load_bytes) 238 : __clobber_all); 239} 240 241SEC("socket") 242__description("bounds checks mixing signed and unsigned, variant 7") 243__success __success_unpriv __retval(0) 244__naked void signed_and_unsigned_variant_7(void) 245{ 246 asm volatile (" \ 247 call %[bpf_ktime_get_ns]; \ 248 *(u64*)(r10 - 16) = r0; \ 249 r1 = 0; \ 250 *(u64*)(r10 - 8) = r1; \ 251 r2 = r10; \ 252 r2 += -8; \ 253 r1 = %[map_hash_8b] ll; \ 254 call %[bpf_map_lookup_elem]; \ 255 if r0 == 0 goto l0_%=; \ 256 r1 = *(u64*)(r10 - 16); \ 257 r2 = %[__imm_0]; \ 258 if r1 > r2 goto l0_%=; \ 259 if r1 s> 1 goto l0_%=; \ 260 r0 += r1; \ 261 r1 = 0; \ 262 *(u8*)(r0 + 0) = r1; \ 263l0_%=: r0 = 0; \ 264 exit; \ 265" : 266 : __imm(bpf_ktime_get_ns), 267 __imm(bpf_map_lookup_elem), 268 __imm_addr(map_hash_8b), 269 __imm_const(__imm_0, 1024 * 1024 * 1024) 270 : __clobber_all); 271} 272 273SEC("socket") 274__description("bounds checks mixing signed and unsigned, variant 8") 275__failure __msg("unbounded min value") 276__failure_unpriv 277__naked void signed_and_unsigned_variant_8(void) 278{ 279 asm volatile (" \ 280 call %[bpf_ktime_get_ns]; \ 281 *(u64*)(r10 - 16) = r0; \ 282 r1 = 0; \ 283 *(u64*)(r10 - 8) = r1; \ 284 r2 = r10; \ 285 r2 += -8; \ 286 r1 = %[map_hash_8b] ll; \ 287 call %[bpf_map_lookup_elem]; \ 288 if r0 == 0 goto l0_%=; \ 289 r1 = *(u64*)(r10 - 16); \ 290 r2 = -1; \ 291 if r2 > r1 goto l1_%=; \ 292 r0 = 0; \ 293 exit; \ 294l1_%=: if r1 s> 1 goto l0_%=; \ 295 r0 += r1; \ 296 r1 = 0; \ 297 *(u8*)(r0 + 0) = r1; \ 298l0_%=: r0 = 0; \ 299 exit; \ 300" : 301 : __imm(bpf_ktime_get_ns), 302 __imm(bpf_map_lookup_elem), 303 __imm_addr(map_hash_8b) 304 : __clobber_all); 305} 306 307SEC("socket") 308__description("bounds checks mixing signed and unsigned, variant 9") 309__success __success_unpriv __retval(0) 310__naked void signed_and_unsigned_variant_9(void) 311{ 312 asm volatile (" \ 313 call %[bpf_ktime_get_ns]; \ 314 *(u64*)(r10 - 16) = r0; \ 315 r1 = 0; \ 316 *(u64*)(r10 - 8) = r1; \ 317 r2 = r10; \ 318 r2 += -8; \ 319 r1 = %[map_hash_8b] ll; \ 320 call %[bpf_map_lookup_elem]; \ 321 if r0 == 0 goto l0_%=; \ 322 r1 = *(u64*)(r10 - 16); \ 323 r2 = -9223372036854775808ULL ll; \ 324 if r2 > r1 goto l1_%=; \ 325 r0 = 0; \ 326 exit; \ 327l1_%=: if r1 s> 1 goto l0_%=; \ 328 r0 += r1; \ 329 r1 = 0; \ 330 *(u8*)(r0 + 0) = r1; \ 331l0_%=: r0 = 0; \ 332 exit; \ 333" : 334 : __imm(bpf_ktime_get_ns), 335 __imm(bpf_map_lookup_elem), 336 __imm_addr(map_hash_8b) 337 : __clobber_all); 338} 339 340SEC("socket") 341__description("bounds checks mixing signed and unsigned, variant 10") 342__failure __msg("unbounded min value") 343__failure_unpriv 344__naked void signed_and_unsigned_variant_10(void) 345{ 346 asm volatile (" \ 347 call %[bpf_ktime_get_ns]; \ 348 *(u64*)(r10 - 16) = r0; \ 349 r1 = 0; \ 350 *(u64*)(r10 - 8) = r1; \ 351 r2 = r10; \ 352 r2 += -8; \ 353 r1 = %[map_hash_8b] ll; \ 354 call %[bpf_map_lookup_elem]; \ 355 if r0 == 0 goto l0_%=; \ 356 r1 = *(u64*)(r10 - 16); \ 357 r2 = -1; \ 358 if r2 > r1 goto l1_%=; \ 359 r0 = 0; \ 360 exit; \ 361l1_%=: if r1 s> 1 goto l0_%=; \ 362 r0 += r1; \ 363 r1 = 0; \ 364 *(u8*)(r0 + 0) = r1; \ 365l0_%=: r0 = 0; \ 366 exit; \ 367" : 368 : __imm(bpf_ktime_get_ns), 369 __imm(bpf_map_lookup_elem), 370 __imm_addr(map_hash_8b) 371 : __clobber_all); 372} 373 374SEC("socket") 375__description("bounds checks mixing signed and unsigned, variant 11") 376__failure __msg("unbounded min value") 377__failure_unpriv 378__naked void signed_and_unsigned_variant_11(void) 379{ 380 asm volatile (" \ 381 call %[bpf_ktime_get_ns]; \ 382 *(u64*)(r10 - 16) = r0; \ 383 r1 = 0; \ 384 *(u64*)(r10 - 8) = r1; \ 385 r2 = r10; \ 386 r2 += -8; \ 387 r1 = %[map_hash_8b] ll; \ 388 call %[bpf_map_lookup_elem]; \ 389 if r0 == 0 goto l0_%=; \ 390 r1 = *(u64*)(r10 - 16); \ 391 r2 = -1; \ 392 if r2 >= r1 goto l1_%=; \ 393 /* Dead branch. */ \ 394 r0 = 0; \ 395 exit; \ 396l1_%=: if r1 s> 1 goto l0_%=; \ 397 r0 += r1; \ 398 r1 = 0; \ 399 *(u8*)(r0 + 0) = r1; \ 400l0_%=: r0 = 0; \ 401 exit; \ 402" : 403 : __imm(bpf_ktime_get_ns), 404 __imm(bpf_map_lookup_elem), 405 __imm_addr(map_hash_8b) 406 : __clobber_all); 407} 408 409SEC("socket") 410__description("bounds checks mixing signed and unsigned, variant 12") 411__failure __msg("unbounded min value") 412__failure_unpriv 413__naked void signed_and_unsigned_variant_12(void) 414{ 415 asm volatile (" \ 416 call %[bpf_ktime_get_ns]; \ 417 *(u64*)(r10 - 16) = r0; \ 418 r1 = 0; \ 419 *(u64*)(r10 - 8) = r1; \ 420 r2 = r10; \ 421 r2 += -8; \ 422 r1 = %[map_hash_8b] ll; \ 423 call %[bpf_map_lookup_elem]; \ 424 if r0 == 0 goto l0_%=; \ 425 r1 = *(u64*)(r10 - 16); \ 426 r2 = -6; \ 427 if r2 >= r1 goto l1_%=; \ 428 r0 = 0; \ 429 exit; \ 430l1_%=: if r1 s> 1 goto l0_%=; \ 431 r0 += r1; \ 432 r1 = 0; \ 433 *(u8*)(r0 + 0) = r1; \ 434l0_%=: r0 = 0; \ 435 exit; \ 436" : 437 : __imm(bpf_ktime_get_ns), 438 __imm(bpf_map_lookup_elem), 439 __imm_addr(map_hash_8b) 440 : __clobber_all); 441} 442 443SEC("socket") 444__description("bounds checks mixing signed and unsigned, variant 13") 445__failure __msg("unbounded min value") 446__failure_unpriv 447__naked void signed_and_unsigned_variant_13(void) 448{ 449 asm volatile (" \ 450 call %[bpf_ktime_get_ns]; \ 451 *(u64*)(r10 - 16) = r0; \ 452 r1 = 0; \ 453 *(u64*)(r10 - 8) = r1; \ 454 r2 = r10; \ 455 r2 += -8; \ 456 r1 = %[map_hash_8b] ll; \ 457 call %[bpf_map_lookup_elem]; \ 458 if r0 == 0 goto l0_%=; \ 459 r1 = *(u64*)(r10 - 16); \ 460 r2 = 2; \ 461 if r2 >= r1 goto l0_%=; \ 462 r7 = 1; \ 463 if r7 s> 0 goto l1_%=; \ 464l0_%=: r0 = 0; \ 465 exit; \ 466l1_%=: r7 += r1; \ 467 if r7 s> 4 goto l2_%=; \ 468 r0 += r7; \ 469 r1 = 0; \ 470 *(u8*)(r0 + 0) = r1; \ 471l2_%=: r0 = 0; \ 472 exit; \ 473" : 474 : __imm(bpf_ktime_get_ns), 475 __imm(bpf_map_lookup_elem), 476 __imm_addr(map_hash_8b) 477 : __clobber_all); 478} 479 480SEC("socket") 481__description("bounds checks mixing signed and unsigned, variant 14") 482__failure __msg("unbounded min value") 483__failure_unpriv 484__naked void signed_and_unsigned_variant_14(void) 485{ 486 asm volatile (" \ 487 r9 = *(u32*)(r1 + %[__sk_buff_mark]); \ 488 call %[bpf_ktime_get_ns]; \ 489 *(u64*)(r10 - 16) = r0; \ 490 r1 = 0; \ 491 *(u64*)(r10 - 8) = r1; \ 492 r2 = r10; \ 493 r2 += -8; \ 494 r1 = %[map_hash_8b] ll; \ 495 call %[bpf_map_lookup_elem]; \ 496 if r0 == 0 goto l0_%=; \ 497 r1 = *(u64*)(r10 - 16); \ 498 r2 = -1; \ 499 r8 = 2; \ 500 if r9 == 42 goto l1_%=; \ 501 if r8 s> r1 goto l2_%=; \ 502l3_%=: if r1 s> 1 goto l2_%=; \ 503 r0 += r1; \ 504l0_%=: r1 = 0; \ 505 *(u8*)(r0 + 0) = r1; \ 506l2_%=: r0 = 0; \ 507 exit; \ 508l1_%=: if r1 > r2 goto l2_%=; \ 509 goto l3_%=; \ 510" : 511 : __imm(bpf_ktime_get_ns), 512 __imm(bpf_map_lookup_elem), 513 __imm_addr(map_hash_8b), 514 __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) 515 : __clobber_all); 516} 517 518SEC("socket") 519__description("bounds checks mixing signed and unsigned, variant 15") 520__failure __msg("unbounded min value") 521__failure_unpriv 522__naked void signed_and_unsigned_variant_15(void) 523{ 524 asm volatile (" \ 525 call %[bpf_ktime_get_ns]; \ 526 *(u64*)(r10 - 16) = r0; \ 527 r1 = 0; \ 528 *(u64*)(r10 - 8) = r1; \ 529 r2 = r10; \ 530 r2 += -8; \ 531 r1 = %[map_hash_8b] ll; \ 532 call %[bpf_map_lookup_elem]; \ 533 if r0 == 0 goto l0_%=; \ 534 r1 = *(u64*)(r10 - 16); \ 535 r2 = -6; \ 536 if r2 >= r1 goto l1_%=; \ 537l0_%=: r0 = 0; \ 538 exit; \ 539l1_%=: r0 += r1; \ 540 if r0 > 1 goto l2_%=; \ 541 r0 = 0; \ 542 exit; \ 543l2_%=: r1 = 0; \ 544 *(u8*)(r0 + 0) = r1; \ 545 r0 = 0; \ 546 exit; \ 547" : 548 : __imm(bpf_ktime_get_ns), 549 __imm(bpf_map_lookup_elem), 550 __imm_addr(map_hash_8b) 551 : __clobber_all); 552} 553 554char _license[] SEC("license") = "GPL"; 555