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

bpf: fix precision bit propagation for BPF_ST instructions

When backtracking instructions to propagate precision bit for registers
and stack slots, one class of instructions (BPF_ST) weren't handled
causing extra stack slots to be propagated into parent state. Parent
state might not have that much stack allocated, though, which causes
warning on invalid stack slot usage.

This patch adds handling of BPF_ST instructions:

BPF_MEM | <size> | BPF_ST: *(size *) (dst_reg + off) = imm32

Reported-by: syzbot+4da3ff23081bafe74fc2@syzkaller.appspotmail.com
Fixes: b5dc0163d8fd ("bpf: precise scalar_value tracking")
Cc: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

authored by

Andrii Nakryiko and committed by
Daniel Borkmann
b3b50f05 327835fb

+4 -7
+4 -7
kernel/bpf/verifier.c
··· 1519 1519 return -EFAULT; 1520 1520 } 1521 1521 *stack_mask |= 1ull << spi; 1522 - } else if (class == BPF_STX) { 1522 + } else if (class == BPF_STX || class == BPF_ST) { 1523 1523 if (*reg_mask & dreg) 1524 - /* stx shouldn't be using _scalar_ dst_reg 1524 + /* stx & st shouldn't be using _scalar_ dst_reg 1525 1525 * to access memory. It means backtracking 1526 1526 * encountered a case of pointer subtraction. 1527 1527 */ ··· 1540 1540 if (!(*stack_mask & (1ull << spi))) 1541 1541 return 0; 1542 1542 *stack_mask &= ~(1ull << spi); 1543 - *reg_mask |= sreg; 1543 + if (class == BPF_STX) 1544 + *reg_mask |= sreg; 1544 1545 } else if (class == BPF_JMP || class == BPF_JMP32) { 1545 1546 if (opcode == BPF_CALL) { 1546 1547 if (insn->src_reg == BPF_PSEUDO_CALL) ··· 1569 1568 */ 1570 1569 if (mode == BPF_IND || mode == BPF_ABS) 1571 1570 /* to be analyzed */ 1572 - return -ENOTSUPP; 1573 - } else if (class == BPF_ST) { 1574 - if (*reg_mask & dreg) 1575 - /* likely pointer subtraction */ 1576 1571 return -ENOTSUPP; 1577 1572 } 1578 1573 return 0;