1 /*- 2 * Copyright (C) 2008-2009 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$"); 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 53 static void sig_handler(int); 54 55 static int nins = sizeof(pc) / sizeof(pc[0]); 56 static int verbose = LOG_LEVEL; 57 58 #ifdef BPF_JIT_COMPILER 59 60 #include <libutil.h> 61 62 #include <net/bpf_jitter.h> 63 64 static u_int 65 bpf_compile_and_filter(void) 66 { 67 bpf_jit_filter *filter; 68 u_int i, ret; 69 70 /* Compile the BPF filter program and generate native code. */ 71 if ((filter = bpf_jitter(pc, nins)) == NULL) { 72 if (verbose > 1) 73 printf("Failed to allocate memory:\t"); 74 if (verbose > 0) 75 printf("FATAL\n"); 76 exit(FATAL); 77 } 78 if (verbose > 2) { 79 printf("\n"); 80 hexdump(filter->func, filter->size, NULL, HD_OMIT_CHARS); 81 } 82 83 for (i = 0; i < BPF_NRUNS; i++) 84 ret = (*(filter->func))(pkt, wirelen, buflen); 85 86 bpf_destroy_jit_filter(filter); 87 88 return (ret); 89 } 90 91 #else 92 93 u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int); 94 95 #endif 96 97 #ifdef BPF_VALIDATE 98 static const u_short bpf_code_map[] = { 99 0x10ff, /* 0x00-0x0f: 1111111100001000 */ 100 0x3070, /* 0x10-0x1f: 0000111000001100 */ 101 0x3131, /* 0x20-0x2f: 1000110010001100 */ 102 0x3031, /* 0x30-0x3f: 1000110000001100 */ 103 0x3131, /* 0x40-0x4f: 1000110010001100 */ 104 0x1011, /* 0x50-0x5f: 1000100000001000 */ 105 0x1013, /* 0x60-0x6f: 1100100000001000 */ 106 0x1010, /* 0x70-0x7f: 0000100000001000 */ 107 0x0093, /* 0x80-0x8f: 1100100100000000 */ 108 0x1010, /* 0x90-0x9f: 0000100000001000 */ 109 0x1010, /* 0xa0-0xaf: 0000100000001000 */ 110 0x0002, /* 0xb0-0xbf: 0100000000000000 */ 111 0x0000, /* 0xc0-0xcf: 0000000000000000 */ 112 0x0000, /* 0xd0-0xdf: 0000000000000000 */ 113 0x0000, /* 0xe0-0xef: 0000000000000000 */ 114 0x0000 /* 0xf0-0xff: 0000000000000000 */ 115 }; 116 117 #define BPF_VALIDATE_CODE(c) \ 118 ((c) <= 0xff && (bpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0) 119 120 /* 121 * XXX Copied from sys/net/bpf_filter.c and modified. 122 * 123 * Return true if the 'fcode' is a valid filter program. 124 * The constraints are that each jump be forward and to a valid 125 * code. The code must terminate with either an accept or reject. 126 * 127 * The kernel needs to be able to verify an application's filter code. 128 * Otherwise, a bogus program could easily crash the system. 129 */ 130 static int 131 bpf_validate(const struct bpf_insn *f, int len) 132 { 133 register int i; 134 register const struct bpf_insn *p; 135 136 /* Do not accept negative length filter. */ 137 if (len < 0) 138 return (0); 139 140 /* An empty filter means accept all. */ 141 if (len == 0) 142 return (1); 143 144 for (i = 0; i < len; ++i) { 145 p = &f[i]; 146 /* 147 * Check that the code is valid. 148 */ 149 if (!BPF_VALIDATE_CODE(p->code)) 150 return (0); 151 /* 152 * Check that jumps are forward, and within 153 * the code block. 154 */ 155 if (BPF_CLASS(p->code) == BPF_JMP) { 156 register u_int offset; 157 158 if (p->code == (BPF_JMP|BPF_JA)) 159 offset = p->k; 160 else 161 offset = p->jt > p->jf ? p->jt : p->jf; 162 if (offset >= (u_int)(len - i) - 1) 163 return (0); 164 continue; 165 } 166 /* 167 * Check that memory operations use valid addresses. 168 */ 169 if (p->code == BPF_ST || p->code == BPF_STX || 170 p->code == (BPF_LD|BPF_MEM) || 171 p->code == (BPF_LDX|BPF_MEM)) { 172 if (p->k >= BPF_MEMWORDS) 173 return (0); 174 continue; 175 } 176 /* 177 * Check for constant division by 0. 178 */ 179 if ((p->code == (BPF_ALU|BPF_DIV|BPF_K) || 180 p->code == (BPF_ALU|BPF_MOD|BPF_K)) && p->k == 0) 181 return (0); 182 } 183 return (BPF_CLASS(f[len - 1].code) == BPF_RET); 184 } 185 #endif 186 187 int 188 main(void) 189 { 190 #ifndef BPF_JIT_COMPILER 191 u_int i; 192 #endif 193 u_int ret; 194 int sig; 195 #ifdef BPF_VALIDATE 196 int valid; 197 #endif 198 199 /* Try to catch all signals */ 200 for (sig = SIGHUP; sig <= SIGUSR2; sig++) 201 signal(sig, sig_handler); 202 203 #ifdef BPF_VALIDATE 204 valid = bpf_validate(pc, nins); 205 if (valid != 0 && invalid != 0) { 206 if (verbose > 1) 207 printf("Validated invalid instruction(s):\t"); 208 if (verbose > 0) 209 printf("FAILED\n"); 210 return (FAILED); 211 } else if (valid == 0 && invalid == 0) { 212 if (verbose > 1) 213 printf("Invalidated valid instruction(s):\t"); 214 if (verbose > 0) 215 printf("FAILED\n"); 216 return (FAILED); 217 } else if (invalid != 0) { 218 if (verbose > 1) 219 printf("Expected and invalidated:\t"); 220 if (verbose > 0) 221 printf("PASSED\n"); 222 return (PASSED); 223 } 224 #endif 225 226 #ifdef BPF_JIT_COMPILER 227 ret = bpf_compile_and_filter(); 228 #else 229 for (i = 0; i < BPF_NRUNS; i++) 230 ret = bpf_filter(nins != 0 ? pc : NULL, pkt, wirelen, buflen); 231 #endif 232 if (expect_signal != 0) { 233 if (verbose > 1) 234 printf("Expected signal %d but got none:\t", 235 expect_signal); 236 if (verbose > 0) 237 printf("FAILED\n"); 238 return (FAILED); 239 } 240 if (ret != expect) { 241 if (verbose > 1) 242 printf("Expected 0x%x but got 0x%x:\t", expect, ret); 243 if (verbose > 0) 244 printf("FAILED\n"); 245 return (FAILED); 246 } 247 if (verbose > 1) 248 printf("Expected and got 0x%x:\t", ret); 249 if (verbose > 0) 250 printf("PASSED\n"); 251 252 return (PASSED); 253 } 254 255 static void 256 sig_handler(int sig) 257 { 258 259 if (expect_signal == 0) { 260 if (verbose > 1) 261 printf("Received unexpected signal %d:\t", sig); 262 if (verbose > 0) 263 printf("FATAL\n"); 264 exit(FATAL); 265 } 266 if (expect_signal != sig) { 267 if (verbose > 1) 268 printf("Expected signal %d but got %d:\t", 269 expect_signal, sig); 270 if (verbose > 0) 271 printf("FAILED\n"); 272 exit(FAILED); 273 } 274 275 if (verbose > 1) 276 printf("Expected and got signal %d:\t", sig); 277 if (verbose > 0) 278 printf("PASSED\n"); 279 280 exit(PASSED); 281 } 282