Module Name: src Committed By: alnsn Date: Thu Feb 12 23:09:55 UTC 2015
Modified Files: src/sys/net: bpfjit.c Log Message: Fix bugs found by afl fuzzer http://lcamtuf.coredump.cx/afl/. To generate a diff of this commit: cvs rdiff -u -r1.38 -r1.39 src/sys/net/bpfjit.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/bpfjit.c diff -u src/sys/net/bpfjit.c:1.38 src/sys/net/bpfjit.c:1.39 --- src/sys/net/bpfjit.c:1.38 Thu Jan 15 16:31:05 2015 +++ src/sys/net/bpfjit.c Thu Feb 12 23:09:55 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: bpfjit.c,v 1.38 2015/01/15 16:31:05 christos Exp $ */ +/* $NetBSD: bpfjit.c,v 1.39 2015/02/12 23:09:55 alnsn Exp $ */ /*- * Copyright (c) 2011-2014 Alexander Nasonov. @@ -31,9 +31,9 @@ #include <sys/cdefs.h> #ifdef _KERNEL -__KERNEL_RCSID(0, "$NetBSD: bpfjit.c,v 1.38 2015/01/15 16:31:05 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bpfjit.c,v 1.39 2015/02/12 23:09:55 alnsn Exp $"); #else -__RCSID("$NetBSD: bpfjit.c,v 1.38 2015/01/15 16:31:05 christos Exp $"); +__RCSID("$NetBSD: bpfjit.c,v 1.39 2015/02/12 23:09:55 alnsn Exp $"); #endif #include <sys/types.h> @@ -290,15 +290,10 @@ read_width(const struct bpf_insn *pc) { switch (BPF_SIZE(pc->code)) { - case BPF_W: - return 4; - case BPF_H: - return 2; - case BPF_B: - return 1; - default: - BJ_ASSERT(false); - return 0; + case BPF_W: return 4; + case BPF_H: return 2; + case BPF_B: return 1; + default: return 0; } } @@ -839,6 +834,8 @@ emit_pkt_read(struct sljit_compiler *com ld_reg = BJ_BUF; width = read_width(pc); + if (width == 0) + return SLJIT_ERR_ALLOC_FAILED; if (BPF_MODE(pc->code) == BPF_IND) { /* tmp1 = buflen - (pc->k + width); */ @@ -1235,12 +1232,15 @@ read_pkt_insn(const struct bpf_insn *pc, case BPF_LD: rv = BPF_MODE(pc->code) == BPF_ABS || BPF_MODE(pc->code) == BPF_IND; - if (rv) + if (rv) { width = read_width(pc); + rv = (width != 0); + } break; case BPF_LDX: - rv = pc->code == (BPF_LDX|BPF_B|BPF_MSH); + rv = BPF_MODE(pc->code) == BPF_MSH && + BPF_SIZE(pc->code) == BPF_B; width = 1; break; } @@ -1412,6 +1412,9 @@ optimize_pass1(const bpf_ctx_t *bc, cons /* Initialize abc_length for ABC pass. */ insn_dat[i].u.jdata.abc_length = MAX_ABC_LENGTH; + if (BPF_SRC(insns[i].code) == BPF_X) + *hints |= BJ_HINT_XREG; + if (BPF_OP(insns[i].code) == BPF_JA) { jt = jf = insns[i].k; } else { @@ -1590,6 +1593,7 @@ optimize(const bpf_ctx_t *bc, const stru static int bpf_alu_to_sljit_op(const struct bpf_insn *pc) { + const int bad = SLJIT_UNUSED; /* * Note: all supported 64bit arches have 32bit multiply @@ -1602,11 +1606,10 @@ bpf_alu_to_sljit_op(const struct bpf_ins case BPF_OR: return SLJIT_OR; case BPF_XOR: return SLJIT_XOR; case BPF_AND: return SLJIT_AND; - case BPF_LSH: return SLJIT_SHL; - case BPF_RSH: return SLJIT_LSHR|SLJIT_INT_OP; + case BPF_LSH: return (pc->k > 31) ? bad : SLJIT_SHL; + case BPF_RSH: return (pc->k > 31) ? bad : SLJIT_LSHR|SLJIT_INT_OP; default: - BJ_ASSERT(false); - return 0; + return bad; } } @@ -1927,10 +1930,12 @@ generate_insn_code(struct sljit_compiler op = BPF_OP(pc->code); if (op != BPF_DIV && op != BPF_MOD) { + const int op2 = bpf_alu_to_sljit_op(pc); + + if (op2 == SLJIT_UNUSED) + goto fail; status = sljit_emit_op2(compiler, - bpf_alu_to_sljit_op(pc), - BJ_AREG, 0, - BJ_AREG, 0, + op2, BJ_AREG, 0, BJ_AREG, 0, kx_to_reg(pc), kx_to_reg_arg(pc)); if (status != SLJIT_SUCCESS) goto fail;