From: Zhang Xiaoxu <zhangxiao...@huawei.com> There is a UBSAN bug as blew: UBSAN: Undefined behaviour in kernel/bpf/core.c:1055:2 shift exponent 511 is too large for 32-bit type 'unsigned int'
Reproduce program: #include <errno.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <linux/audit.h> #include <linux/filter.h> #include <linux/seccomp.h> #include <sys/prctl.h> #include <sys/syscall.h> int main() { struct sock_filter sock_filter[3] = { BPF_JUMP(BPF_LDX|BPF_IMM, 0x1ff, 0x2, 0xfffffffffffffffd), BPF_JUMP(BPF_ALU|BPF_LSH|BPF_X, 0x0, 0x506, 0x401), BPF_JUMP(BPF_RET|BPF_K, 0x0, 0x0, SECCOMP_RET_KILL) }; struct sock_fprog sock_fprog= { .len = 3, .filter = &sock_filter, }; int ret = syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &sock_fprog); printf("%d\n", ret); return 0; } Make sure the right operand not greater than or equal to the width of the promoted left operand when do shift operation. Signed-off-by: ZhangXiaoxu <zhangxiao...@huawei.com> --- kernel/bpf/core.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 503d421..7635557 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -683,11 +683,26 @@ static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn) ALU(SUB, -) ALU(AND, &) ALU(OR, |) - ALU(LSH, <<) - ALU(RSH, >>) ALU(XOR, ^) ALU(MUL, *) #undef ALU +#define ALU_SHIFT(OPCODE, OP) \ + ALU64_##OPCODE##_X: \ + DST = DST OP (SRC & 0x3F); \ + CONT; \ + ALU_##OPCODE##_X: \ + DST = (u32) DST OP (SRC & 0x1F);\ + CONT; \ + ALU64_##OPCODE##_K: \ + DST = DST OP (IMM & 0x3F); \ + CONT; \ + ALU_##OPCODE##_K: \ + DST = (u32) DST OP (IMM & 0x1F);\ + CONT; + + ALU_SHIFT(LSH, <<) + ALU_SHIFT(RSH, >>) +#undef ALU_SHIFT ALU_NEG: DST = (u32) -DST; CONT; -- 2.7.4