Commit 302d6637 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller

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: default avatarJiri Pirko <jpirko@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fca231b2
...@@ -153,6 +153,9 @@ static inline unsigned int sk_filter_len(const struct sk_filter *fp) ...@@ -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 int sk_filter(struct sock *sk, struct sk_buff *skb);
extern unsigned int sk_run_filter(const struct sk_buff *skb, extern unsigned int sk_run_filter(const struct sk_buff *skb,
const struct sock_filter *filter); 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_attach_filter(struct sock_fprog *fprog, struct sock *sk);
extern int sk_detach_filter(struct sock *sk); extern int sk_detach_filter(struct sock *sk);
extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen); extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen);
......
...@@ -587,6 +587,67 @@ void sk_filter_release_rcu(struct rcu_head *rcu) ...@@ -587,6 +587,67 @@ void sk_filter_release_rcu(struct rcu_head *rcu)
} }
EXPORT_SYMBOL(sk_filter_release_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 * sk_attach_filter - attach a socket filter
* @fprog: the filter program * @fprog: the filter program
...@@ -617,16 +678,13 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) ...@@ -617,16 +678,13 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
atomic_set(&fp->refcnt, 1); atomic_set(&fp->refcnt, 1);
fp->len = fprog->len; 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) { if (err) {
sk_filter_uncharge(sk, fp); sk_filter_uncharge(sk, fp);
return err; return err;
} }
bpf_jit_compile(fp);
old_fp = rcu_dereference_protected(sk->sk_filter, old_fp = rcu_dereference_protected(sk->sk_filter,
sock_owned_by_user(sk)); sock_owned_by_user(sk));
rcu_assign_pointer(sk->sk_filter, fp); rcu_assign_pointer(sk->sk_filter, fp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment