Page MenuHomeFreeBSD

D37563.id.diff
No OneTemporary

D37563.id.diff

diff --git a/share/man/man9/bpf.9 b/share/man/man9/bpf.9
--- a/share/man/man9/bpf.9
+++ b/share/man/man9/bpf.9
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 11, 2012
+.Dd December 10, 2022
.Dt BPF 9
.Os
.\"
@@ -51,7 +51,11 @@
.Fn bpf_mtap2 "struct bpf_if *bp" "void *data" "u_int dlen" "struct mbuf *m"
.Ft u_int
.Fo bpf_filter
-.Fa "const struct bpf_insn *pc " "u_char *pkt" "u_int wirelen" "u_int buflen"
+.Fa "const struct bpf_insn *pc" "const u_char *pkt" "u_int wirelen" "u_int buflen"
+.Fc
+.Ft u_int
+.Fo bpf_mfilter
+.Fa "const struct bpf_insn *pc" "const struct mbuf *m" "u_int wirelen"
.Fc
.Ft int
.Fn bpf_validate "const struct bpf_insn *fcode" "int flen"
@@ -217,12 +221,19 @@
is the length of the original packet and
.Fa buflen
is the amount of data present.
+.Pp
The
-.Fa buflen
-value of 0 is special; it indicates that the
-.Fa pkt
-is actually a pointer to an mbuf chain
-.Pq Vt "struct mbuf *" .
+.Fn bpf_mfilter
+function
+executes the filter program starting at
+.Fa pc
+against the packet in an mbuf chain
+.Pq Vt "struct mbuf *"
+.Fa m .
+The
+.Fa wirelen
+argument
+is the length of the original packet.
.Pp
The
.Fn bpf_validate
@@ -236,7 +247,9 @@
.Sh RETURN VALUES
The
.Fn bpf_filter
-function returns \-1
+and
+.Fn bpf_mfilter
+functions return \-1
(cast to an unsigned integer)
if there is no filter.
Otherwise, it returns the result of the filter program.
diff --git a/sys/net/bpf.h b/sys/net/bpf.h
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -368,12 +368,28 @@
bpf_u_int32 k;
};
+/*
+ * Load operations for _bpf_filter to use against the packet pointer.
+ */
+struct bpf_ops {
+ u_int32_t (*ldw)(const void *, u_int32_t, int *);
+ u_int32_t (*ldh)(const void *, u_int32_t, int *);
+ u_int32_t (*ldb)(const void *, u_int32_t, int *);
+};
+
/*
* Macros for insn array initializers.
*/
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+__BEGIN_DECLS
+u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+u_int _bpf_filter(const struct bpf_insn *, const struct bpf_ops *,
+ const void *, u_int);
+int bpf_validate(const struct bpf_insn *, int);
+__END_DECLS
+
/*
* Structure to retrieve available DLTs for the interface.
*/
@@ -405,6 +421,9 @@
bpf_bufheld(d); \
} while (0)
+struct ifnet;
+struct mbuf;
+
/*
* Descriptor associated with each attached hardware interface.
* Part of this structure is exposed to external callers to speed up
@@ -419,7 +438,6 @@
};
void bpf_bufheld(struct bpf_d *d);
-int bpf_validate(const struct bpf_insn *, int);
void bpf_tap(struct bpf_if *, u_char *, u_int);
void bpf_mtap(struct bpf_if *, struct mbuf *);
void bpf_mtap2(struct bpf_if *, void *, u_int, struct mbuf *);
@@ -431,7 +449,7 @@
#endif
void bpfilterattach(int);
-u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int);
+u_int bpf_mfilter(const struct bpf_insn *, const struct mbuf *, u_int);
static __inline int
bpf_peers_present(struct bpf_if *bpf)
@@ -460,7 +478,7 @@
bpf_mtap2((_ifp)->if_bpf,(_data),(_dlen),(_m)); \
} \
} while (0)
-#endif
+#endif /* _KERNEL */
/*
* Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -2390,7 +2390,7 @@
pktlen);
else
#endif
- slen = bpf_filter(d->bd_rfilter, (u_char *)m, pktlen, 0);
+ slen = bpf_mfilter(d->bd_rfilter, m, pktlen);
if (slen != 0) {
BPFD_LOCK(d);
@@ -2447,7 +2447,7 @@
if (BPF_CHECK_DIRECTION(d, m->m_pkthdr.rcvif, bp->bif_ifp))
continue;
counter_u64_add(d->bd_rcount, 1);
- slen = bpf_filter(d->bd_rfilter, (u_char *)&mb, pktlen, 0);
+ slen = bpf_mfilter(d->bd_rfilter, &mb, pktlen);
if (slen != 0) {
BPFD_LOCK(d);
@@ -3078,6 +3078,107 @@
return (error);
}
+static u_int32_t bpf_mbuf_ldw(const void *, u_int32_t, int *);
+static u_int32_t bpf_mbuf_ldh(const void *, u_int32_t, int *);
+static u_int32_t bpf_mbuf_ldb(const void *, u_int32_t, int *);
+
+static int bpf_mbuf_copy(const struct mbuf *, u_int32_t, void *, u_int32_t);
+
+static const struct bpf_ops bpf_mbuf_ops = {
+ bpf_mbuf_ldw,
+ bpf_mbuf_ldh,
+ bpf_mbuf_ldb,
+};
+
+static int
+bpf_mbuf_copy(const struct mbuf *m, u_int32_t off, void *buf, u_int32_t len)
+{
+ u_int8_t *cp = buf;
+ u_int32_t count;
+
+ while (off >= m->m_len) {
+ off -= m->m_len;
+
+ m = m->m_next;
+ if (m == NULL)
+ return (-1);
+ }
+
+ for (;;) {
+ count = min(m->m_len - off, len);
+
+ memcpy(cp, m->m_data + off, count);
+ len -= count;
+
+ if (len == 0)
+ return (0);
+
+ m = m->m_next;
+ if (m == NULL)
+ break;
+
+ cp += count;
+ off = 0;
+ }
+
+ return (-1);
+}
+
+static u_int32_t
+bpf_mbuf_ldw(const void *m0, u_int32_t k, int *err)
+{
+ u_int32_t v;
+
+ if (bpf_mbuf_copy(m0, k, &v, sizeof(v)) != 0) {
+ *err = 1;
+ return (0);
+ }
+
+ *err = 0;
+ return ntohl(v);
+}
+
+static u_int32_t
+bpf_mbuf_ldh(const void *m0, u_int32_t k, int *err)
+{
+ u_int16_t v;
+
+ if (bpf_mbuf_copy(m0, k, &v, sizeof(v)) != 0) {
+ *err = 1;
+ return (0);
+ }
+
+ *err = 0;
+ return ntohs(v);
+}
+
+static u_int32_t
+bpf_mbuf_ldb(const void *m0, u_int32_t k, int *err)
+{
+ const struct mbuf *m = m0;
+ u_int8_t v;
+
+ while (k >= m->m_len) {
+ k -= m->m_len;
+
+ m = m->m_next;
+ if (m == NULL) {
+ *err = 1;
+ return (0);
+ }
+ }
+ v = m->m_data[k];
+
+ *err = 0;
+ return v;
+}
+
+u_int
+bpf_mfilter(const struct bpf_insn *pc, const struct mbuf *m, u_int wirelen)
+{
+ return _bpf_filter(pc, &bpf_mbuf_ops, m, wirelen);
+}
+
SYSINIT(bpfdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,bpf_drvinit,NULL);
#else /* !DEV_BPF && !NETGRAPH_BPF */
@@ -3124,7 +3225,13 @@
}
u_int
-bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen)
+bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, u_int buflen)
+{
+ return -1; /* "no filter" behaviour */
+}
+
+u_int
+bpf_mfilter(const struct bpf_insn *pc, const struct mbuf *m, u_int wirelen)
{
return -1; /* "no filter" behaviour */
}
diff --git a/sys/net/bpf_buffer.c b/sys/net/bpf_buffer.c
--- a/sys/net/bpf_buffer.c
+++ b/sys/net/bpf_buffer.c
@@ -93,7 +93,7 @@
static int bpf_bufsize = 4096;
SYSCTL_INT(_net_bpf, OID_AUTO, bufsize, CTLFLAG_RW,
&bpf_bufsize, 0, "Default capture buffer size in bytes");
-static int bpf_maxbufsize = BPF_MAXBUFSIZE;
+int bpf_maxbufsize = BPF_MAXBUFSIZE;
SYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,
&bpf_maxbufsize, 0, "Maximum capture buffer in bytes");
diff --git a/sys/net/bpf_filter.c b/sys/net/bpf_filter.c
--- a/sys/net/bpf_filter.c
+++ b/sys/net/bpf_filter.c
@@ -40,135 +40,89 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/systm.h>
#if !defined(_KERNEL)
-#include <strings.h>
+#include <string.h>
#endif
#if !defined(_KERNEL) || defined(sun)
#include <netinet/in.h>
#endif
-#ifndef __i386__
-#define BPF_ALIGN
-#endif
-
-#ifndef BPF_ALIGN
-#define EXTRACT_SHORT(p) ((u_int16_t)ntohs(*(u_int16_t *)p))
-#define EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p))
-#else
-#define EXTRACT_SHORT(p)\
- ((u_int16_t)\
- ((u_int16_t)*((u_char *)p+0)<<8|\
- (u_int16_t)*((u_char *)p+1)<<0))
-#define EXTRACT_LONG(p)\
- ((u_int32_t)*((u_char *)p+0)<<24|\
- (u_int32_t)*((u_char *)p+1)<<16|\
- (u_int32_t)*((u_char *)p+2)<<8|\
- (u_int32_t)*((u_char *)p+3)<<0)
-#endif
+#include <sys/endian.h>
#ifdef _KERNEL
#include <sys/mbuf.h>
+extern int bpf_maxbufsize;
#else
#include <stdlib.h>
-#endif
+#define bpf_maxbufsize BPF_MAXBUFSIZE
+#endif /* _KERNEL */
+
#include <net/bpf.h>
-#ifdef _KERNEL
-#define MINDEX(m, k) \
-{ \
- int len = m->m_len; \
- \
- while (k >= len) { \
- k -= len; \
- m = m->m_next; \
- if (m == 0) \
- return (0); \
- len = m->m_len; \
- } \
-}
-static u_int16_t m_xhalf(struct mbuf *m, bpf_u_int32 k, int *err);
-static u_int32_t m_xword(struct mbuf *m, bpf_u_int32 k, int *err);
+struct bpf_mem {
+ const u_char *pkt;
+ u_int len;
+};
+
+static u_int32_t bpf_mem_ldw(const void *, u_int32_t, int *);
+static u_int32_t bpf_mem_ldh(const void *, u_int32_t, int *);
+static u_int32_t bpf_mem_ldb(const void *, u_int32_t, int *);
+
+static const struct bpf_ops bpf_mem_ops = {
+ bpf_mem_ldw,
+ bpf_mem_ldh,
+ bpf_mem_ldb,
+};
static u_int32_t
-m_xword(struct mbuf *m, bpf_u_int32 k, int *err)
+bpf_mem_ldw(const void *mem, u_int32_t k, int *err)
{
- size_t len;
- u_char *cp, *np;
- struct mbuf *m0;
-
- len = m->m_len;
- while (k >= len) {
- k -= len;
- m = m->m_next;
- if (m == NULL)
- goto bad;
- len = m->m_len;
- }
- cp = mtod(m, u_char *) + k;
- if (len - k >= 4) {
- *err = 0;
- return (EXTRACT_LONG(cp));
- }
- m0 = m->m_next;
- if (m0 == NULL || m0->m_len + len - k < 4)
- goto bad;
- *err = 0;
- np = mtod(m0, u_char *);
- switch (len - k) {
- case 1:
- return (((u_int32_t)cp[0] << 24) |
- ((u_int32_t)np[0] << 16) |
- ((u_int32_t)np[1] << 8) |
- (u_int32_t)np[2]);
-
- case 2:
- return (((u_int32_t)cp[0] << 24) |
- ((u_int32_t)cp[1] << 16) |
- ((u_int32_t)np[0] << 8) |
- (u_int32_t)np[1]);
-
- default:
- return (((u_int32_t)cp[0] << 24) |
- ((u_int32_t)cp[1] << 16) |
- ((u_int32_t)cp[2] << 8) |
- (u_int32_t)np[0]);
- }
- bad:
+ const struct bpf_mem *bm = mem;
+ u_int32_t v;
+
*err = 1;
- return (0);
+
+ if (k > bm->len || sizeof(v) > bm->len - k)
+ return (0);
+
+ memcpy(&v, bm->pkt + k, sizeof(v));
+
+ *err = 0;
+ return ntohl(v);
}
-static u_int16_t
-m_xhalf(struct mbuf *m, bpf_u_int32 k, int *err)
+static u_int32_t
+bpf_mem_ldh(const void *mem, u_int32_t k, int *err)
{
- size_t len;
- u_char *cp;
- struct mbuf *m0;
-
- len = m->m_len;
- while (k >= len) {
- k -= len;
- m = m->m_next;
- if (m == NULL)
- goto bad;
- len = m->m_len;
- }
- cp = mtod(m, u_char *) + k;
- if (len - k >= 2) {
- *err = 0;
- return (EXTRACT_SHORT(cp));
- }
- m0 = m->m_next;
- if (m0 == NULL)
- goto bad;
+ const struct bpf_mem *bm = mem;
+ u_int16_t v;
+
+ *err = 1;
+
+ if (k > bm->len || sizeof(v) > bm->len - k)
+ return (0);
+
+ memcpy(&v, bm->pkt + k, sizeof(v));
+
*err = 0;
- return ((cp[0] << 8) | mtod(m0, u_char *)[0]);
- bad:
+ return ntohs(v);
+}
+
+static u_int32_t
+bpf_mem_ldb(const void *mem, u_int32_t k, int *err)
+{
+ const struct bpf_mem *bm = mem;
+
*err = 1;
- return (0);
+
+ if (k >= bm->len)
+ return (0);
+
+ *err = 0;
+ return bm->pkt[k];
}
-#endif
/*
* Execute the filter program starting at pc on the packet p
@@ -176,31 +130,46 @@
* buflen is the amount of data present
*/
u_int
-bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen)
+bpf_filter(const struct bpf_insn *pc, const u_char *pkt,
+ u_int wirelen, u_int buflen)
{
- u_int32_t A = 0, X = 0;
- bpf_u_int32 k;
- u_int32_t mem[BPF_MEMWORDS];
+ struct bpf_mem bm;
- bzero(mem, sizeof(mem));
+ bm.pkt = pkt;
+ bm.len = buflen;
- if (pc == NULL)
+ return _bpf_filter(pc, &bpf_mem_ops, &bm, wirelen);
+}
+
+u_int
+_bpf_filter(const struct bpf_insn *pc, const struct bpf_ops *ops,
+ const void *pkt, u_int wirelen)
+{
+ u_int32_t A = 0, X = 0;
+ u_int32_t k;
+ int32_t mem[BPF_MEMWORDS];
+ int err;
+
+ if (pc == NULL) {
/*
* No filter means accept all.
*/
- return ((u_int)-1);
+ return (u_int)-1;
+ }
+
+ memset(mem, 0, sizeof(mem));
--pc;
while (1) {
++pc;
switch (pc->code) {
+
default:
#ifdef _KERNEL
return (0);
#else
abort();
#endif
-
case BPF_RET|BPF_K:
return ((u_int)pc->k);
@@ -208,63 +177,21 @@
return ((u_int)A);
case BPF_LD|BPF_W|BPF_ABS:
- k = pc->k;
- if (k > buflen || sizeof(int32_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xword((struct mbuf *)p, k, &merr);
- if (merr != 0)
- return (0);
- continue;
-#else
+ A = ops->ldw(pkt, pc->k, &err);
+ if (err != 0)
return (0);
-#endif
- }
-#ifdef BPF_ALIGN
- if (((intptr_t)(p + k) & 3) != 0)
- A = EXTRACT_LONG(&p[k]);
- else
-#endif
- A = ntohl(*(int32_t *)(p + k));
continue;
case BPF_LD|BPF_H|BPF_ABS:
- k = pc->k;
- if (k > buflen || sizeof(int16_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xhalf((struct mbuf *)p, k, &merr);
- continue;
-#else
+ A = ops->ldh(pkt, pc->k, &err);
+ if (err != 0)
return (0);
-#endif
- }
- A = EXTRACT_SHORT(&p[k]);
continue;
case BPF_LD|BPF_B|BPF_ABS:
- k = pc->k;
- if (k >= buflen) {
-#ifdef _KERNEL
- struct mbuf *m;
-
- if (buflen != 0)
- return (0);
- m = (struct mbuf *)p;
- MINDEX(m, k);
- A = mtod(m, u_char *)[k];
- continue;
-#else
+ A = ops->ldb(pkt, pc->k, &err);
+ if (err != 0)
return (0);
-#endif
- }
- A = p[k];
continue;
case BPF_LD|BPF_W|BPF_LEN:
@@ -277,85 +204,37 @@
case BPF_LD|BPF_W|BPF_IND:
k = X + pc->k;
- if (pc->k > buflen || X > buflen - pc->k ||
- sizeof(int32_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xword((struct mbuf *)p, k, &merr);
- if (merr != 0)
- return (0);
- continue;
-#else
+ if (k < pc->k)
+ return (0);
+ A = ops->ldw(pkt, k, &err);
+ if (err != 0)
return (0);
-#endif
- }
-#ifdef BPF_ALIGN
- if (((intptr_t)(p + k) & 3) != 0)
- A = EXTRACT_LONG(&p[k]);
- else
-#endif
- A = ntohl(*(int32_t *)(p + k));
continue;
case BPF_LD|BPF_H|BPF_IND:
k = X + pc->k;
- if (X > buflen || pc->k > buflen - X ||
- sizeof(int16_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xhalf((struct mbuf *)p, k, &merr);
- if (merr != 0)
- return (0);
- continue;
-#else
+ if (k < pc->k)
return (0);
-#endif
- }
- A = EXTRACT_SHORT(&p[k]);
+ A = ops->ldh(pkt, k, &err);
+ if (err != 0)
+ return 0;
continue;
case BPF_LD|BPF_B|BPF_IND:
k = X + pc->k;
- if (pc->k >= buflen || X >= buflen - pc->k) {
-#ifdef _KERNEL
- struct mbuf *m;
-
- if (buflen != 0)
- return (0);
- m = (struct mbuf *)p;
- MINDEX(m, k);
- A = mtod(m, u_char *)[k];
- continue;
-#else
+ if (k < pc->k)
return (0);
-#endif
- }
- A = p[k];
+ A = ops->ldb(pkt, k, &err);
+ if (err != 0)
+ return 0;
continue;
case BPF_LDX|BPF_MSH|BPF_B:
- k = pc->k;
- if (k >= buflen) {
-#ifdef _KERNEL
- struct mbuf *m;
-
- if (buflen != 0)
- return (0);
- m = (struct mbuf *)p;
- MINDEX(m, k);
- X = (mtod(m, u_char *)[k] & 0xf) << 2;
- continue;
-#else
- return (0);
-#endif
- }
- X = (p[pc->k] & 0xf) << 2;
+ X = ops->ldb(pkt, pc->k, &err);
+ if (err != 0)
+ return 0;
+ X &= 0xf;
+ X <<= 2;
continue;
case BPF_LD|BPF_IMM:
@@ -517,33 +396,11 @@
}
}
-#ifdef _KERNEL
-static const u_short bpf_code_map[] = {
- 0x10ff, /* 0x00-0x0f: 1111111100001000 */
- 0x3070, /* 0x10-0x1f: 0000111000001100 */
- 0x3131, /* 0x20-0x2f: 1000110010001100 */
- 0x3031, /* 0x30-0x3f: 1000110000001100 */
- 0x3131, /* 0x40-0x4f: 1000110010001100 */
- 0x1011, /* 0x50-0x5f: 1000100000001000 */
- 0x1013, /* 0x60-0x6f: 1100100000001000 */
- 0x1010, /* 0x70-0x7f: 0000100000001000 */
- 0x0093, /* 0x80-0x8f: 1100100100000000 */
- 0x1010, /* 0x90-0x9f: 0000100000001000 */
- 0x1010, /* 0xa0-0xaf: 0000100000001000 */
- 0x0002, /* 0xb0-0xbf: 0100000000000000 */
- 0x0000, /* 0xc0-0xcf: 0000000000000000 */
- 0x0000, /* 0xd0-0xdf: 0000000000000000 */
- 0x0000, /* 0xe0-0xef: 0000000000000000 */
- 0x0000 /* 0xf0-0xff: 0000000000000000 */
-};
-
-#define BPF_VALIDATE_CODE(c) \
- ((c) <= 0xff && (bpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0)
-
/*
* Return true if the 'fcode' is a valid filter program.
* The constraints are that each jump be forward and to a valid
- * code. The code must terminate with either an accept or reject.
+ * code and memory operations use valid addresses. The code
+ * must terminate with either an accept or reject.
*
* The kernel needs to be able to verify an application's filter code.
* Otherwise, a bogus program could easily crash the system.
@@ -551,7 +408,7 @@
int
bpf_validate(const struct bpf_insn *f, int len)
{
- int i;
+ u_int i, from;
const struct bpf_insn *p;
/* Do not accept negative length filter. */
@@ -564,43 +421,94 @@
for (i = 0; i < len; ++i) {
p = &f[i];
- /*
- * Check that the code is valid.
- */
- if (!BPF_VALIDATE_CODE(p->code))
- return (0);
- /*
- * Check that the jumps are forward, and within
- * the code block.
- */
- if (BPF_CLASS(p->code) == BPF_JMP) {
- u_int offset;
-
- if (p->code == (BPF_JMP|BPF_JA))
- offset = p->k;
- else
- offset = p->jt > p->jf ? p->jt : p->jf;
- if (offset >= (u_int)(len - i) - 1)
- return (0);
- continue;
- }
+ switch (BPF_CLASS(p->code)) {
/*
* Check that memory operations use valid addresses.
*/
- if (p->code == BPF_ST || p->code == BPF_STX ||
- p->code == (BPF_LD|BPF_MEM) ||
- p->code == (BPF_LDX|BPF_MEM)) {
+ case BPF_LD:
+ case BPF_LDX:
+ switch (BPF_MODE(p->code)) {
+ case BPF_IMM:
+ break;
+ case BPF_ABS:
+ case BPF_IND:
+ case BPF_MSH:
+ /*
+ * More strict check with actual packet length
+ * is done runtime.
+ */
+ if (p->k >= bpf_maxbufsize)
+ return (0);
+ break;
+ case BPF_MEM:
+ if (p->k >= BPF_MEMWORDS)
+ return (0);
+ break;
+ case BPF_LEN:
+ break;
+ default:
+ return (0);
+ }
+ break;
+ case BPF_ST:
+ case BPF_STX:
if (p->k >= BPF_MEMWORDS)
return (0);
- continue;
- }
- /*
- * Check for constant division by 0.
- */
- if ((p->code == (BPF_ALU|BPF_DIV|BPF_K) ||
- p->code == (BPF_ALU|BPF_MOD|BPF_K)) && p->k == 0)
+ break;
+ case BPF_ALU:
+ switch (BPF_OP(p->code)) {
+ case BPF_ADD:
+ case BPF_SUB:
+ case BPF_MUL:
+ case BPF_OR:
+ case BPF_AND:
+ case BPF_LSH:
+ case BPF_RSH:
+ case BPF_NEG:
+ case BPF_XOR:
+ break;
+ case BPF_DIV:
+ case BPF_MOD:
+ /*
+ * Check for constant division by 0.
+ */
+ if (BPF_SRC(p->code) == BPF_K && p->k == 0)
+ return (0);
+ break;
+ default:
+ return (0);
+ }
+ break;
+ case BPF_JMP:
+ /*
+ * Check that jumps are forward, and within
+ * the code block.
+ */
+ from = i + 1;
+ switch (BPF_OP(p->code)) {
+ case BPF_JA:
+ if (from + p->k < from || from + p->k >= len)
+ return (0);
+ break;
+ case BPF_JEQ:
+ case BPF_JGT:
+ case BPF_JGE:
+ case BPF_JSET:
+ if (from + p->jt >= len || from + p->jf >= len)
+ return (0);
+ break;
+ default:
+ return (0);
+ }
+ break;
+ case BPF_RET:
+ break;
+ case BPF_MISC:
+ break;
+ default:
return (0);
+ }
+
}
return (BPF_CLASS(f[len - 1].code) == BPF_RET);
}
-#endif
diff --git a/sys/netgraph/ng_bpf.c b/sys/netgraph/ng_bpf.c
--- a/sys/netgraph/ng_bpf.c
+++ b/sys/netgraph/ng_bpf.c
@@ -472,7 +472,7 @@
if (data)
len = bpf_filter(hip->prog->bpf_prog, data, totlen, totlen);
else
- len = bpf_filter(hip->prog->bpf_prog, (u_char *)m, totlen, 0);
+ len = bpf_mfilter(hip->prog->bpf_prog, m, totlen);
if (needfree)
free(data, M_NETGRAPH_BPF);
ready:
diff --git a/sys/netpfil/ipfilter/netinet/fil.c b/sys/netpfil/ipfilter/netinet/fil.c
--- a/sys/netpfil/ipfilter/netinet/fil.c
+++ b/sys/netpfil/ipfilter/netinet/fil.c
@@ -2411,16 +2411,14 @@
case FR_T_BPFOPC :
case FR_T_BPFOPC_BUILTIN :
{
- u_char *mc;
int wlen;
if (*fin->fin_mp == NULL)
continue;
if (fin->fin_family != fr->fr_family)
continue;
- mc = (u_char *)fin->fin_m;
wlen = fin->fin_dlen + fin->fin_hlen;
- if (!bpf_filter(fr->fr_data, mc, wlen, 0))
+ if (!bpf_mfilter(fr->fr_data, fin->fin_m, wlen))
continue;
break;
}
diff --git a/tools/regression/bpf/bpf_filter/bpf_test.c b/tools/regression/bpf/bpf_filter/bpf_test.c
--- a/tools/regression/bpf/bpf_filter/bpf_test.c
+++ b/tools/regression/bpf/bpf_filter/bpf_test.c
@@ -90,100 +90,10 @@
#else
-u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int);
+u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
#endif
-#ifdef BPF_VALIDATE
-static const u_short bpf_code_map[] = {
- 0x10ff, /* 0x00-0x0f: 1111111100001000 */
- 0x3070, /* 0x10-0x1f: 0000111000001100 */
- 0x3131, /* 0x20-0x2f: 1000110010001100 */
- 0x3031, /* 0x30-0x3f: 1000110000001100 */
- 0x3131, /* 0x40-0x4f: 1000110010001100 */
- 0x1011, /* 0x50-0x5f: 1000100000001000 */
- 0x1013, /* 0x60-0x6f: 1100100000001000 */
- 0x1010, /* 0x70-0x7f: 0000100000001000 */
- 0x0093, /* 0x80-0x8f: 1100100100000000 */
- 0x1010, /* 0x90-0x9f: 0000100000001000 */
- 0x1010, /* 0xa0-0xaf: 0000100000001000 */
- 0x0002, /* 0xb0-0xbf: 0100000000000000 */
- 0x0000, /* 0xc0-0xcf: 0000000000000000 */
- 0x0000, /* 0xd0-0xdf: 0000000000000000 */
- 0x0000, /* 0xe0-0xef: 0000000000000000 */
- 0x0000 /* 0xf0-0xff: 0000000000000000 */
-};
-
-#define BPF_VALIDATE_CODE(c) \
- ((c) <= 0xff && (bpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0)
-
-/*
- * XXX Copied from sys/net/bpf_filter.c and modified.
- *
- * Return true if the 'fcode' is a valid filter program.
- * The constraints are that each jump be forward and to a valid
- * code. The code must terminate with either an accept or reject.
- *
- * The kernel needs to be able to verify an application's filter code.
- * Otherwise, a bogus program could easily crash the system.
- */
-static int
-bpf_validate(const struct bpf_insn *f, int len)
-{
- register int i;
- register const struct bpf_insn *p;
-
- /* Do not accept negative length filter. */
- if (len < 0)
- return (0);
-
- /* An empty filter means accept all. */
- if (len == 0)
- return (1);
-
- for (i = 0; i < len; ++i) {
- p = &f[i];
- /*
- * Check that the code is valid.
- */
- if (!BPF_VALIDATE_CODE(p->code))
- return (0);
- /*
- * Check that jumps are forward, and within
- * the code block.
- */
- if (BPF_CLASS(p->code) == BPF_JMP) {
- register u_int offset;
-
- if (p->code == (BPF_JMP|BPF_JA))
- offset = p->k;
- else
- offset = p->jt > p->jf ? p->jt : p->jf;
- if (offset >= (u_int)(len - i) - 1)
- return (0);
- continue;
- }
- /*
- * Check that memory operations use valid addresses.
- */
- if (p->code == BPF_ST || p->code == BPF_STX ||
- p->code == (BPF_LD|BPF_MEM) ||
- p->code == (BPF_LDX|BPF_MEM)) {
- if (p->k >= BPF_MEMWORDS)
- return (0);
- continue;
- }
- /*
- * Check for constant division by 0.
- */
- if ((p->code == (BPF_ALU|BPF_DIV|BPF_K) ||
- p->code == (BPF_ALU|BPF_MOD|BPF_K)) && p->k == 0)
- return (0);
- }
- return (BPF_CLASS(f[len - 1].code) == BPF_RET);
-}
-#endif
-
int
main(void)
{
diff --git a/tools/regression/bpf/bpf_filter/tests/test0056.h b/tools/regression/bpf/bpf_filter/tests/test0056.h
--- a/tools/regression/bpf/bpf_filter/tests/test0056.h
+++ b/tools/regression/bpf/bpf_filter/tests/test0056.h
@@ -24,7 +24,7 @@
static u_int buflen = sizeof(pkt);
/* Invalid instruction */
-static int invalid = 0;
+static int invalid = 1;
/* Expected return value */
static u_int expect = 0;
diff --git a/tools/regression/bpf/bpf_filter/tests/test0057.h b/tools/regression/bpf/bpf_filter/tests/test0057.h
--- a/tools/regression/bpf/bpf_filter/tests/test0057.h
+++ b/tools/regression/bpf/bpf_filter/tests/test0057.h
@@ -24,7 +24,7 @@
static u_int buflen = sizeof(pkt);
/* Invalid instruction */
-static int invalid = 0;
+static int invalid = 1;
/* Expected return value */
static u_int expect = 0;
diff --git a/tools/regression/bpf/bpf_filter/tests/test0058.h b/tools/regression/bpf/bpf_filter/tests/test0058.h
--- a/tools/regression/bpf/bpf_filter/tests/test0058.h
+++ b/tools/regression/bpf/bpf_filter/tests/test0058.h
@@ -24,7 +24,7 @@
static u_int buflen = sizeof(pkt);
/* Invalid instruction */
-static int invalid = 0;
+static int invalid = 1;
/* Expected return value */
static u_int expect = 0;
diff --git a/tools/regression/bpf/bpf_filter/tests/test0075.h b/tools/regression/bpf/bpf_filter/tests/test0075.h
--- a/tools/regression/bpf/bpf_filter/tests/test0075.h
+++ b/tools/regression/bpf/bpf_filter/tests/test0075.h
@@ -29,8 +29,4 @@
static u_int expect = 0xdeadc0de;
/* Expected signal */
-#ifdef __amd64__
-static int expect_signal = SIGBUS;
-#else
static int expect_signal = SIGSEGV;
-#endif
diff --git a/tools/regression/bpf/bpf_filter/tests/test0076.h b/tools/regression/bpf/bpf_filter/tests/test0076.h
--- a/tools/regression/bpf/bpf_filter/tests/test0076.h
+++ b/tools/regression/bpf/bpf_filter/tests/test0076.h
@@ -30,8 +30,4 @@
static u_int expect = 0xdeadc0de;
/* Expected signal */
-#ifdef __amd64__
-static int expect_signal = SIGBUS;
-#else
static int expect_signal = SIGSEGV;
-#endif
diff --git a/tools/regression/bpf/bpf_filter/tests/test0077.h b/tools/regression/bpf/bpf_filter/tests/test0077.h
--- a/tools/regression/bpf/bpf_filter/tests/test0077.h
+++ b/tools/regression/bpf/bpf_filter/tests/test0077.h
@@ -29,8 +29,4 @@
static u_int expect = 0xdeadc0de;
/* Expected signal */
-#ifdef __amd64__
-static int expect_signal = SIGBUS;
-#else
static int expect_signal = SIGSEGV;
-#endif
diff --git a/tools/regression/bpf/bpf_filter/tests/test0078.h b/tools/regression/bpf/bpf_filter/tests/test0078.h
--- a/tools/regression/bpf/bpf_filter/tests/test0078.h
+++ b/tools/regression/bpf/bpf_filter/tests/test0078.h
@@ -30,8 +30,4 @@
static u_int expect = 0xdeadc0de;
/* Expected signal */
-#ifdef __amd64__
-static int expect_signal = SIGBUS;
-#else
static int expect_signal = SIGSEGV;
-#endif
diff --git a/tools/regression/bpf/bpf_filter/tests/test0083.h b/tools/regression/bpf/bpf_filter/tests/test0083.h
--- a/tools/regression/bpf/bpf_filter/tests/test0083.h
+++ b/tools/regression/bpf/bpf_filter/tests/test0083.h
@@ -27,8 +27,4 @@
static u_int expect = 0;
/* Expected signal */
-#ifdef BPF_JIT_COMPILER
static int expect_signal = SIGSEGV;
-#else
-static int expect_signal = SIGABRT;
-#endif

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 22, 7:54 AM (21 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31962927
Default Alt Text
D37563.id.diff (25 KB)

Event Timeline