diff --git a/share/man/man4/bpf.4 b/share/man/man4/bpf.4 index e63b3a6ce73..0d95c322784 100644 --- a/share/man/man4/bpf.4 +++ b/share/man/man4/bpf.4 @@ -49,7 +49,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 15, 2010 +.Dd October 21, 2016 .Dt BPF 4 .Os .Sh NAME @@ -881,16 +881,20 @@ BPF_ALU+BPF_ADD+BPF_K A <- A + k BPF_ALU+BPF_SUB+BPF_K A <- A - k BPF_ALU+BPF_MUL+BPF_K A <- A * k BPF_ALU+BPF_DIV+BPF_K A <- A / k +BPF_ALU+BPF_MOD+BPF_K A <- A % k BPF_ALU+BPF_AND+BPF_K A <- A & k BPF_ALU+BPF_OR+BPF_K A <- A | k +BPF_ALU+BPF_XOR+BPF_K A <- A ^ k BPF_ALU+BPF_LSH+BPF_K A <- A << k BPF_ALU+BPF_RSH+BPF_K A <- A >> k BPF_ALU+BPF_ADD+BPF_X A <- A + X BPF_ALU+BPF_SUB+BPF_X A <- A - X BPF_ALU+BPF_MUL+BPF_X A <- A * X BPF_ALU+BPF_DIV+BPF_X A <- A / X +BPF_ALU+BPF_MOD+BPF_X A <- A % X BPF_ALU+BPF_AND+BPF_X A <- A & X BPF_ALU+BPF_OR+BPF_X A <- A | X +BPF_ALU+BPF_XOR+BPF_X A <- A ^ X BPF_ALU+BPF_LSH+BPF_X A <- A << X BPF_ALU+BPF_RSH+BPF_X A <- A >> X BPF_ALU+BPF_NEG A <- -A diff --git a/sys/amd64/amd64/bpf_jit_machdep.c b/sys/amd64/amd64/bpf_jit_machdep.c index 01b898f84cf..f199c80b292 100644 --- a/sys/amd64/amd64/bpf_jit_machdep.c +++ b/sys/amd64/amd64/bpf_jit_machdep.c @@ -1,6 +1,6 @@ /*- * Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy) - * Copyright (C) 2005-2009 Jung-uk Kim + * Copyright (C) 2005-2016 Jung-uk Kim * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -494,6 +494,7 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size) break; case BPF_ALU|BPF_DIV|BPF_X: + case BPF_ALU|BPF_MOD|BPF_X: TESTrd(EDX, EDX); if (fmem) { JNEb(4); @@ -507,6 +508,8 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size) MOVrd(EDX, ECX); ZEROrd(EDX); DIVrd(ECX); + if (BPF_OP(ins->code) == BPF_MOD) + MOVrd(EDX, EAX); MOVrd(ECX, EDX); break; @@ -518,6 +521,10 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size) ORrd(EDX, EAX); break; + case BPF_ALU|BPF_XOR|BPF_X: + XORrd(EDX, EAX); + break; + case BPF_ALU|BPF_LSH|BPF_X: MOVrd(EDX, ECX); SHL_CLrb(EAX); @@ -544,10 +551,13 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size) break; case BPF_ALU|BPF_DIV|BPF_K: + case BPF_ALU|BPF_MOD|BPF_K: MOVrd(EDX, ECX); ZEROrd(EDX); MOVid(ins->k, ESI); DIVrd(ESI); + if (BPF_OP(ins->code) == BPF_MOD) + MOVrd(EDX, EAX); MOVrd(ECX, EDX); break; @@ -559,6 +569,10 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size) ORid(ins->k, EAX); break; + case BPF_ALU|BPF_XOR|BPF_K: + XORid(ins->k, EAX); + break; + case BPF_ALU|BPF_LSH|BPF_K: SHLib((ins->k) & 0xff, EAX); break; diff --git a/sys/amd64/amd64/bpf_jit_machdep.h b/sys/amd64/amd64/bpf_jit_machdep.h index 01c251f6db9..ad1e8462989 100644 --- a/sys/amd64/amd64/bpf_jit_machdep.h +++ b/sys/amd64/amd64/bpf_jit_machdep.h @@ -1,6 +1,6 @@ /*- * Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy) - * Copyright (C) 2005-2009 Jung-uk Kim + * Copyright (C) 2005-2016 Jung-uk Kim * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -357,6 +357,24 @@ typedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n); emitm(&stream, i32, 4); \ } while (0) +/* xorl sr32,dr32 */ +#define XORrd(sr32, dr32) do { \ + emitm(&stream, 0x31, 1); \ + emitm(&stream, \ + (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ +} while (0) + +/* xorl i32,r32 */ +#define XORid(i32, r32) do { \ + if (r32 == EAX) { \ + emitm(&stream, 0x35, 1); \ + } else { \ + emitm(&stream, 0x81, 1); \ + emitm(&stream, (25 << 3) | r32, 1); \ + } \ + emitm(&stream, i32, 4); \ +} while (0) + /* shll i8,r32 */ #define SHLib(i8, r32) do { \ emitm(&stream, 0xc1, 1); \ diff --git a/sys/i386/i386/bpf_jit_machdep.c b/sys/i386/i386/bpf_jit_machdep.c index 4c81c704b28..9f31dde17f0 100644 --- a/sys/i386/i386/bpf_jit_machdep.c +++ b/sys/i386/i386/bpf_jit_machdep.c @@ -1,6 +1,6 @@ /*- * Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy) - * Copyright (C) 2005-2009 Jung-uk Kim + * Copyright (C) 2005-2016 Jung-uk Kim * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -139,6 +139,7 @@ bpf_jit_optimize(struct bpf_insn *prog, u_int nins) flags |= BPF_JIT_FJMP; break; case BPF_ALU|BPF_DIV|BPF_K: + case BPF_ALU|BPF_MOD|BPF_K: flags |= BPF_JIT_FADK; break; } @@ -515,6 +516,7 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size) break; case BPF_ALU|BPF_DIV|BPF_X: + case BPF_ALU|BPF_MOD|BPF_X: TESTrd(EDX, EDX); if (save_esp) { if (fpkt) { @@ -536,6 +538,8 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size) MOVrd(EDX, ECX); ZEROrd(EDX); DIVrd(ECX); + if (BPF_OP(ins->code) == BPF_MOD) + MOVrd(EDX, EAX); MOVrd(ECX, EDX); break; @@ -547,6 +551,10 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size) ORrd(EDX, EAX); break; + case BPF_ALU|BPF_XOR|BPF_X: + XORrd(EDX, EAX); + break; + case BPF_ALU|BPF_LSH|BPF_X: MOVrd(EDX, ECX); SHL_CLrb(EAX); @@ -573,10 +581,13 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size) break; case BPF_ALU|BPF_DIV|BPF_K: + case BPF_ALU|BPF_MOD|BPF_K: MOVrd(EDX, ECX); ZEROrd(EDX); MOVid(ins->k, ESI); DIVrd(ESI); + if (BPF_OP(ins->code) == BPF_MOD) + MOVrd(EDX, EAX); MOVrd(ECX, EDX); break; @@ -588,6 +599,10 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size) ORid(ins->k, EAX); break; + case BPF_ALU|BPF_XOR|BPF_K: + XORid(ins->k, EAX); + break; + case BPF_ALU|BPF_LSH|BPF_K: SHLib((ins->k) & 0xff, EAX); break; diff --git a/sys/i386/i386/bpf_jit_machdep.h b/sys/i386/i386/bpf_jit_machdep.h index 4ae5494a72a..22d66321794 100644 --- a/sys/i386/i386/bpf_jit_machdep.h +++ b/sys/i386/i386/bpf_jit_machdep.h @@ -1,6 +1,6 @@ /*- * Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy) - * Copyright (C) 2005-2009 Jung-uk Kim + * Copyright (C) 2005-2016 Jung-uk Kim * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -302,6 +302,24 @@ typedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n); emitm(&stream, i32, 4); \ } while (0) +/* xorl sr32,dr32 */ +#define XORrd(sr32, dr32) do { \ + emitm(&stream, 0x31, 1); \ + emitm(&stream, \ + (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ +} while (0) + +/* xorl i32,r32 */ +#define XORid(i32, r32) do { \ + if (r32 == EAX) { \ + emitm(&stream, 0x35, 1); \ + } else { \ + emitm(&stream, 0x81, 1); \ + emitm(&stream, (25 << 3) | r32, 1); \ + } \ + emitm(&stream, i32, 4); \ +} while (0) + /* shll i8,r32 */ #define SHLib(i8, r32) do { \ emitm(&stream, 0xc1, 1); \ diff --git a/sys/net/bpf_filter.c b/sys/net/bpf_filter.c index ab3198ab3ea..54bcf9abf93 100644 --- a/sys/net/bpf_filter.c +++ b/sys/net/bpf_filter.c @@ -434,6 +434,12 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) A /= X; continue; + case BPF_ALU|BPF_MOD|BPF_X: + if (X == 0) + return (0); + A %= X; + continue; + case BPF_ALU|BPF_AND|BPF_X: A &= X; continue; @@ -442,6 +448,10 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) A |= X; continue; + case BPF_ALU|BPF_XOR|BPF_X: + A ^= X; + continue; + case BPF_ALU|BPF_LSH|BPF_X: A <<= X; continue; @@ -466,6 +476,10 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) A /= pc->k; continue; + case BPF_ALU|BPF_MOD|BPF_K: + A %= pc->k; + continue; + case BPF_ALU|BPF_AND|BPF_K: A &= pc->k; continue; @@ -474,6 +488,10 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) A |= pc->k; continue; + case BPF_ALU|BPF_XOR|BPF_K: + A ^= pc->k; + continue; + case BPF_ALU|BPF_LSH|BPF_K: A <<= pc->k; continue; @@ -508,8 +526,8 @@ static const u_short bpf_code_map[] = { 0x1013, /* 0x60-0x6f: 1100100000001000 */ 0x1010, /* 0x70-0x7f: 0000100000001000 */ 0x0093, /* 0x80-0x8f: 1100100100000000 */ - 0x0000, /* 0x90-0x9f: 0000000000000000 */ - 0x0000, /* 0xa0-0xaf: 0000000000000000 */ + 0x1010, /* 0x90-0x9f: 0000100000001000 */ + 0x1010, /* 0xa0-0xaf: 0000100000001000 */ 0x0002, /* 0xb0-0xbf: 0100000000000000 */ 0x0000, /* 0xc0-0xcf: 0000000000000000 */ 0x0000, /* 0xd0-0xdf: 0000000000000000 */ @@ -577,7 +595,8 @@ bpf_validate(const struct bpf_insn *f, int len) /* * Check for constant division by 0. */ - if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 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);