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;

Reply via email to