mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 08:33:17 +02:00
Merge branch 'range-tracking-for-bpf_neg'
Song Liu says: ==================== Add range tracking for BPF_NEG. Please see commit log of 1/2 for more details. --- Changes v3 => v4: 1. Fix selftest verifier_value_ptr_arith.c. (Eduard) v3: https://lore.kernel.org/bpf/20250624233328.313573-1-song@kernel.org/ Changes v2 => v3: 1. Minor changes in the selftests. (Eduard) v2: https://lore.kernel.org/bpf/20250624220038.656646-1-song@kernel.org/ Changes v1 => v2: 1. Split new selftests to a separate patch. (Eduard) 2. Reset reg id on BPF_NEG. (Eduard) 3. Use env->fake_reg instead of a bpf_reg_state on the stack. (Eduard) 4. Add __msg for passing selftests. v1: https://lore.kernel.org/bpf/20250624172320.2923031-1-song@kernel.org/ ==================== Link: https://patch.msgid.link/20250625164025.3310203-1-song@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
0967f5399b
|
|
@ -40,6 +40,8 @@ struct tnum tnum_arshift(struct tnum a, u8 min_shift, u8 insn_bitness);
|
|||
struct tnum tnum_add(struct tnum a, struct tnum b);
|
||||
/* Subtract two tnums, return @a - @b */
|
||||
struct tnum tnum_sub(struct tnum a, struct tnum b);
|
||||
/* Neg of a tnum, return 0 - @a */
|
||||
struct tnum tnum_neg(struct tnum a);
|
||||
/* Bitwise-AND, return @a & @b */
|
||||
struct tnum tnum_and(struct tnum a, struct tnum b);
|
||||
/* Bitwise-OR, return @a | @b */
|
||||
|
|
|
|||
|
|
@ -83,6 +83,11 @@ struct tnum tnum_sub(struct tnum a, struct tnum b)
|
|||
return TNUM(dv & ~mu, mu);
|
||||
}
|
||||
|
||||
struct tnum tnum_neg(struct tnum a)
|
||||
{
|
||||
return tnum_sub(TNUM(0, 0), a);
|
||||
}
|
||||
|
||||
struct tnum tnum_and(struct tnum a, struct tnum b)
|
||||
{
|
||||
u64 alpha, beta, v;
|
||||
|
|
|
|||
|
|
@ -15182,6 +15182,7 @@ static bool is_safe_to_compute_dst_reg_range(struct bpf_insn *insn,
|
|||
switch (BPF_OP(insn->code)) {
|
||||
case BPF_ADD:
|
||||
case BPF_SUB:
|
||||
case BPF_NEG:
|
||||
case BPF_AND:
|
||||
case BPF_XOR:
|
||||
case BPF_OR:
|
||||
|
|
@ -15250,6 +15251,13 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
|
|||
scalar_min_max_sub(dst_reg, &src_reg);
|
||||
dst_reg->var_off = tnum_sub(dst_reg->var_off, src_reg.var_off);
|
||||
break;
|
||||
case BPF_NEG:
|
||||
env->fake_reg[0] = *dst_reg;
|
||||
__mark_reg_known(dst_reg, 0);
|
||||
scalar32_min_max_sub(dst_reg, &env->fake_reg[0]);
|
||||
scalar_min_max_sub(dst_reg, &env->fake_reg[0]);
|
||||
dst_reg->var_off = tnum_neg(env->fake_reg[0].var_off);
|
||||
break;
|
||||
case BPF_MUL:
|
||||
dst_reg->var_off = tnum_mul(dst_reg->var_off, src_reg.var_off);
|
||||
scalar32_min_max_mul(dst_reg, &src_reg);
|
||||
|
|
@ -15473,7 +15481,14 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
|||
}
|
||||
|
||||
/* check dest operand */
|
||||
err = check_reg_arg(env, insn->dst_reg, DST_OP);
|
||||
if (opcode == BPF_NEG) {
|
||||
err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
|
||||
err = err ?: adjust_scalar_min_max_vals(env, insn,
|
||||
®s[insn->dst_reg],
|
||||
regs[insn->dst_reg]);
|
||||
} else {
|
||||
err = check_reg_arg(env, insn->dst_reg, DST_OP);
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
|
|||
|
|
@ -159,13 +159,16 @@ __failure_unpriv
|
|||
__naked void deducing_bounds_from_const_10(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
r6 = r1; \
|
||||
r0 = 0; \
|
||||
if r0 s<= 0 goto l0_%=; \
|
||||
l0_%=: /* Marks reg as unknown. */ \
|
||||
r0 = -r0; \
|
||||
r0 -= r1; \
|
||||
l0_%=: /* Marks r0 as unknown. */ \
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
r0 -= r6; \
|
||||
exit; \
|
||||
" ::: __clobber_all);
|
||||
" :
|
||||
: __imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
|
|
|||
|
|
@ -231,4 +231,74 @@ __naked void bpf_cond_op_not_r10(void)
|
|||
::: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("lsm.s/socket_connect")
|
||||
__success __log_level(2)
|
||||
__msg("0: (b7) r0 = 1 ; R0_w=1")
|
||||
__msg("1: (84) w0 = -w0 ; R0_w=0xffffffff")
|
||||
__msg("mark_precise: frame0: last_idx 2 first_idx 0 subseq_idx -1")
|
||||
__msg("mark_precise: frame0: regs=r0 stack= before 1: (84) w0 = -w0")
|
||||
__msg("mark_precise: frame0: regs=r0 stack= before 0: (b7) r0 = 1")
|
||||
__naked int bpf_neg_2(void)
|
||||
{
|
||||
/*
|
||||
* lsm.s/socket_connect requires a return value within [-4095, 0].
|
||||
* Returning -1 is allowed
|
||||
*/
|
||||
asm volatile (
|
||||
"r0 = 1;"
|
||||
"w0 = -w0;"
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("lsm.s/socket_connect")
|
||||
__failure __msg("At program exit the register R0 has")
|
||||
__naked int bpf_neg_3(void)
|
||||
{
|
||||
/*
|
||||
* lsm.s/socket_connect requires a return value within [-4095, 0].
|
||||
* Returning -10000 is not allowed.
|
||||
*/
|
||||
asm volatile (
|
||||
"r0 = 10000;"
|
||||
"w0 = -w0;"
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("lsm.s/socket_connect")
|
||||
__success __log_level(2)
|
||||
__msg("0: (b7) r0 = 1 ; R0_w=1")
|
||||
__msg("1: (87) r0 = -r0 ; R0_w=-1")
|
||||
__msg("mark_precise: frame0: last_idx 2 first_idx 0 subseq_idx -1")
|
||||
__msg("mark_precise: frame0: regs=r0 stack= before 1: (87) r0 = -r0")
|
||||
__msg("mark_precise: frame0: regs=r0 stack= before 0: (b7) r0 = 1")
|
||||
__naked int bpf_neg_4(void)
|
||||
{
|
||||
/*
|
||||
* lsm.s/socket_connect requires a return value within [-4095, 0].
|
||||
* Returning -1 is allowed
|
||||
*/
|
||||
asm volatile (
|
||||
"r0 = 1;"
|
||||
"r0 = -r0;"
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("lsm.s/socket_connect")
|
||||
__failure __msg("At program exit the register R0 has")
|
||||
__naked int bpf_neg_5(void)
|
||||
{
|
||||
/*
|
||||
* lsm.s/socket_connect requires a return value within [-4095, 0].
|
||||
* Returning -10000 is not allowed.
|
||||
*/
|
||||
asm volatile (
|
||||
"r0 = 10000;"
|
||||
"r0 = -r0;"
|
||||
"exit;"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
|
|
|||
|
|
@ -231,6 +231,10 @@ __retval(1)
|
|||
__naked void ptr_unknown_vs_unknown_lt(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
r8 = r1; \
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
r9 = r0; \
|
||||
r1 = r8; \
|
||||
r0 = *(u32*)(r1 + %[__sk_buff_len]); \
|
||||
r1 = 0; \
|
||||
*(u64*)(r10 - 8) = r1; \
|
||||
|
|
@ -245,11 +249,11 @@ l1_%=: call %[bpf_map_lookup_elem]; \
|
|||
r4 = *(u8*)(r0 + 0); \
|
||||
if r4 == 1 goto l3_%=; \
|
||||
r1 = 6; \
|
||||
r1 = -r1; \
|
||||
r1 = r9; \
|
||||
r1 &= 0x3; \
|
||||
goto l4_%=; \
|
||||
l3_%=: r1 = 6; \
|
||||
r1 = -r1; \
|
||||
r1 = r9; \
|
||||
r1 &= 0x7; \
|
||||
l4_%=: r1 += r0; \
|
||||
r0 = *(u8*)(r1 + 0); \
|
||||
|
|
@ -259,7 +263,8 @@ l2_%=: r0 = 1; \
|
|||
: __imm(bpf_map_lookup_elem),
|
||||
__imm_addr(map_array_48b),
|
||||
__imm_addr(map_hash_16b),
|
||||
__imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
|
||||
__imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)),
|
||||
__imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
|
|
@ -271,6 +276,10 @@ __retval(1)
|
|||
__naked void ptr_unknown_vs_unknown_gt(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
r8 = r1; \
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
r9 = r0; \
|
||||
r1 = r8; \
|
||||
r0 = *(u32*)(r1 + %[__sk_buff_len]); \
|
||||
r1 = 0; \
|
||||
*(u64*)(r10 - 8) = r1; \
|
||||
|
|
@ -285,11 +294,11 @@ l1_%=: call %[bpf_map_lookup_elem]; \
|
|||
r4 = *(u8*)(r0 + 0); \
|
||||
if r4 == 1 goto l3_%=; \
|
||||
r1 = 6; \
|
||||
r1 = -r1; \
|
||||
r1 = r9; \
|
||||
r1 &= 0x7; \
|
||||
goto l4_%=; \
|
||||
l3_%=: r1 = 6; \
|
||||
r1 = -r1; \
|
||||
r1 = r9; \
|
||||
r1 &= 0x3; \
|
||||
l4_%=: r1 += r0; \
|
||||
r0 = *(u8*)(r1 + 0); \
|
||||
|
|
@ -299,7 +308,8 @@ l2_%=: r0 = 1; \
|
|||
: __imm(bpf_map_lookup_elem),
|
||||
__imm_addr(map_array_48b),
|
||||
__imm_addr(map_hash_16b),
|
||||
__imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
|
||||
__imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)),
|
||||
__imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user