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 +#include #if !defined(_KERNEL) -#include +#include #endif #if !defined(_KERNEL) || defined(sun) #include #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 #ifdef _KERNEL #include +extern int bpf_maxbufsize; #else #include -#endif +#define bpf_maxbufsize BPF_MAXBUFSIZE +#endif /* _KERNEL */ + #include -#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