This patch adds a jited flag into sk_filter struct in order to indicate whether a filter is currently jited or not. The size of sk_filter is not being expanded as the 32 bit 'len' member allows upper bits to be reused since a filter can currently only grow as large as BPF_MAXINSNS. Therefore, there's enough room also for other in future needed flags to reuse 'len' field if necessary. The jited flag also allows for having alternative interpreter functions running as currently, we can only detect jit compiled filters by testing fp->bpf_func to not equal the address of sk_run_filter(). Joint work with Alexei Starovoitov. Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Cc: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
161 lines
3.6 KiB
C
161 lines
3.6 KiB
C
/*
|
|
* Linux Socket Filter Data Structures
|
|
*/
|
|
#ifndef __LINUX_FILTER_H__
|
|
#define __LINUX_FILTER_H__
|
|
|
|
#include <linux/atomic.h>
|
|
#include <linux/compat.h>
|
|
#include <linux/workqueue.h>
|
|
#include <uapi/linux/filter.h>
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
/*
|
|
* A struct sock_filter is architecture independent.
|
|
*/
|
|
struct compat_sock_fprog {
|
|
u16 len;
|
|
compat_uptr_t filter; /* struct sock_filter * */
|
|
};
|
|
#endif
|
|
|
|
struct sk_buff;
|
|
struct sock;
|
|
|
|
struct sk_filter
|
|
{
|
|
atomic_t refcnt;
|
|
u32 jited:1, /* Is our filter JIT'ed? */
|
|
len:31; /* Number of filter blocks */
|
|
struct rcu_head rcu;
|
|
unsigned int (*bpf_func)(const struct sk_buff *skb,
|
|
const struct sock_filter *filter);
|
|
union {
|
|
struct sock_filter insns[0];
|
|
struct work_struct work;
|
|
};
|
|
};
|
|
|
|
static inline unsigned int sk_filter_size(unsigned int proglen)
|
|
{
|
|
return max(sizeof(struct sk_filter),
|
|
offsetof(struct sk_filter, insns[proglen]));
|
|
}
|
|
|
|
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);
|
|
extern int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, unsigned len);
|
|
extern void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to);
|
|
|
|
#ifdef CONFIG_BPF_JIT
|
|
#include <stdarg.h>
|
|
#include <linux/linkage.h>
|
|
#include <linux/printk.h>
|
|
|
|
extern void bpf_jit_compile(struct sk_filter *fp);
|
|
extern void bpf_jit_free(struct sk_filter *fp);
|
|
|
|
static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
|
|
u32 pass, void *image)
|
|
{
|
|
pr_err("flen=%u proglen=%u pass=%u image=%pK\n",
|
|
flen, proglen, pass, image);
|
|
if (image)
|
|
print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_OFFSET,
|
|
16, 1, image, proglen, false);
|
|
}
|
|
#define SK_RUN_FILTER(FILTER, SKB) (*FILTER->bpf_func)(SKB, FILTER->insns)
|
|
#else
|
|
#include <linux/slab.h>
|
|
static inline void bpf_jit_compile(struct sk_filter *fp)
|
|
{
|
|
}
|
|
static inline void bpf_jit_free(struct sk_filter *fp)
|
|
{
|
|
kfree(fp);
|
|
}
|
|
#define SK_RUN_FILTER(FILTER, SKB) sk_run_filter(SKB, FILTER->insns)
|
|
#endif
|
|
|
|
static inline int bpf_tell_extensions(void)
|
|
{
|
|
return SKF_AD_MAX;
|
|
}
|
|
|
|
enum {
|
|
BPF_S_RET_K = 1,
|
|
BPF_S_RET_A,
|
|
BPF_S_ALU_ADD_K,
|
|
BPF_S_ALU_ADD_X,
|
|
BPF_S_ALU_SUB_K,
|
|
BPF_S_ALU_SUB_X,
|
|
BPF_S_ALU_MUL_K,
|
|
BPF_S_ALU_MUL_X,
|
|
BPF_S_ALU_DIV_X,
|
|
BPF_S_ALU_MOD_K,
|
|
BPF_S_ALU_MOD_X,
|
|
BPF_S_ALU_AND_K,
|
|
BPF_S_ALU_AND_X,
|
|
BPF_S_ALU_OR_K,
|
|
BPF_S_ALU_OR_X,
|
|
BPF_S_ALU_XOR_K,
|
|
BPF_S_ALU_XOR_X,
|
|
BPF_S_ALU_LSH_K,
|
|
BPF_S_ALU_LSH_X,
|
|
BPF_S_ALU_RSH_K,
|
|
BPF_S_ALU_RSH_X,
|
|
BPF_S_ALU_NEG,
|
|
BPF_S_LD_W_ABS,
|
|
BPF_S_LD_H_ABS,
|
|
BPF_S_LD_B_ABS,
|
|
BPF_S_LD_W_LEN,
|
|
BPF_S_LD_W_IND,
|
|
BPF_S_LD_H_IND,
|
|
BPF_S_LD_B_IND,
|
|
BPF_S_LD_IMM,
|
|
BPF_S_LDX_W_LEN,
|
|
BPF_S_LDX_B_MSH,
|
|
BPF_S_LDX_IMM,
|
|
BPF_S_MISC_TAX,
|
|
BPF_S_MISC_TXA,
|
|
BPF_S_ALU_DIV_K,
|
|
BPF_S_LD_MEM,
|
|
BPF_S_LDX_MEM,
|
|
BPF_S_ST,
|
|
BPF_S_STX,
|
|
BPF_S_JMP_JA,
|
|
BPF_S_JMP_JEQ_K,
|
|
BPF_S_JMP_JEQ_X,
|
|
BPF_S_JMP_JGE_K,
|
|
BPF_S_JMP_JGE_X,
|
|
BPF_S_JMP_JGT_K,
|
|
BPF_S_JMP_JGT_X,
|
|
BPF_S_JMP_JSET_K,
|
|
BPF_S_JMP_JSET_X,
|
|
/* Ancillary data */
|
|
BPF_S_ANC_PROTOCOL,
|
|
BPF_S_ANC_PKTTYPE,
|
|
BPF_S_ANC_IFINDEX,
|
|
BPF_S_ANC_NLATTR,
|
|
BPF_S_ANC_NLATTR_NEST,
|
|
BPF_S_ANC_MARK,
|
|
BPF_S_ANC_QUEUE,
|
|
BPF_S_ANC_HATYPE,
|
|
BPF_S_ANC_RXHASH,
|
|
BPF_S_ANC_CPU,
|
|
BPF_S_ANC_ALU_XOR_X,
|
|
BPF_S_ANC_SECCOMP_LD_W,
|
|
BPF_S_ANC_VLAN_TAG,
|
|
BPF_S_ANC_VLAN_TAG_PRESENT,
|
|
BPF_S_ANC_PAY_OFFSET,
|
|
};
|
|
|
|
#endif /* __LINUX_FILTER_H__ */
|