2 * Lightweight Autonomic Network Architecture
4 * LANA Berkeley Packet Filter (BPF) module.
6 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
7 * Swiss federal institute of technology (ETH Zurich)
10 * To generate BPF's, do the following:
11 * 1. Install flex + bison
13 * 2. Download bpfc from http://netsniff-ng.org i.e.:
15 * git clone git://repo.or.cz/netsniff-ng.git
16 * cd netsniff-ng/src/bpfc/
17 * make && make install
26 * And finally cat the code into the fb's procfs file, e.g.
27 * bpfc firstfilter > /proc/net/lana/fblock/fb1
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/spinlock.h>
33 #include <linux/notifier.h>
34 #include <linux/rcupdate.h>
35 #include <linux/seqlock.h>
36 #include <linux/spinlock.h>
37 #include <linux/slab.h>
38 #include <linux/percpu.h>
39 #include <linux/prefetch.h>
40 #include <linux/filter.h>
41 #include <linux/proc_fs.h>
42 #include <linux/seq_file.h>
43 #include <linux/uaccess.h>
45 #include "xt_fblock.h"
46 #include "xt_builder.h"
49 #include "xt_engine.h"
50 #include "xt_builder.h"
54 struct sk_filter
*filter
;
58 struct sock_fprog_kern
{
60 struct sock_filter
*filter
;
65 * To use the BPF JIT compiler, you need to export symbols from
66 * /arch/x86/net/ so that they can be used from a module. Then,
67 * recompile your kernel with CONFIG_BPF_JIT=y and change symbols
68 * within this file from fb_bpf_jit_<x> to bpf_jit_<x> and the macro
69 * FB_SK_RUN_FILTER to SK_RUN_FILTER.
72 static inline void fb_bpf_jit_compile(struct sk_filter
*fp
)
76 static inline void fb_bpf_jit_free(struct sk_filter
*fp
)
80 static int fb_bpf_init_filter(struct fb_bpf_priv __percpu
*fb_priv_cpu
,
81 struct sock_fprog_kern
*fprog
, unsigned int cpu
)
84 struct sk_filter
*sf
, *sfold
;
88 if (fprog
->filter
== NULL
)
91 fsize
= sizeof(struct sock_filter
) * fprog
->len
;
93 sf
= kmalloc_node(fsize
+ sizeof(*sf
), GFP_KERNEL
, cpu_to_node(cpu
));
97 memcpy(sf
->insns
, fprog
->filter
, fsize
);
98 atomic_set(&sf
->refcnt
, 1);
100 sf
->bpf_func
= sk_run_filter
;
102 err
= sk_chk_filter(sf
->insns
, sf
->len
);
108 fb_bpf_jit_compile(sf
);
110 spin_lock_irqsave(&fb_priv_cpu
->flock
, flags
);
111 sfold
= fb_priv_cpu
->filter
;
112 fb_priv_cpu
->filter
= sf
;
113 spin_unlock_irqrestore(&fb_priv_cpu
->flock
, flags
);
116 fb_bpf_jit_free(sfold
);
123 static int fb_bpf_init_filter_cpus(struct fblock
*fb
,
124 struct sock_fprog_kern
*fprog
)
128 struct fb_bpf_priv __percpu
*fb_priv
;
134 fb_priv
= (struct fb_bpf_priv __percpu
*) rcu_dereference_raw(fb
->private_data
);
138 for_each_online_cpu(cpu
) {
139 struct fb_bpf_priv
*fb_priv_cpu
;
140 fb_priv_cpu
= per_cpu_ptr(fb_priv
, cpu
);
141 err
= fb_bpf_init_filter(fb_priv_cpu
, fprog
, cpu
);
143 printk(KERN_ERR
"[%s::%s] fb_bpf_init_filter error: %d\n",
144 fb
->name
, fb
->factory
->type
, err
);
153 static void fb_bpf_cleanup_filter(struct fb_bpf_priv __percpu
*fb_priv_cpu
)
156 struct sk_filter
*sfold
;
158 spin_lock_irqsave(&fb_priv_cpu
->flock
, flags
);
159 sfold
= fb_priv_cpu
->filter
;
160 fb_priv_cpu
->filter
= NULL
;
161 spin_unlock_irqrestore(&fb_priv_cpu
->flock
, flags
);
164 fb_bpf_jit_free(sfold
);
169 static void fb_bpf_cleanup_filter_cpus(struct fblock
*fb
)
172 struct fb_bpf_priv __percpu
*fb_priv
;
178 fb_priv
= (struct fb_bpf_priv __percpu
*) rcu_dereference_raw(fb
->private_data
);
182 for_each_online_cpu(cpu
) {
183 struct fb_bpf_priv
*fb_priv_cpu
;
184 fb_priv_cpu
= per_cpu_ptr(fb_priv
, cpu
);
185 fb_bpf_cleanup_filter(fb_priv_cpu
);
190 static int fb_bpf_netrx(const struct fblock
* const fb
,
191 struct sk_buff
* const skb
,
192 enum path_type
* const dir
)
195 unsigned int pkt_len
;
197 struct fb_bpf_priv __percpu
*fb_priv_cpu
;
199 fb_priv_cpu
= this_cpu_ptr(rcu_dereference_raw(fb
->private_data
));
201 spin_lock_irqsave(&fb_priv_cpu
->flock
, flags
);
202 if (fb_priv_cpu
->filter
) {
203 pkt_len
= SK_RUN_FILTER(fb_priv_cpu
->filter
, skb
);
204 if (pkt_len
< skb
->len
) {
205 spin_unlock_irqrestore(&fb_priv_cpu
->flock
, flags
);
210 write_next_idp_to_skb(skb
, fb
->idp
, fb_priv_cpu
->port
[*dir
]);
211 if (fb_priv_cpu
->port
[*dir
] == IDP_UNKNOWN
)
213 spin_unlock_irqrestore(&fb_priv_cpu
->flock
, flags
);
221 static int fb_bpf_event(struct notifier_block
*self
, unsigned long cmd
,
227 struct fb_bpf_priv __percpu
*fb_priv
;
230 fb
= rcu_dereference_raw(container_of(self
, struct fblock_notifier
, nb
)->self
);
231 fb_priv
= (struct fb_bpf_priv __percpu
*) rcu_dereference_raw(fb
->private_data
);
235 case FBLOCK_BIND_IDP
: {
237 struct fblock_bind_msg
*msg
= args
;
239 for_each_online_cpu(cpu
) {
240 struct fb_bpf_priv
*fb_priv_cpu
;
241 fb_priv_cpu
= per_cpu_ptr(fb_priv
, cpu
);
242 spin_lock(&fb_priv_cpu
->flock
);
243 if (fb_priv_cpu
->port
[msg
->dir
] == IDP_UNKNOWN
) {
244 fb_priv_cpu
->port
[msg
->dir
] = msg
->idp
;
248 spin_unlock(&fb_priv_cpu
->flock
);
251 spin_unlock(&fb_priv_cpu
->flock
);
255 printk(KERN_INFO
"[%s::%s] port %s bound to IDP%u\n",
256 fb
->name
, fb
->factory
->type
,
257 path_names
[msg
->dir
], msg
->idp
);
259 case FBLOCK_UNBIND_IDP
: {
261 struct fblock_bind_msg
*msg
= args
;
263 for_each_online_cpu(cpu
) {
264 struct fb_bpf_priv
*fb_priv_cpu
;
265 fb_priv_cpu
= per_cpu_ptr(fb_priv
, cpu
);
266 spin_lock(&fb_priv_cpu
->flock
);
267 if (fb_priv_cpu
->port
[msg
->dir
] == msg
->idp
) {
268 fb_priv_cpu
->port
[msg
->dir
] = IDP_UNKNOWN
;
272 spin_unlock(&fb_priv_cpu
->flock
);
275 spin_unlock(&fb_priv_cpu
->flock
);
279 printk(KERN_INFO
"[%s::%s] port %s unbound\n",
280 fb
->name
, fb
->factory
->type
,
281 path_names
[msg
->dir
]);
290 static int fb_bpf_proc_show_filter(struct seq_file
*m
, void *v
)
293 struct fblock
*fb
= (struct fblock
*) m
->private;
294 struct fb_bpf_priv
*fb_priv_cpu
;
295 struct sk_filter
*sf
;
299 fb_priv_cpu
= this_cpu_ptr(rcu_dereference_raw(fb
->private_data
));
302 spin_lock_irqsave(&fb_priv_cpu
->flock
, flags
);
303 sf
= fb_priv_cpu
->filter
;
306 if (sf
->bpf_func
== sk_run_filter
)
307 seq_puts(m
, "bpf jit: 0\n");
309 seq_puts(m
, "bpf jit: 1\n");
310 seq_puts(m
, "code:\n");
311 for (i
= 0; i
< sf
->len
; ++i
) {
313 memset(sline
, 0, sizeof(sline
));
314 snprintf(sline
, sizeof(sline
),
315 "{ 0x%x, %u, %u, 0x%x }\n",
320 sline
[sizeof(sline
) - 1] = 0;
324 spin_unlock_irqrestore(&fb_priv_cpu
->flock
, flags
);
330 static int fb_bpf_proc_open(struct inode
*inode
, struct file
*file
)
332 return single_open(file
, fb_bpf_proc_show_filter
, PDE(inode
)->data
);
335 #define MAX_BUFF_SIZ 16384
336 #define MAX_INSTR_SIZ 512
338 static ssize_t
fb_bpf_proc_write(struct file
*file
, const char __user
* ubuff
,
339 size_t count
, loff_t
* offset
)
343 char *code
, *ptr1
, *ptr2
;
344 size_t len
= MAX_BUFF_SIZ
;
345 struct sock_fprog_kern
*fp
;
346 struct fblock
*fb
= PDE(file
->f_path
.dentry
->d_inode
)->data
;
348 if (count
> MAX_BUFF_SIZ
)
350 if (count
< MAX_BUFF_SIZ
)
353 code
= kmalloc(len
, GFP_KERNEL
);
356 fp
= kmalloc(sizeof(*fp
), GFP_KERNEL
);
359 fp
->filter
= kmalloc(MAX_INSTR_SIZ
* sizeof(struct sock_filter
), GFP_KERNEL
);
362 memset(code
, 0, len
);
363 if (copy_from_user(code
, ubuff
, len
)) {
372 while (fp
->len
< MAX_INSTR_SIZ
&& (char *) (code
+ len
) > ptr1
) {
373 while (ptr1
&& (*ptr1
== ' ' || *ptr1
== '{'))
375 fp
->filter
[fp
->len
].code
= (__u16
) simple_strtoul(ptr1
, &ptr2
, 16);
376 while (ptr2
&& (*ptr2
== ' ' || *ptr2
== ','))
378 fp
->filter
[fp
->len
].jt
= (__u8
) simple_strtoul(ptr2
, &ptr1
, 10);
379 while (ptr1
&& (*ptr1
== ' ' || *ptr1
== ','))
381 fp
->filter
[fp
->len
].jf
= (__u8
) simple_strtoul(ptr1
, &ptr2
, 10);
382 while (ptr2
&& (*ptr2
== ' ' || *ptr2
== ','))
384 fp
->filter
[fp
->len
].k
= (__u32
) simple_strtoul(ptr2
, &ptr1
, 16);
385 while (ptr1
&& (*ptr1
== ' ' || *ptr1
== ',' || *ptr1
== '}' ||
391 if (fp
->len
== MAX_INSTR_SIZ
) {
392 printk(KERN_ERR
"[%s::%s] Maximun instruction size exeeded!\n",
393 fb
->name
, fb
->factory
->type
);
397 printk(KERN_ERR
"[%s::%s] Parsed code:\n", fb
->name
, fb
->factory
->type
);
398 for (i
= 0; i
< fp
->len
; ++i
) {
399 printk(KERN_INFO
"[%s::%s] %d: c:0x%x jt:%u jf:%u k:0x%x\n",
400 fb
->name
, fb
->factory
->type
, i
,
401 fp
->filter
[i
].code
, fp
->filter
[i
].jt
, fp
->filter
[i
].jf
,
405 fb_bpf_cleanup_filter_cpus(fb
);
406 ret
= fb_bpf_init_filter_cpus(fb
, fp
);
408 printk(KERN_INFO
"[%s::%s] Filter injected!\n",
409 fb
->name
, fb
->factory
->type
);
411 printk(KERN_ERR
"[%s::%s] Filter injection error: %ld!\n",
412 fb
->name
, fb
->factory
->type
, ret
);
413 fb_bpf_cleanup_filter_cpus(fb
);
427 return !ret
? -ENOMEM
: ret
;
431 static const struct file_operations fb_bpf_proc_fops
= {
432 .owner
= THIS_MODULE
,
433 .open
= fb_bpf_proc_open
,
436 .write
= fb_bpf_proc_write
,
437 .release
= single_release
,
440 static struct fblock
*fb_bpf_ctor(char *name
)
445 struct fb_bpf_priv __percpu
*fb_priv
;
446 struct proc_dir_entry
*fb_proc
;
448 fb
= alloc_fblock(GFP_ATOMIC
);
452 fb_priv
= alloc_percpu(struct fb_bpf_priv
);
457 for_each_online_cpu(cpu
) {
458 struct fb_bpf_priv
*fb_priv_cpu
;
459 fb_priv_cpu
= per_cpu_ptr(fb_priv
, cpu
);
460 spin_lock_init(&fb_priv_cpu
->flock
);
461 fb_priv_cpu
->port
[0] = IDP_UNKNOWN
;
462 fb_priv_cpu
->port
[1] = IDP_UNKNOWN
;
463 fb_priv_cpu
->filter
= NULL
;
467 ret
= init_fblock(fb
, name
, fb_priv
);
471 fb
->netfb_rx
= fb_bpf_netrx
;
472 fb
->event_rx
= fb_bpf_event
;
474 fb_proc
= proc_create_data(fb
->name
, 0444, fblock_proc_dir
,
475 &fb_bpf_proc_fops
, (void *)(long) fb
);
479 ret
= register_fblock_namespace(fb
);
483 __module_get(THIS_MODULE
);
487 remove_proc_entry(fb
->name
, fblock_proc_dir
);
489 cleanup_fblock_ctor(fb
);
491 free_percpu(fb_priv
);
497 static void fb_bpf_dtor(struct fblock
*fb
)
499 free_percpu(rcu_dereference_raw(fb
->private_data
));
500 remove_proc_entry(fb
->name
, fblock_proc_dir
);
501 module_put(THIS_MODULE
);
504 static void fb_bpf_dtor_outside_rcu(struct fblock
*fb
)
506 fb_bpf_cleanup_filter_cpus(fb
);
509 static struct fblock_factory fb_bpf_factory
= {
514 .dtor_outside_rcu
= fb_bpf_dtor_outside_rcu
,
515 .owner
= THIS_MODULE
,
518 static int __init
init_fb_bpf_module(void)
520 return register_fblock_type(&fb_bpf_factory
);
523 static void __exit
cleanup_fb_bpf_module(void)
526 unregister_fblock_type(&fb_bpf_factory
);
529 module_init(init_fb_bpf_module
);
530 module_exit(cleanup_fb_bpf_module
);
532 MODULE_LICENSE("GPL");
533 MODULE_AUTHOR("Daniel Borkmann <dborkma@tik.ee.ethz.ch>");
534 MODULE_DESCRIPTION("LANA Berkeley Packet Filter module");