Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153463893
D37563.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
25 KB
Referenced Files
None
Subscribers
None
D37563.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D37563: [WIP] bpf(9): Refactor to improve readability.
Attached
Detach File
Event Timeline
Log In to Comment