1/*- 2 * Copyright (C) 2008 Jung-uk Kim <jkim@FreeBSD.org>. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h>
| 1/*- 2 * Copyright (C) 2008 Jung-uk Kim <jkim@FreeBSD.org>. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h>
|
27__FBSDID("$FreeBSD: head/tools/regression/bpf/bpf_filter/bpf_test.c 182185 2008-08-26 00:35:04Z jkim $");
| 27__FBSDID("$FreeBSD: head/tools/regression/bpf/bpf_filter/bpf_test.c 182219 2008-08-26 19:24:58Z jkim $");
|
28 29#include <signal.h> 30#include <stdio.h> 31#include <stdlib.h> 32 33#include <sys/types.h> 34 35#include <net/bpf.h> 36 37#include BPF_TEST_H 38 39#define PASSED 0 40#define FAILED 1 41#define FATAL -1 42 43#ifndef LOG_LEVEL 44#define LOG_LEVEL 1 45#endif 46 47#ifdef BPF_BENCHMARK 48#define BPF_NRUNS 10000000 49#else 50#define BPF_NRUNS 1 51#endif 52 53static void sig_handler(int); 54 55#if defined(BPF_JIT_COMPILER) || defined(BPF_VALIDATE) 56static int nins = sizeof(pc) / sizeof(pc[0]); 57#endif 58 59static int verbose = LOG_LEVEL; 60 61#ifdef BPF_JIT_COMPILER 62 63#include <net/bpf_jitter.h> 64 65static u_int 66bpf_compile_and_filter(void) 67{ 68 bpf_jit_filter *filter; 69 u_int i, ret; 70 71 /* Do not use BPF JIT compiler for an empty program */ 72 if (nins == 0) 73 return (0); 74 75 /* Compile the BPF filter program and generate native code. */ 76 if ((filter = bpf_jitter(pc, nins)) == NULL) { 77 if (verbose > 1) 78 printf("Failed to allocate memory:\t"); 79 if (verbose > 0) 80 printf("FATAL\n"); 81 exit(FATAL); 82 } 83 84 for (i = 0; i < BPF_NRUNS; i++) 85 ret = (*(filter->func))(pkt, wirelen, buflen); 86 87 bpf_destroy_jit_filter(filter); 88 89 return (ret); 90} 91
| 28 29#include <signal.h> 30#include <stdio.h> 31#include <stdlib.h> 32 33#include <sys/types.h> 34 35#include <net/bpf.h> 36 37#include BPF_TEST_H 38 39#define PASSED 0 40#define FAILED 1 41#define FATAL -1 42 43#ifndef LOG_LEVEL 44#define LOG_LEVEL 1 45#endif 46 47#ifdef BPF_BENCHMARK 48#define BPF_NRUNS 10000000 49#else 50#define BPF_NRUNS 1 51#endif 52 53static void sig_handler(int); 54 55#if defined(BPF_JIT_COMPILER) || defined(BPF_VALIDATE) 56static int nins = sizeof(pc) / sizeof(pc[0]); 57#endif 58 59static int verbose = LOG_LEVEL; 60 61#ifdef BPF_JIT_COMPILER 62 63#include <net/bpf_jitter.h> 64 65static u_int 66bpf_compile_and_filter(void) 67{ 68 bpf_jit_filter *filter; 69 u_int i, ret; 70 71 /* Do not use BPF JIT compiler for an empty program */ 72 if (nins == 0) 73 return (0); 74 75 /* Compile the BPF filter program and generate native code. */ 76 if ((filter = bpf_jitter(pc, nins)) == NULL) { 77 if (verbose > 1) 78 printf("Failed to allocate memory:\t"); 79 if (verbose > 0) 80 printf("FATAL\n"); 81 exit(FATAL); 82 } 83 84 for (i = 0; i < BPF_NRUNS; i++) 85 ret = (*(filter->func))(pkt, wirelen, buflen); 86 87 bpf_destroy_jit_filter(filter); 88 89 return (ret); 90} 91
|
| 92#else 93 94u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int); 95
|
92#endif 93 94#ifdef BPF_VALIDATE 95/* 96 * XXX Copied from sys/net/bpf_filter.c and modified. 97 * 98 * Return true if the 'fcode' is a valid filter program. 99 * The constraints are that each jump be forward and to a valid 100 * code. The code must terminate with either an accept or reject. 101 * 102 * The kernel needs to be able to verify an application's filter code. 103 * Otherwise, a bogus program could easily crash the system. 104 */ 105static int 106bpf_validate(const struct bpf_insn *f, int len) 107{ 108 register int i; 109 register const struct bpf_insn *p; 110 111 /* Do not accept negative length filter. */ 112 if (len < 0) 113 return (0); 114 115 /* An empty filter means accept all. */ 116 if (len == 0) 117 return (1); 118 119 for (i = 0; i < len; ++i) { 120 /* 121 * Check that that jumps are forward, and within 122 * the code block. 123 */ 124 p = &f[i];
| 96#endif 97 98#ifdef BPF_VALIDATE 99/* 100 * XXX Copied from sys/net/bpf_filter.c and modified. 101 * 102 * Return true if the 'fcode' is a valid filter program. 103 * The constraints are that each jump be forward and to a valid 104 * code. The code must terminate with either an accept or reject. 105 * 106 * The kernel needs to be able to verify an application's filter code. 107 * Otherwise, a bogus program could easily crash the system. 108 */ 109static int 110bpf_validate(const struct bpf_insn *f, int len) 111{ 112 register int i; 113 register const struct bpf_insn *p; 114 115 /* Do not accept negative length filter. */ 116 if (len < 0) 117 return (0); 118 119 /* An empty filter means accept all. */ 120 if (len == 0) 121 return (1); 122 123 for (i = 0; i < len; ++i) { 124 /* 125 * Check that that jumps are forward, and within 126 * the code block. 127 */ 128 p = &f[i];
|
| 129#if BPF_VALIDATE > 1 130 /* 131 * XXX JK: Illegal instructions must be checked here. 132 */ 133 switch (p->code) { 134 default: 135 return (0); 136 case BPF_RET|BPF_K: 137 case BPF_RET|BPF_A: 138 case BPF_LD|BPF_W|BPF_ABS: 139 case BPF_LD|BPF_H|BPF_ABS: 140 case BPF_LD|BPF_B|BPF_ABS: 141 case BPF_LD|BPF_W|BPF_LEN: 142 case BPF_LDX|BPF_W|BPF_LEN: 143 case BPF_LD|BPF_W|BPF_IND: 144 case BPF_LD|BPF_H|BPF_IND: 145 case BPF_LD|BPF_B|BPF_IND: 146 case BPF_LDX|BPF_MSH|BPF_B: 147 case BPF_LD|BPF_IMM: 148 case BPF_LDX|BPF_IMM: 149 case BPF_LD|BPF_MEM: 150 case BPF_LDX|BPF_MEM: 151 case BPF_ST: 152 case BPF_STX: 153 case BPF_JMP|BPF_JA: 154 case BPF_JMP|BPF_JGT|BPF_K: 155 case BPF_JMP|BPF_JGE|BPF_K: 156 case BPF_JMP|BPF_JEQ|BPF_K: 157 case BPF_JMP|BPF_JSET|BPF_K: 158 case BPF_JMP|BPF_JGT|BPF_X: 159 case BPF_JMP|BPF_JGE|BPF_X: 160 case BPF_JMP|BPF_JEQ|BPF_X: 161 case BPF_JMP|BPF_JSET|BPF_X: 162 case BPF_ALU|BPF_ADD|BPF_X: 163 case BPF_ALU|BPF_SUB|BPF_X: 164 case BPF_ALU|BPF_MUL|BPF_X: 165 case BPF_ALU|BPF_DIV|BPF_X: 166 case BPF_ALU|BPF_AND|BPF_X: 167 case BPF_ALU|BPF_OR|BPF_X: 168 case BPF_ALU|BPF_LSH|BPF_X: 169 case BPF_ALU|BPF_RSH|BPF_X: 170 case BPF_ALU|BPF_ADD|BPF_K: 171 case BPF_ALU|BPF_SUB|BPF_K: 172 case BPF_ALU|BPF_MUL|BPF_K: 173 case BPF_ALU|BPF_DIV|BPF_K: 174 case BPF_ALU|BPF_AND|BPF_K: 175 case BPF_ALU|BPF_OR|BPF_K: 176 case BPF_ALU|BPF_LSH|BPF_K: 177 case BPF_ALU|BPF_RSH|BPF_K: 178 case BPF_ALU|BPF_NEG: 179 case BPF_MISC|BPF_TAX: 180 case BPF_MISC|BPF_TXA: 181 break; 182 } 183#endif
|
125 if (BPF_CLASS(p->code) == BPF_JMP) { 126 register int from = i + 1; 127 128 if (BPF_OP(p->code) == BPF_JA) { 129 if (from >= len || p->k >= (u_int)len - from) 130 return (0); 131 } 132 else if (from >= len || p->jt >= len - from || 133 p->jf >= len - from) 134 return (0); 135 } 136 /* 137 * Check that memory operations use valid addresses. 138 */ 139 if ((BPF_CLASS(p->code) == BPF_ST ||
| 184 if (BPF_CLASS(p->code) == BPF_JMP) { 185 register int from = i + 1; 186 187 if (BPF_OP(p->code) == BPF_JA) { 188 if (from >= len || p->k >= (u_int)len - from) 189 return (0); 190 } 191 else if (from >= len || p->jt >= len - from || 192 p->jf >= len - from) 193 return (0); 194 } 195 /* 196 * Check that memory operations use valid addresses. 197 */ 198 if ((BPF_CLASS(p->code) == BPF_ST ||
|
140 (BPF_CLASS(p->code) == BPF_LD && 141 (p->code & 0xe0) == BPF_MEM)) &&
| 199 (BPF_CLASS(p->code) == BPF_LD && 200 (p->code & 0xe0) == BPF_MEM)) &&
|
142 p->k >= BPF_MEMWORDS) 143 return (0);
| 201 p->k >= BPF_MEMWORDS) 202 return (0);
|
| 203#if BPF_VALIDATE > 1
|
144 /*
| 204 /*
|
| 205 * XXX JK: BPF_STX and BPF_LDX|BPF_MEM must be checked. 206 */ 207 if ((BPF_CLASS(p->code) == BPF_STX || 208 (BPF_CLASS(p->code) == BPF_LDX && 209 (p->code & 0xe0) == BPF_MEM)) && 210 p->k >= BPF_MEMWORDS) 211 return (0); 212#endif 213 /*
|
145 * Check for constant division by 0. 146 */ 147 if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) 148 return (0); 149 } 150 return (BPF_CLASS(f[len - 1].code) == BPF_RET); 151} 152#endif 153 154int 155main(void) 156{ 157#ifndef BPF_JIT_COMPILER 158 u_int i; 159#endif 160 u_int ret; 161 int sig; 162#ifdef BPF_VALIDATE 163 int valid; 164#endif 165 166 /* Try to catch all signals */ 167 for (sig = SIGHUP; sig <= SIGUSR2; sig++) 168 signal(sig, sig_handler); 169 170#ifdef BPF_VALIDATE 171 valid = bpf_validate(pc, nins); 172 if (valid != 0 && invalid != 0) { 173 if (verbose > 1)
| 214 * Check for constant division by 0. 215 */ 216 if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) 217 return (0); 218 } 219 return (BPF_CLASS(f[len - 1].code) == BPF_RET); 220} 221#endif 222 223int 224main(void) 225{ 226#ifndef BPF_JIT_COMPILER 227 u_int i; 228#endif 229 u_int ret; 230 int sig; 231#ifdef BPF_VALIDATE 232 int valid; 233#endif 234 235 /* Try to catch all signals */ 236 for (sig = SIGHUP; sig <= SIGUSR2; sig++) 237 signal(sig, sig_handler); 238 239#ifdef BPF_VALIDATE 240 valid = bpf_validate(pc, nins); 241 if (valid != 0 && invalid != 0) { 242 if (verbose > 1)
|
174 printf("Validated invalid instructions:\t");
| 243 printf("Validated invalid instruction(s):\t");
|
175 if (verbose > 0) 176 printf("FAILED\n"); 177 return (FAILED); 178 } else if (valid == 0 && invalid == 0) { 179 if (verbose > 1)
| 244 if (verbose > 0) 245 printf("FAILED\n"); 246 return (FAILED); 247 } else if (valid == 0 && invalid == 0) { 248 if (verbose > 1)
|
180 printf("Invalidated valid instructions:\t");
| 249 printf("Invalidated valid instruction(s):\t");
|
181 if (verbose > 0) 182 printf("FAILED\n"); 183 return (FAILED);
| 250 if (verbose > 0) 251 printf("FAILED\n"); 252 return (FAILED);
|
| 253 } else if (invalid != 0) { 254 if (verbose > 1) 255 printf("Expected and invalidated:\t"); 256 if (verbose > 0) 257 printf("PASSED\n"); 258 return (PASSED);
|
184 } 185#endif 186 187#ifdef BPF_JIT_COMPILER 188 ret = bpf_compile_and_filter(); 189#else 190 for (i = 0; i < BPF_NRUNS; i++) 191 ret = bpf_filter(pc, pkt, wirelen, buflen); 192#endif 193 if (ret != expect) { 194 if (verbose > 1) 195 printf("Expected 0x%x but got 0x%x:\t", expect, ret); 196 if (verbose > 0) 197 printf("FAILED\n"); 198 return (FAILED); 199 } 200 if (verbose > 1) 201 printf("Expected and got 0x%x:\t", ret); 202 if (verbose > 0) 203 printf("PASSED\n"); 204 205 return (PASSED); 206} 207 208static void 209sig_handler(int sig) 210{ 211 212 if (expect_signal == 0) { 213 if (verbose > 1) 214 printf("Received unexpected signal %d:\t", sig); 215 if (verbose > 0) 216 printf("FATAL\n"); 217 exit(FATAL); 218 } 219 if (expect_signal != sig) { 220 if (verbose > 1) 221 printf("Expected signal %d but got %d:\t", 222 expect_signal, sig); 223 if (verbose > 0) 224 printf("FAILED\n"); 225 exit(FAILED); 226 } 227 228 if (verbose > 1) 229 printf("Expected and got signal %d:\t", sig); 230 if (verbose > 0) 231 printf("PASSED\n"); 232 233 exit(PASSED); 234}
| 259 } 260#endif 261 262#ifdef BPF_JIT_COMPILER 263 ret = bpf_compile_and_filter(); 264#else 265 for (i = 0; i < BPF_NRUNS; i++) 266 ret = bpf_filter(pc, pkt, wirelen, buflen); 267#endif 268 if (ret != expect) { 269 if (verbose > 1) 270 printf("Expected 0x%x but got 0x%x:\t", expect, ret); 271 if (verbose > 0) 272 printf("FAILED\n"); 273 return (FAILED); 274 } 275 if (verbose > 1) 276 printf("Expected and got 0x%x:\t", ret); 277 if (verbose > 0) 278 printf("PASSED\n"); 279 280 return (PASSED); 281} 282 283static void 284sig_handler(int sig) 285{ 286 287 if (expect_signal == 0) { 288 if (verbose > 1) 289 printf("Received unexpected signal %d:\t", sig); 290 if (verbose > 0) 291 printf("FATAL\n"); 292 exit(FATAL); 293 } 294 if (expect_signal != sig) { 295 if (verbose > 1) 296 printf("Expected signal %d but got %d:\t", 297 expect_signal, sig); 298 if (verbose > 0) 299 printf("FAILED\n"); 300 exit(FAILED); 301 } 302 303 if (verbose > 1) 304 printf("Expected and got signal %d:\t", sig); 305 if (verbose > 0) 306 printf("PASSED\n"); 307 308 exit(PASSED); 309}
|