net: filter: move filter accounting to filter core
This patch basically does two things, i) removes the extern keyword from the include/linux/filter.h file to be more consistent with the rest of Joe's changes, and ii) moves filter accounting into the filter core framework. Filter accounting mainly done through sk_filter_{un,}charge() take care of the case when sockets are being cloned through sk_clone_lock() so that removal of the filter on one socket won't result in eviction as it's still referenced by the other. These functions actually belong to net/core/filter.c and not include/net/sock.h as we want to keep all that in a central place. It's also not in fast-path so uninlining them is fine and even allows us to get rd of sk_filter_release_rcu()'s EXPORT_SYMBOL and a forward declaration. Joint work with Alexei Starovoitov. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Cc: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
a3ea269b8b
Коммит
fbc907f0b1
|
@ -50,28 +50,32 @@ static inline unsigned int sk_filter_size(unsigned int proglen)
|
||||||
#define sk_filter_proglen(fprog) \
|
#define sk_filter_proglen(fprog) \
|
||||||
(fprog->len * sizeof(fprog->filter[0]))
|
(fprog->len * sizeof(fprog->filter[0]))
|
||||||
|
|
||||||
extern int sk_filter(struct sock *sk, struct sk_buff *skb);
|
int sk_filter(struct sock *sk, struct sk_buff *skb);
|
||||||
extern unsigned int sk_run_filter(const struct sk_buff *skb,
|
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,
|
int sk_unattached_filter_create(struct sk_filter **pfp,
|
||||||
struct sock_fprog *fprog);
|
struct sock_fprog *fprog);
|
||||||
extern void sk_unattached_filter_destroy(struct sk_filter *fp);
|
void sk_unattached_filter_destroy(struct sk_filter *fp);
|
||||||
|
|
||||||
extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
|
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
|
||||||
extern int sk_detach_filter(struct sock *sk);
|
int sk_detach_filter(struct sock *sk);
|
||||||
|
|
||||||
extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen);
|
int sk_chk_filter(struct sock_filter *filter, unsigned int flen);
|
||||||
extern int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, unsigned len);
|
int sk_get_filter(struct sock *sk, struct sock_filter __user *filter,
|
||||||
extern void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to);
|
unsigned int len);
|
||||||
|
void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to);
|
||||||
|
|
||||||
|
void sk_filter_charge(struct sock *sk, struct sk_filter *fp);
|
||||||
|
void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp);
|
||||||
|
|
||||||
#ifdef CONFIG_BPF_JIT
|
#ifdef CONFIG_BPF_JIT
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <linux/printk.h>
|
#include <linux/printk.h>
|
||||||
|
|
||||||
extern void bpf_jit_compile(struct sk_filter *fp);
|
void bpf_jit_compile(struct sk_filter *fp);
|
||||||
extern void bpf_jit_free(struct sk_filter *fp);
|
void bpf_jit_free(struct sk_filter *fp);
|
||||||
|
|
||||||
static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
|
static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
|
||||||
u32 pass, void *image)
|
u32 pass, void *image)
|
||||||
|
|
|
@ -1621,33 +1621,6 @@ void sk_common_release(struct sock *sk);
|
||||||
/* Initialise core socket variables */
|
/* Initialise core socket variables */
|
||||||
void sock_init_data(struct socket *sock, struct sock *sk);
|
void sock_init_data(struct socket *sock, struct sock *sk);
|
||||||
|
|
||||||
void sk_filter_release_rcu(struct rcu_head *rcu);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sk_filter_release - release a socket filter
|
|
||||||
* @fp: filter to remove
|
|
||||||
*
|
|
||||||
* Remove a filter from a socket and release its resources.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static inline void sk_filter_release(struct sk_filter *fp)
|
|
||||||
{
|
|
||||||
if (atomic_dec_and_test(&fp->refcnt))
|
|
||||||
call_rcu(&fp->rcu, sk_filter_release_rcu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
|
|
||||||
{
|
|
||||||
atomic_sub(sk_filter_size(fp->len), &sk->sk_omem_alloc);
|
|
||||||
sk_filter_release(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
|
|
||||||
{
|
|
||||||
atomic_inc(&fp->refcnt);
|
|
||||||
atomic_add(sk_filter_size(fp->len), &sk->sk_omem_alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Socket reference counting postulates.
|
* Socket reference counting postulates.
|
||||||
*
|
*
|
||||||
|
|
|
@ -664,14 +664,37 @@ static void sk_release_orig_filter(struct sk_filter *fp)
|
||||||
* sk_filter_release_rcu - Release a socket filter by rcu_head
|
* sk_filter_release_rcu - Release a socket filter by rcu_head
|
||||||
* @rcu: rcu_head that contains the sk_filter to free
|
* @rcu: rcu_head that contains the sk_filter to free
|
||||||
*/
|
*/
|
||||||
void sk_filter_release_rcu(struct rcu_head *rcu)
|
static void sk_filter_release_rcu(struct rcu_head *rcu)
|
||||||
{
|
{
|
||||||
struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
|
struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
|
||||||
|
|
||||||
sk_release_orig_filter(fp);
|
sk_release_orig_filter(fp);
|
||||||
bpf_jit_free(fp);
|
bpf_jit_free(fp);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sk_filter_release_rcu);
|
|
||||||
|
/**
|
||||||
|
* sk_filter_release - release a socket filter
|
||||||
|
* @fp: filter to remove
|
||||||
|
*
|
||||||
|
* Remove a filter from a socket and release its resources.
|
||||||
|
*/
|
||||||
|
static void sk_filter_release(struct sk_filter *fp)
|
||||||
|
{
|
||||||
|
if (atomic_dec_and_test(&fp->refcnt))
|
||||||
|
call_rcu(&fp->rcu, sk_filter_release_rcu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
|
||||||
|
{
|
||||||
|
atomic_sub(sk_filter_size(fp->len), &sk->sk_omem_alloc);
|
||||||
|
sk_filter_release(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
|
||||||
|
{
|
||||||
|
atomic_inc(&fp->refcnt);
|
||||||
|
atomic_add(sk_filter_size(fp->len), &sk->sk_omem_alloc);
|
||||||
|
}
|
||||||
|
|
||||||
static int __sk_prepare_filter(struct sk_filter *fp)
|
static int __sk_prepare_filter(struct sk_filter *fp)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче