Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions kernel/bpf/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1736,6 +1736,12 @@ bool bpf_opcode_in_insntable(u8 code)
}

#ifndef CONFIG_BPF_JIT_ALWAYS_ON
/* Safe absolute value for s32 to prevent undefined behavior for abs(S32_MIN) */
static inline u32 __safe_abs32(s32 x)
{
return x >= 0 ? (u32)x : -(u32)x;
}

/**
* ___bpf_prog_run - run eBPF program on a given context
* @regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers
Expand Down Expand Up @@ -1900,8 +1906,8 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
DST = do_div(AX, (u32) SRC);
break;
case 1:
AX = abs((s32)DST);
AX = do_div(AX, abs((s32)SRC));
AX = __safe_abs32((s32)DST);
AX = do_div(AX, __safe_abs32((s32)SRC));
if ((s32)DST < 0)
DST = (u32)-AX;
else
Expand All @@ -1928,8 +1934,8 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
DST = do_div(AX, (u32) IMM);
break;
case 1:
AX = abs((s32)DST);
AX = do_div(AX, abs((s32)IMM));
AX = __safe_abs32((s32)DST);
AX = do_div(AX, __safe_abs32((s32)IMM));
if ((s32)DST < 0)
DST = (u32)-AX;
else
Expand All @@ -1955,8 +1961,8 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
DST = (u32) AX;
break;
case 1:
AX = abs((s32)DST);
do_div(AX, abs((s32)SRC));
AX = __safe_abs32((s32)DST);
do_div(AX, __safe_abs32((s32)SRC));
if (((s32)DST < 0) == ((s32)SRC < 0))
DST = (u32)AX;
else
Expand All @@ -1982,8 +1988,8 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
DST = (u32) AX;
break;
case 1:
AX = abs((s32)DST);
do_div(AX, abs((s32)IMM));
AX = __safe_abs32((s32)DST);
do_div(AX, __safe_abs32((s32)IMM));
if (((s32)DST < 0) == ((s32)IMM < 0))
DST = (u32)AX;
else
Expand Down
58 changes: 58 additions & 0 deletions tools/testing/selftests/bpf/progs/verifier_sdiv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,64 @@ __naked void smod32_ri_divisor_neg_1(void)
: __clobber_all);
}

SEC("socket")
__description("SDIV32, INT_MIN divided by 2, imm")
__success __success_unpriv __retval(-1073741824)
__naked void sdiv32_int_min_div_2_imm(void)
{
asm volatile (" \
w0 = %[int_min]; \
w0 s/= 2; \
exit; \
" :
: __imm_const(int_min, INT_MIN)
: __clobber_all);
}

SEC("socket")
__description("SDIV32, INT_MIN divided by 2, reg")
__success __success_unpriv __retval(-1073741824)
__naked void sdiv32_int_min_div_2_reg(void)
{
asm volatile (" \
w0 = %[int_min]; \
w1 = 2; \
w0 s/= w1; \
exit; \
" :
: __imm_const(int_min, INT_MIN)
: __clobber_all);
}

SEC("socket")
__description("SMOD32, INT_MIN modulo 2, imm")
__success __success_unpriv __retval(0)
__naked void smod32_int_min_mod_2_imm(void)
{
asm volatile (" \
w0 = %[int_min]; \
w0 s%%= 2; \
exit; \
" :
: __imm_const(int_min, INT_MIN)
: __clobber_all);
}

SEC("socket")
__description("SMOD32, INT_MIN modulo -2, imm")
__success __success_unpriv __retval(0)
__naked void smod32_int_min_mod_neg2_imm(void)
{
asm volatile (" \
w0 = %[int_min]; \
w0 s%%= -2; \
exit; \
" :
: __imm_const(int_min, INT_MIN)
: __clobber_all);
}


#else

SEC("socket")
Expand Down
Loading