aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2012-03-31 07:01:19 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-03 18:36:20 -0400
commit302d663740cfaf2c364df6bb61cd339014ed714c (patch)
tree85e3ea387a72e08b91b325850af062f430ce1260 /net/core
parentfca231b2771cfd4e4f89445cf5c8dd81409b5b3c (diff)
filter: Allow to create sk-unattached filters
Today, BPF filters are bind to sockets. Since BPF machine becomes handy for other purposes, this patch allows to create unattached filter. Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/filter.c66
1 files changed, 62 insertions, 4 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 5dea45279215..cfbea889a0eb 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -587,6 +587,67 @@ void sk_filter_release_rcu(struct rcu_head *rcu)
587} 587}
588EXPORT_SYMBOL(sk_filter_release_rcu); 588EXPORT_SYMBOL(sk_filter_release_rcu);
589 589
590static int __sk_prepare_filter(struct sk_filter *fp)
591{
592 int err;
593
594 fp->bpf_func = sk_run_filter;
595
596 err = sk_chk_filter(fp->insns, fp->len);
597 if (err)
598 return err;
599
600 bpf_jit_compile(fp);
601 return 0;
602}
603
604/**
605 * sk_unattached_filter_create - create an unattached filter
606 * @fprog: the filter program
607 * @sk: the socket to use
608 *
609 * Create a filter independent ofr any socket. We first run some
610 * sanity checks on it to make sure it does not explode on us later.
611 * If an error occurs or there is insufficient memory for the filter
612 * a negative errno code is returned. On success the return is zero.
613 */
614int sk_unattached_filter_create(struct sk_filter **pfp,
615 struct sock_fprog *fprog)
616{
617 struct sk_filter *fp;
618 unsigned int fsize = sizeof(struct sock_filter) * fprog->len;
619 int err;
620
621 /* Make sure new filter is there and in the right amounts. */
622 if (fprog->filter == NULL)
623 return -EINVAL;
624
625 fp = kmalloc(fsize + sizeof(*fp), GFP_KERNEL);
626 if (!fp)
627 return -ENOMEM;
628 memcpy(fp->insns, fprog->filter, fsize);
629
630 atomic_set(&fp->refcnt, 1);
631 fp->len = fprog->len;
632
633 err = __sk_prepare_filter(fp);
634 if (err)
635 goto free_mem;
636
637 *pfp = fp;
638 return 0;
639free_mem:
640 kfree(fp);
641 return err;
642}
643EXPORT_SYMBOL_GPL(sk_unattached_filter_create);
644
645void sk_unattached_filter_destroy(struct sk_filter *fp)
646{
647 sk_filter_release(fp);
648}
649EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy);
650
590/** 651/**
591 * sk_attach_filter - attach a socket filter 652 * sk_attach_filter - attach a socket filter
592 * @fprog: the filter program 653 * @fprog: the filter program
@@ -617,16 +678,13 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
617 678
618 atomic_set(&fp->refcnt, 1); 679 atomic_set(&fp->refcnt, 1);
619 fp->len = fprog->len; 680 fp->len = fprog->len;
620 fp->bpf_func = sk_run_filter;
621 681
622 err = sk_chk_filter(fp->insns, fp->len); 682 err = __sk_prepare_filter(fp);
623 if (err) { 683 if (err) {
624 sk_filter_uncharge(sk, fp); 684 sk_filter_uncharge(sk, fp);
625 return err; 685 return err;
626 } 686 }
627 687
628 bpf_jit_compile(fp);
629
630 old_fp = rcu_dereference_protected(sk->sk_filter, 688 old_fp = rcu_dereference_protected(sk->sk_filter,
631 sock_owned_by_user(sk)); 689 sock_owned_by_user(sk));
632 rcu_assign_pointer(sk->sk_filter, fp); 690 rcu_assign_pointer(sk->sk_filter, fp);