Import 2.2.5pre2
[davej-history.git] / net / core / filter.c
blobcc1ed83cd8325531eb080f7b9a442c614a29cd5e
1 /*
2 * Linux Socket Filter - Kernel level socket filtering
4 * Author:
5 * Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
7 * Based on the design of:
8 * - The Berkeley Packet Filter
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
15 * Andi Kleen - Fix a few bad bugs and races.
18 #include <linux/config.h>
19 #if defined(CONFIG_FILTER)
21 #include <linux/module.h>
22 #include <linux/types.h>
23 #include <linux/sched.h>
24 #include <linux/mm.h>
25 #include <linux/fcntl.h>
26 #include <linux/socket.h>
27 #include <linux/in.h>
28 #include <linux/inet.h>
29 #include <linux/netdevice.h>
30 #include <linux/if_packet.h>
31 #include <net/ip.h>
32 #include <net/protocol.h>
33 #include <linux/skbuff.h>
34 #include <net/sock.h>
35 #include <linux/errno.h>
36 #include <linux/timer.h>
37 #include <asm/system.h>
38 #include <asm/uaccess.h>
39 #include <linux/filter.h>
41 /* No hurry in this branch */
43 static u8 *load_pointer(struct sk_buff *skb, int k)
45 u8 *ptr = NULL;
47 if (k>=SKF_NET_OFF)
48 ptr = skb->nh.raw + k - SKF_NET_OFF;
49 else if (k>=SKF_LL_OFF)
50 ptr = skb->mac.raw + k - SKF_LL_OFF;
52 if (ptr<skb->head && ptr < skb->tail)
53 return ptr;
54 return NULL;
58 * Decode and apply filter instructions to the skb->data.
59 * Return length to keep, 0 for none. skb is the data we are
60 * filtering, filter is the array of filter instructions, and
61 * len is the number of filter blocks in the array.
64 int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
66 unsigned char *data = skb->data;
67 /* len is UNSIGNED. Byte wide insns relies only on implicit
68 type casts to prevent reading arbitrary memory locations.
70 unsigned int len = skb->len;
71 struct sock_filter *fentry; /* We walk down these */
72 u32 A = 0; /* Accumulator */
73 u32 X = 0; /* Index Register */
74 u32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */
75 int k;
76 int pc;
79 * Process array of filter instructions.
82 for(pc = 0; pc < flen; pc++)
84 fentry = &filter[pc];
86 switch(fentry->code)
88 case BPF_ALU|BPF_ADD|BPF_X:
89 A += X;
90 continue;
92 case BPF_ALU|BPF_ADD|BPF_K:
93 A += fentry->k;
94 continue;
96 case BPF_ALU|BPF_SUB|BPF_X:
97 A -= X;
98 continue;
100 case BPF_ALU|BPF_SUB|BPF_K:
101 A -= fentry->k;
102 continue;
104 case BPF_ALU|BPF_MUL|BPF_X:
105 A *= X;
106 continue;
108 case BPF_ALU|BPF_MUL|BPF_K:
109 A *= X;
110 continue;
112 case BPF_ALU|BPF_DIV|BPF_X:
113 if(X == 0)
114 return (0);
115 A /= X;
116 continue;
118 case BPF_ALU|BPF_DIV|BPF_K:
119 if(fentry->k == 0)
120 return (0);
121 A /= fentry->k;
122 continue;
124 case BPF_ALU|BPF_AND|BPF_X:
125 A &= X;
126 continue;
128 case BPF_ALU|BPF_AND|BPF_K:
129 A &= fentry->k;
130 continue;
132 case BPF_ALU|BPF_OR|BPF_X:
133 A |= X;
134 continue;
136 case BPF_ALU|BPF_OR|BPF_K:
137 A |= fentry->k;
138 continue;
140 case BPF_ALU|BPF_LSH|BPF_X:
141 A <<= X;
142 continue;
144 case BPF_ALU|BPF_LSH|BPF_K:
145 A <<= fentry->k;
146 continue;
148 case BPF_ALU|BPF_RSH|BPF_X:
149 A >>= X;
150 continue;
152 case BPF_ALU|BPF_RSH|BPF_K:
153 A >>= fentry->k;
154 continue;
156 case BPF_ALU|BPF_NEG:
157 A = -A;
158 continue;
160 case BPF_JMP|BPF_JA:
161 pc += fentry->k;
162 continue;
164 case BPF_JMP|BPF_JGT|BPF_K:
165 pc += (A > fentry->k) ? fentry->jt : fentry->jf;
166 continue;
168 case BPF_JMP|BPF_JGE|BPF_K:
169 pc += (A >= fentry->k) ? fentry->jt : fentry->jf;
170 continue;
172 case BPF_JMP|BPF_JEQ|BPF_K:
173 pc += (A == fentry->k) ? fentry->jt : fentry->jf;
174 continue;
176 case BPF_JMP|BPF_JSET|BPF_K:
177 pc += (A & fentry->k) ? fentry->jt : fentry->jf;
178 continue;
180 case BPF_JMP|BPF_JGT|BPF_X:
181 pc += (A > X) ? fentry->jt : fentry->jf;
182 continue;
184 case BPF_JMP|BPF_JGE|BPF_X:
185 pc += (A >= X) ? fentry->jt : fentry->jf;
186 continue;
188 case BPF_JMP|BPF_JEQ|BPF_X:
189 pc += (A == X) ? fentry->jt : fentry->jf;
190 continue;
192 case BPF_JMP|BPF_JSET|BPF_X:
193 pc += (A & X) ? fentry->jt : fentry->jf;
194 continue;
196 case BPF_LD|BPF_W|BPF_ABS:
197 k = fentry->k;
198 load_w:
199 if(k+sizeof(u32) <= len) {
200 A = ntohl(*(u32*)&data[k]);
201 continue;
203 if (k<0) {
204 u8 *ptr;
206 if (k>=SKF_AD_OFF)
207 break;
208 if ((ptr = load_pointer(skb, k)) != NULL) {
209 A = ntohl(*(u32*)ptr);
210 continue;
213 return 0;
215 case BPF_LD|BPF_H|BPF_ABS:
216 k = fentry->k;
217 load_h:
218 if(k + sizeof(u16) <= len) {
219 A = ntohs(*(u16*)&data[k]);
220 continue;
222 if (k<0) {
223 u8 *ptr;
225 if (k>=SKF_AD_OFF)
226 break;
227 if ((ptr = load_pointer(skb, k)) != NULL) {
228 A = ntohs(*(u16*)ptr);
229 continue;
232 return 0;
234 case BPF_LD|BPF_B|BPF_ABS:
235 k = fentry->k;
236 load_b:
237 if(k < len) {
238 A = data[k];
239 continue;
241 if (k<0) {
242 u8 *ptr;
244 if (k>=SKF_AD_OFF)
245 break;
246 if ((ptr = load_pointer(skb, k)) != NULL) {
247 A = *ptr;
248 continue;
252 case BPF_LD|BPF_W|BPF_LEN:
253 A = len;
254 continue;
256 case BPF_LDX|BPF_W|BPF_LEN:
257 X = len;
258 continue;
260 case BPF_LD|BPF_W|BPF_IND:
261 k = X + fentry->k;
262 goto load_w;
264 case BPF_LD|BPF_H|BPF_IND:
265 k = X + fentry->k;
266 goto load_h;
268 case BPF_LD|BPF_B|BPF_IND:
269 k = X + fentry->k;
270 goto load_b;
272 case BPF_LDX|BPF_B|BPF_MSH:
273 k = fentry->k;
274 if(k >= len)
275 return (0);
276 X = (data[k] & 0xf) << 2;
277 continue;
279 case BPF_LD|BPF_IMM:
280 A = fentry->k;
281 continue;
283 case BPF_LDX|BPF_IMM:
284 X = fentry->k;
285 continue;
287 case BPF_LD|BPF_MEM:
288 A = mem[fentry->k];
289 continue;
291 case BPF_LDX|BPF_MEM:
292 X = mem[fentry->k];
293 continue;
295 case BPF_MISC|BPF_TAX:
296 X = A;
297 continue;
299 case BPF_MISC|BPF_TXA:
300 A = X;
301 continue;
303 case BPF_RET|BPF_K:
304 return ((unsigned int)fentry->k);
306 case BPF_RET|BPF_A:
307 return ((unsigned int)A);
309 case BPF_ST:
310 mem[fentry->k] = A;
311 continue;
313 case BPF_STX:
314 mem[fentry->k] = X;
315 continue;
317 default:
318 /* Invalid instruction counts as RET */
319 return (0);
322 /* Handle ancillary data, which are impossible
323 (or very difficult) to get parsing packet contents.
325 switch (k-SKF_AD_OFF) {
326 case SKF_AD_PROTOCOL:
327 A = htons(skb->protocol);
328 continue;
329 case SKF_AD_PKTTYPE:
330 A = skb->pkt_type;
331 continue;
332 case SKF_AD_IFINDEX:
333 A = skb->dev->ifindex;
334 continue;
335 default:
336 return 0;
340 return (0);
344 * Check the user's filter code. If we let some ugly
345 * filter code slip through kaboom!
348 int sk_chk_filter(struct sock_filter *filter, int flen)
350 struct sock_filter *ftest;
351 int pc;
354 * Check the filter code now.
356 for(pc = 0; pc < flen; pc++)
359 * All jumps are forward as they are not signed
362 ftest = &filter[pc];
363 if(BPF_CLASS(ftest->code) == BPF_JMP)
366 * But they mustn't jump off the end.
368 if(BPF_OP(ftest->code) == BPF_JA)
370 /* Note, the large ftest->k might cause
371 loops. Compare this with conditional
372 jumps below, where offsets are limited. --ANK (981016)
374 if (ftest->k >= (unsigned)(flen-pc-1))
375 return (-EINVAL);
377 else
380 * For conditionals both must be safe
382 if(pc + ftest->jt +1 >= flen || pc + ftest->jf +1 >= flen)
383 return (-EINVAL);
388 * Check that memory operations use valid addresses.
391 if (ftest->k >= BPF_MEMWORDS)
394 * But it might not be a memory operation...
396 switch (ftest->code) {
397 case BPF_ST:
398 case BPF_STX:
399 case BPF_LD|BPF_MEM:
400 case BPF_LDX|BPF_MEM:
401 return -EINVAL;
407 * The program must end with a return. We don't care where they
408 * jumped within the script (its always forwards) but in the
409 * end they _will_ hit this.
412 return (BPF_CLASS(filter[flen - 1].code) == BPF_RET)?0:-EINVAL;
416 * Attach the user's filter code. We first run some sanity checks on
417 * it to make sure it does not explode on us later.
420 int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
422 struct sk_filter *fp;
423 unsigned int fsize = sizeof(struct sock_filter) * fprog->len;
424 int err;
426 /* Make sure new filter is there and in the right amounts. */
427 if (fprog->filter == NULL || fprog->len > BPF_MAXINSNS)
428 return (-EINVAL);
430 fp = (struct sk_filter *)sock_kmalloc(sk, fsize+sizeof(*fp), GFP_KERNEL);
431 if(fp == NULL)
432 return (-ENOMEM);
434 if (copy_from_user(fp->insns, fprog->filter, fsize)) {
435 sock_kfree_s(sk, fp, fsize+sizeof(*fp));
436 return -EFAULT;
439 atomic_set(&fp->refcnt, 1);
440 fp->len = fprog->len;
442 if ((err = sk_chk_filter(fp->insns, fp->len))==0) {
443 struct sk_filter *old_fp = sk->filter;
444 sk->filter = fp;
445 synchronize_bh();
446 fp = old_fp;
449 if (fp)
450 sk_filter_release(sk, fp);
452 return (err);
454 #endif /* CONFIG_FILTER */