diff options
| author | Daniel Borkmann <dborkman@redhat.com> | 2014-03-28 13:58:19 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-03-31 00:45:09 -0400 |
| commit | a3ea269b8bcdbb0c5fa2fd449a436e7987446975 (patch) | |
| tree | 9e118e381c14f9a065cc4136be2a9bf6e5257dfb /include/linux | |
| parent | f8bbbfc3b97f4c7a6c7c23185e520b22bfc3a21d (diff) | |
net: filter: keep original BPF program around
In order to open up the possibility to internally transform a BPF program
into an alternative and possibly non-trivial reversible representation, we
need to keep the original BPF program around, so that it can be passed back
to user space w/o the need of a complex decoder.
The reason for that use case resides in commit a8fc92778080 ("sk-filter:
Add ability to get socket filter program (v2)"), that is, the ability
to retrieve the currently attached BPF filter from a given socket used
mainly by the checkpoint-restore project, for example.
Therefore, we add two helpers sk_{store,release}_orig_filter for taking
care of that. In the sk_unattached_filter_create() case, there's no such
possibility/requirement to retrieve a loaded BPF program. Therefore, we
can spare us the work in that case.
This approach will simplify and slightly speed up both, sk_get_filter()
and sock_diag_put_filterinfo() handlers as we won't need to successively
decode filters anymore through sk_decode_filter(). As we still need
sk_decode_filter() later on, we're keeping it around.
Joint work with Alexei Starovoitov.
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/filter.h | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/include/linux/filter.h b/include/linux/filter.h index e65e23087367..93a9792e27bc 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h | |||
| @@ -19,14 +19,19 @@ struct compat_sock_fprog { | |||
| 19 | }; | 19 | }; |
| 20 | #endif | 20 | #endif |
| 21 | 21 | ||
| 22 | struct sock_fprog_kern { | ||
| 23 | u16 len; | ||
| 24 | struct sock_filter *filter; | ||
| 25 | }; | ||
| 26 | |||
| 22 | struct sk_buff; | 27 | struct sk_buff; |
| 23 | struct sock; | 28 | struct sock; |
| 24 | 29 | ||
| 25 | struct sk_filter | 30 | struct sk_filter { |
| 26 | { | ||
| 27 | atomic_t refcnt; | 31 | atomic_t refcnt; |
| 28 | u32 jited:1, /* Is our filter JIT'ed? */ | 32 | u32 jited:1, /* Is our filter JIT'ed? */ |
| 29 | len:31; /* Number of filter blocks */ | 33 | len:31; /* Number of filter blocks */ |
| 34 | struct sock_fprog_kern *orig_prog; /* Original BPF program */ | ||
| 30 | struct rcu_head rcu; | 35 | struct rcu_head rcu; |
| 31 | unsigned int (*bpf_func)(const struct sk_buff *skb, | 36 | unsigned int (*bpf_func)(const struct sk_buff *skb, |
| 32 | const struct sock_filter *filter); | 37 | const struct sock_filter *filter); |
| @@ -42,14 +47,20 @@ static inline unsigned int sk_filter_size(unsigned int proglen) | |||
| 42 | offsetof(struct sk_filter, insns[proglen])); | 47 | offsetof(struct sk_filter, insns[proglen])); |
| 43 | } | 48 | } |
| 44 | 49 | ||
| 50 | #define sk_filter_proglen(fprog) \ | ||
| 51 | (fprog->len * sizeof(fprog->filter[0])) | ||
| 52 | |||
| 45 | extern int sk_filter(struct sock *sk, struct sk_buff *skb); | 53 | extern int sk_filter(struct sock *sk, struct sk_buff *skb); |
| 46 | extern unsigned int sk_run_filter(const struct sk_buff *skb, | 54 | extern unsigned int sk_run_filter(const struct sk_buff *skb, |
| 47 | const struct sock_filter *filter); | 55 | const struct sock_filter *filter); |
| 56 | |||
| 48 | extern int sk_unattached_filter_create(struct sk_filter **pfp, | 57 | extern int sk_unattached_filter_create(struct sk_filter **pfp, |
| 49 | struct sock_fprog *fprog); | 58 | struct sock_fprog *fprog); |
| 50 | extern void sk_unattached_filter_destroy(struct sk_filter *fp); | 59 | extern void sk_unattached_filter_destroy(struct sk_filter *fp); |
| 60 | |||
| 51 | extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); | 61 | extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); |
| 52 | extern int sk_detach_filter(struct sock *sk); | 62 | extern int sk_detach_filter(struct sock *sk); |
| 63 | |||
| 53 | extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen); | 64 | extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen); |
| 54 | extern int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, unsigned len); | 65 | extern int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, unsigned len); |
| 55 | extern void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to); | 66 | extern void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to); |
