Subject: kern/3366: [dM] bpf doesn't check its filter enough
To: None <gnats-bugs@gnats.netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: netbsd-bugs
Date: 03/20/1997 10:43:32
>Number:         3366
>Category:       kern
>Synopsis:       [dM] bpf doesn't check its filter enough
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Mar 20 07:50:00 1997
>Last-Modified:
>Originator:     der Mouse
>Organization:
	Dis-
>Release:        1.2_BETA (code inspection implies -current broken too)
>Environment:
	Any (found on a SPARC IPC)
>Description:
	bpf tries to validate its filter when set; see bpf_validate().
	But it misses two possibilities: backward jumps (using
	BPF_JMP+BPF_JA with a negative k value) that target a valid
	code location, and JA with a positive k value that overflows
	when added to the jump-relative-to offset (which, given the way
	JA is implemented, will amount to the same thing on most
	machines).

	It's true that on most machines bpf is root-only, in which case
	this can be looked upon as a "don't do that, then" bug - but in
	that case, why does bpf_validate() exist at all?  Such filters
	are invalid and should be caught by bpf_validate().
>How-To-Repeat:
	Install the following filter.  Watch your machine lock up hard
	as soon as it receives a packet that makes it run the filter.

	struct bpf_insn code[] = { BPF_STMT(BPF_JMP+BPF_JA,-1),
				   BPF_STMT(BPF_RET+BPF_K,-1) };

	Install the following filter on a 32-bit machine.  Watch your
	machine misbehave (lock up, fall over, whatever, depending on
	what happens when "pc += pc->k" is executed) as soon as ditto.

	struct bpf_insn code[] = { BPF_STMT(BPF_JMP+BPF_JA,0x7fffffff),
				   BPF_STMT(BPF_RET+BPF_K,-1) };

	In both cases, note that the filter is invalid and should have
	been caught by bpf_validate() at BIOCSETF time.
>Fix:
	Here's a patch that looks reasonable to me.  I have not
	actually tried this patch yet; once I have, I will send an
	addendum to this PR.

--- /sources/latest-usr-src/sys/net/bpf_filter.c	Tue Feb 13 17:00:00 1996
+++ /usr/src/sys/net/bpf_filter.c	Thu Mar 20 10:01:18 1997
@@ -499,7 +499,9 @@
 			register int from = i + 1;
 
 			if (BPF_OP(p->code) == BPF_JA) {
-				if (from + p->k >= len)
+				if ((p->k < 0) ||
+				    (from + p->k >= len) ||
+				    (from + p->k < 0))
 					return 0;
 			}
 			else if (from + p->jt >= len || from + p->jf >= len)

					der Mouse

			       mouse@rodents.montreal.qc.ca
		     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B
>Audit-Trail:
>Unformatted: