2 * Linux Socket Filter - Kernel level socket filtering
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>
25 #include <linux/fcntl.h>
26 #include <linux/socket.h>
28 #include <linux/inet.h>
29 #include <linux/netdevice.h>
30 #include <linux/if_packet.h>
32 #include <net/protocol.h>
33 #include <linux/skbuff.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
)
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
)
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 */
79 * Process array of filter instructions.
82 for(pc
= 0; pc
< flen
; pc
++)
88 case BPF_ALU
|BPF_ADD
|BPF_X
:
92 case BPF_ALU
|BPF_ADD
|BPF_K
:
96 case BPF_ALU
|BPF_SUB
|BPF_X
:
100 case BPF_ALU
|BPF_SUB
|BPF_K
:
104 case BPF_ALU
|BPF_MUL
|BPF_X
:
108 case BPF_ALU
|BPF_MUL
|BPF_K
:
112 case BPF_ALU
|BPF_DIV
|BPF_X
:
118 case BPF_ALU
|BPF_DIV
|BPF_K
:
124 case BPF_ALU
|BPF_AND
|BPF_X
:
128 case BPF_ALU
|BPF_AND
|BPF_K
:
132 case BPF_ALU
|BPF_OR
|BPF_X
:
136 case BPF_ALU
|BPF_OR
|BPF_K
:
140 case BPF_ALU
|BPF_LSH
|BPF_X
:
144 case BPF_ALU
|BPF_LSH
|BPF_K
:
148 case BPF_ALU
|BPF_RSH
|BPF_X
:
152 case BPF_ALU
|BPF_RSH
|BPF_K
:
156 case BPF_ALU
|BPF_NEG
:
164 case BPF_JMP
|BPF_JGT
|BPF_K
:
165 pc
+= (A
> fentry
->k
) ? fentry
->jt
: fentry
->jf
;
168 case BPF_JMP
|BPF_JGE
|BPF_K
:
169 pc
+= (A
>= fentry
->k
) ? fentry
->jt
: fentry
->jf
;
172 case BPF_JMP
|BPF_JEQ
|BPF_K
:
173 pc
+= (A
== fentry
->k
) ? fentry
->jt
: fentry
->jf
;
176 case BPF_JMP
|BPF_JSET
|BPF_K
:
177 pc
+= (A
& fentry
->k
) ? fentry
->jt
: fentry
->jf
;
180 case BPF_JMP
|BPF_JGT
|BPF_X
:
181 pc
+= (A
> X
) ? fentry
->jt
: fentry
->jf
;
184 case BPF_JMP
|BPF_JGE
|BPF_X
:
185 pc
+= (A
>= X
) ? fentry
->jt
: fentry
->jf
;
188 case BPF_JMP
|BPF_JEQ
|BPF_X
:
189 pc
+= (A
== X
) ? fentry
->jt
: fentry
->jf
;
192 case BPF_JMP
|BPF_JSET
|BPF_X
:
193 pc
+= (A
& X
) ? fentry
->jt
: fentry
->jf
;
196 case BPF_LD
|BPF_W
|BPF_ABS
:
199 if(k
+sizeof(u32
) <= len
) {
200 A
= ntohl(*(u32
*)&data
[k
]);
208 if ((ptr
= load_pointer(skb
, k
)) != NULL
) {
209 A
= ntohl(*(u32
*)ptr
);
215 case BPF_LD
|BPF_H
|BPF_ABS
:
218 if(k
+ sizeof(u16
) <= len
) {
219 A
= ntohs(*(u16
*)&data
[k
]);
227 if ((ptr
= load_pointer(skb
, k
)) != NULL
) {
228 A
= ntohs(*(u16
*)ptr
);
234 case BPF_LD
|BPF_B
|BPF_ABS
:
246 if ((ptr
= load_pointer(skb
, k
)) != NULL
) {
252 case BPF_LD
|BPF_W
|BPF_LEN
:
256 case BPF_LDX
|BPF_W
|BPF_LEN
:
260 case BPF_LD
|BPF_W
|BPF_IND
:
264 case BPF_LD
|BPF_H
|BPF_IND
:
268 case BPF_LD
|BPF_B
|BPF_IND
:
272 case BPF_LDX
|BPF_B
|BPF_MSH
:
276 X
= (data
[k
] & 0xf) << 2;
283 case BPF_LDX
|BPF_IMM
:
291 case BPF_LDX
|BPF_MEM
:
295 case BPF_MISC
|BPF_TAX
:
299 case BPF_MISC
|BPF_TXA
:
304 return ((unsigned int)fentry
->k
);
307 return ((unsigned int)A
);
318 /* Invalid instruction counts as RET */
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
);
333 A
= skb
->dev
->ifindex
;
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
;
354 * Check the filter code now.
356 for(pc
= 0; pc
< flen
; pc
++)
359 * All jumps are forward as they are not signed
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))
380 * For conditionals both must be safe
382 if(pc
+ ftest
->jt
+1 >= flen
|| pc
+ ftest
->jf
+1 >= flen
)
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
) {
400 case BPF_LDX
|BPF_MEM
:
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
;
426 /* Make sure new filter is there and in the right amounts. */
427 if (fprog
->filter
== NULL
|| fprog
->len
> BPF_MAXINSNS
)
430 fp
= (struct sk_filter
*)sock_kmalloc(sk
, fsize
+sizeof(*fp
), GFP_KERNEL
);
434 if (copy_from_user(fp
->insns
, fprog
->filter
, fsize
)) {
435 sock_kfree_s(sk
, fp
, fsize
+sizeof(*fp
));
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
;
450 sk_filter_release(sk
, fp
);
454 #endif /* CONFIG_FILTER */