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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'bpf-fix-linked-register-tracking'

Puranjay Mohan says:

====================
bpf: Fix linked register tracking

This patch fixes the linked register tracking when multiple links from
the same register are created with a sync between the creation of these
links. The sync corrupts the id of the register and therefore the second
link is not created properly. See the patch description to understand
more.

The fix is to preserve the id while doing the sync similar to the off.
====================

Link: https://patch.msgid.link/20260115151143.1344724-1-puranjay@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+36 -1
+3 -1
kernel/bpf/verifier.c
··· 16871 16871 } else { 16872 16872 s32 saved_subreg_def = reg->subreg_def; 16873 16873 s32 saved_off = reg->off; 16874 + u32 saved_id = reg->id; 16874 16875 16875 16876 fake_reg.type = SCALAR_VALUE; 16876 16877 __mark_reg_known(&fake_reg, (s32)reg->off - (s32)known_reg->off); ··· 16879 16878 /* reg = known_reg; reg += delta */ 16880 16879 copy_register_state(reg, known_reg); 16881 16880 /* 16882 - * Must preserve off, id and add_const flag, 16881 + * Must preserve off, id and subreg_def flag, 16883 16882 * otherwise another sync_linked_regs() will be incorrect. 16884 16883 */ 16885 16884 reg->off = saved_off; 16885 + reg->id = saved_id; 16886 16886 reg->subreg_def = saved_subreg_def; 16887 16887 16888 16888 scalar32_min_max_add(reg, &fake_reg);
+33
tools/testing/selftests/bpf/progs/verifier_linked_scalars.c
··· 31 31 " ::: __clobber_all); 32 32 } 33 33 34 + /* 35 + * Test that sync_linked_regs() preserves register IDs. 36 + * 37 + * The sync_linked_regs() function copies bounds from known_reg to linked 38 + * registers. When doing so, it must preserve each register's original id 39 + * to allow subsequent syncs from the same source to work correctly. 40 + * 41 + */ 42 + SEC("socket") 43 + __success 44 + __naked void sync_linked_regs_preserves_id(void) 45 + { 46 + asm volatile (" \ 47 + call %[bpf_get_prandom_u32]; \ 48 + r0 &= 0xff; /* r0 in [0, 255] */ \ 49 + r1 = r0; /* r0, r1 linked with id 1 */ \ 50 + r1 += 4; /* r1 has id=1 and off=4 in [4, 259] */ \ 51 + if r1 < 10 goto l0_%=; \ 52 + /* r1 in [10, 259], r0 synced to [6, 255] */ \ 53 + r2 = r0; /* r2 has id=1 and in [6, 255] */ \ 54 + if r1 < 14 goto l0_%=; \ 55 + /* r1 in [14, 259], r0 synced to [10, 255] */ \ 56 + if r0 >= 10 goto l0_%=; \ 57 + /* Never executed */ \ 58 + r0 /= 0; \ 59 + l0_%=: \ 60 + r0 = 0; \ 61 + exit; \ 62 + " : 63 + : __imm(bpf_get_prandom_u32) 64 + : __clobber_all); 65 + } 66 + 34 67 char _license[] SEC("license") = "GPL";