]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - include/linux/filter.h
Merge remote-tracking branch 'audit/next'
[karo-tx-linux.git] / include / linux / filter.h
index fa2cab985e577681c801f8861c299ad938ec9ffc..4165e9ac9e36aa82735f40a790e25e0b7218c95b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/printk.h>
 #include <linux/workqueue.h>
 #include <linux/sched.h>
+#include <net/sch_generic.h>
 
 #include <asm/cacheflush.h>
 
@@ -302,10 +303,6 @@ struct bpf_prog_aux;
        bpf_size;                                               \
 })
 
-/* Macro to invoke filter function. */
-#define SK_RUN_FILTER(filter, ctx) \
-       (*filter->prog->bpf_func)(ctx, filter->prog->insnsi)
-
 #ifdef CONFIG_COMPAT
 /* A struct sock_filter is architecture independent. */
 struct compat_sock_fprog {
@@ -326,8 +323,12 @@ struct bpf_binary_header {
 
 struct bpf_prog {
        u16                     pages;          /* Number of allocated pages */
-       bool                    jited;          /* Is our filter JIT'ed? */
-       bool                    gpl_compatible; /* Is our filter GPL compatible? */
+       kmemcheck_bitfield_begin(meta);
+       u16                     jited:1,        /* Is our filter JIT'ed? */
+                               gpl_compatible:1, /* Is filter GPL compatible? */
+                               cb_access:1,    /* Is control block accessed? */
+                               dst_needed:1;   /* Do we need dst entry? */
+       kmemcheck_bitfield_end(meta);
        u32                     len;            /* Number of filter blocks */
        enum bpf_prog_type      type;           /* Type of BPF program */
        struct bpf_prog_aux     *aux;           /* Auxiliary fields */
@@ -349,6 +350,39 @@ struct sk_filter {
 
 #define BPF_PROG_RUN(filter, ctx)  (*filter->bpf_func)(ctx, filter->insnsi)
 
+static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
+                                      struct sk_buff *skb)
+{
+       u8 *cb_data = qdisc_skb_cb(skb)->data;
+       u8 saved_cb[QDISC_CB_PRIV_LEN];
+       u32 res;
+
+       BUILD_BUG_ON(FIELD_SIZEOF(struct __sk_buff, cb) !=
+                    QDISC_CB_PRIV_LEN);
+
+       if (unlikely(prog->cb_access)) {
+               memcpy(saved_cb, cb_data, sizeof(saved_cb));
+               memset(cb_data, 0, sizeof(saved_cb));
+       }
+
+       res = BPF_PROG_RUN(prog, skb);
+
+       if (unlikely(prog->cb_access))
+               memcpy(cb_data, saved_cb, sizeof(saved_cb));
+
+       return res;
+}
+
+static inline u32 bpf_prog_run_clear_cb(const struct bpf_prog *prog,
+                                       struct sk_buff *skb)
+{
+       u8 *cb_data = qdisc_skb_cb(skb)->data;
+
+       if (unlikely(prog->cb_access))
+               memset(cb_data, 0, QDISC_CB_PRIV_LEN);
+       return BPF_PROG_RUN(prog, skb);
+}
+
 static inline unsigned int bpf_prog_size(unsigned int proglen)
 {
        return max(sizeof(struct bpf_prog),
@@ -408,7 +442,7 @@ typedef int (*bpf_aux_classic_check_t)(struct sock_filter *filter,
 
 int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog);
 int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog,
-                             bpf_aux_classic_check_t trans);
+                             bpf_aux_classic_check_t trans, bool save_orig);
 void bpf_prog_destroy(struct bpf_prog *fp);
 
 int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);