UBSAN: shift-out-of-bounds in kernel/bpf/core.c:1414:2 shift exponent 248 is too large for 32-bit type 'unsigned int' Reported-and-tested-by: syzbot+bed360704c521841c85d@xxxxxxxxxxxxxxxxxxxxxxxxx Signed-off-by: Kurt Manucredo <fuzzybritches0@xxxxxxxxx> --- https://syzkaller.appspot.com/bug?id=edb51be4c9a320186328893287bb30d5eed09231 Changelog: ---------- v3 - Make it clearer what the fix is for. v2 - Fix shift-out-of-bounds in ___bpf_prog_run() by adding boundary check in check_alu_op() in verifier.c. v1 - Fix shift-out-of-bounds in ___bpf_prog_run() by adding boundary check in ___bpf_prog_run(). Hi everyone, I hope this fixes it! kind regards kernel/bpf/verifier.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 94ba5163d4c5..04e3bf344ecd 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -7880,13 +7880,25 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) return -EINVAL; } - if ((opcode == BPF_LSH || opcode == BPF_RSH || - opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) { + if (opcode == BPF_LSH || opcode == BPF_RSH || + opcode == BPF_ARSH) { int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32; - if (insn->imm < 0 || insn->imm >= size) { - verbose(env, "invalid shift %d\n", insn->imm); - return -EINVAL; + if (BPF_SRC(insn->code) == BPF_K) { + if (insn->imm < 0 || insn->imm >= size) { + verbose(env, "invalid shift %d\n", insn->imm); + return -EINVAL; + } + } + if (BPF_SRC(insn->code) == BPF_X) { + struct bpf_reg_state *src_reg; + + src_reg = ®s[insn->src_reg]; + if (src_reg->umax_value >= size) { + verbose(env, "invalid shift %lld\n", + src_reg->umax_value); + return -EINVAL; + } } } -- 2.30.2