Skip to content

Commit

Permalink
filter: Allow to create sk-unattached filters
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jiri Pirko authored and David S. Miller committed Apr 3, 2012
1 parent fca231b commit 302d663
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 4 deletions.
3 changes: 3 additions & 0 deletions include/linux/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ static inline unsigned int sk_filter_len(const struct sk_filter *fp)
extern int sk_filter(struct sock *sk, struct sk_buff *skb);
extern unsigned int sk_run_filter(const struct sk_buff *skb,
const struct sock_filter *filter);
extern int sk_unattached_filter_create(struct sk_filter **pfp,
struct sock_fprog *fprog);
extern void sk_unattached_filter_destroy(struct sk_filter *fp);
extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
extern int sk_detach_filter(struct sock *sk);
extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen);
Expand Down
66 changes: 62 additions & 4 deletions net/core/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,67 @@ void sk_filter_release_rcu(struct rcu_head *rcu)
}
EXPORT_SYMBOL(sk_filter_release_rcu);

static int __sk_prepare_filter(struct sk_filter *fp)
{
int err;

fp->bpf_func = sk_run_filter;

err = sk_chk_filter(fp->insns, fp->len);
if (err)
return err;

bpf_jit_compile(fp);
return 0;
}

/**
* sk_unattached_filter_create - create an unattached filter
* @fprog: the filter program
* @sk: the socket to use
*
* Create a filter independent ofr any socket. We first run some
* sanity checks on it to make sure it does not explode on us later.
* If an error occurs or there is insufficient memory for the filter
* a negative errno code is returned. On success the return is zero.
*/
int sk_unattached_filter_create(struct sk_filter **pfp,
struct sock_fprog *fprog)
{
struct sk_filter *fp;
unsigned int fsize = sizeof(struct sock_filter) * fprog->len;
int err;

/* Make sure new filter is there and in the right amounts. */
if (fprog->filter == NULL)
return -EINVAL;

fp = kmalloc(fsize + sizeof(*fp), GFP_KERNEL);
if (!fp)
return -ENOMEM;
memcpy(fp->insns, fprog->filter, fsize);

atomic_set(&fp->refcnt, 1);
fp->len = fprog->len;

err = __sk_prepare_filter(fp);
if (err)
goto free_mem;

*pfp = fp;
return 0;
free_mem:
kfree(fp);
return err;
}
EXPORT_SYMBOL_GPL(sk_unattached_filter_create);

void sk_unattached_filter_destroy(struct sk_filter *fp)
{
sk_filter_release(fp);
}
EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy);

/**
* sk_attach_filter - attach a socket filter
* @fprog: the filter program
Expand Down Expand Up @@ -617,16 +678,13 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)

atomic_set(&fp->refcnt, 1);
fp->len = fprog->len;
fp->bpf_func = sk_run_filter;

err = sk_chk_filter(fp->insns, fp->len);
err = __sk_prepare_filter(fp);
if (err) {
sk_filter_uncharge(sk, fp);
return err;
}

bpf_jit_compile(fp);

old_fp = rcu_dereference_protected(sk->sk_filter,
sock_owned_by_user(sk));
rcu_assign_pointer(sk->sk_filter, fp);
Expand Down

0 comments on commit 302d663

Please sign in to comment.