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: