Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: test case for relaxed prunning of active_lock.id

Check that verifier.c:states_equal() uses check_ids() to match
consistent active_lock/map_value configurations. This allows to prune
states with active spin locks even if numerical values of
active_lock ids do not match across compared states.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20221209135733.28851-8-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
efd6286f 2026f206

+75
+75
tools/testing/selftests/bpf/verifier/spin_lock.c
··· 370 370 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 371 371 .flags = BPF_F_TEST_STATE_FREQ, 372 372 }, 373 + /* Make sure that regsafe() compares ids for spin lock records using 374 + * check_ids(): 375 + * 1: r9 = map_lookup_elem(...) ; r9.id == 1 376 + * 2: r8 = map_lookup_elem(...) ; r8.id == 2 377 + * 3: r7 = ktime_get_ns() 378 + * 4: r6 = ktime_get_ns() 379 + * 5: if r6 > r7 goto <9> 380 + * 6: spin_lock(r8) 381 + * 7: r9 = r8 382 + * 8: goto <10> 383 + * 9: spin_lock(r9) 384 + * 10: spin_unlock(r9) ; r9.id == 1 || r9.id == 2 and lock is active, 385 + * ; second visit to (10) should be considered safe 386 + * ; if check_ids() is used. 387 + * 11: exit(0) 388 + */ 389 + { 390 + "spin_lock: regsafe() check_ids() similar id mappings", 391 + .insns = { 392 + BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 0), 393 + /* r9 = map_lookup_elem(...) */ 394 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 395 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), 396 + BPF_LD_MAP_FD(BPF_REG_1, 397 + 0), 398 + BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 399 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 24), 400 + BPF_MOV64_REG(BPF_REG_9, BPF_REG_0), 401 + /* r8 = map_lookup_elem(...) */ 402 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 403 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), 404 + BPF_LD_MAP_FD(BPF_REG_1, 405 + 0), 406 + BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 407 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 18), 408 + BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), 409 + /* r7 = ktime_get_ns() */ 410 + BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns), 411 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), 412 + /* r6 = ktime_get_ns() */ 413 + BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns), 414 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 415 + /* if r6 > r7 goto +5 ; no new information about the state is derived from 416 + * ; this check, thus produced verifier states differ 417 + * ; only in 'insn_idx' 418 + * spin_lock(r8) 419 + * r9 = r8 420 + * goto unlock 421 + */ 422 + BPF_JMP_REG(BPF_JGT, BPF_REG_6, BPF_REG_7, 5), 423 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_8), 424 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 4), 425 + BPF_EMIT_CALL(BPF_FUNC_spin_lock), 426 + BPF_MOV64_REG(BPF_REG_9, BPF_REG_8), 427 + BPF_JMP_A(3), 428 + /* spin_lock(r9) */ 429 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_9), 430 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 4), 431 + BPF_EMIT_CALL(BPF_FUNC_spin_lock), 432 + /* spin_unlock(r9) */ 433 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_9), 434 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 4), 435 + BPF_EMIT_CALL(BPF_FUNC_spin_unlock), 436 + /* exit(0) */ 437 + BPF_MOV64_IMM(BPF_REG_0, 0), 438 + BPF_EXIT_INSN(), 439 + }, 440 + .fixup_map_spin_lock = { 3, 10 }, 441 + .result = VERBOSE_ACCEPT, 442 + .errstr = "28: safe", 443 + .result_unpriv = REJECT, 444 + .errstr_unpriv = "", 445 + .prog_type = BPF_PROG_TYPE_CGROUP_SKB, 446 + .flags = BPF_F_TEST_STATE_FREQ, 447 + },