ebpf: move read-only fields to bpf_prog and shrink bpf_prog_aux
authorDaniel Borkmann <daniel@iogearbox.net>
Sun, 1 Mar 2015 11:31:47 +0000 (12:31 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 1 Mar 2015 19:05:19 +0000 (14:05 -0500)
is_gpl_compatible and prog_type should be moved directly into bpf_prog
as they stay immutable during bpf_prog's lifetime, are core attributes
and they can be locked as read-only later on via bpf_prog_select_runtime().

With a bit of rearranging, this also allows us to shrink bpf_prog_aux
to exactly 1 cacheline.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/bpf.h
include/linux/filter.h
kernel/bpf/syscall.c
kernel/bpf/verifier.c
net/core/filter.c

index 9c45814..a1a7ff2 100644 (file)
@@ -117,11 +117,9 @@ struct bpf_prog;
 
 struct bpf_prog_aux {
        atomic_t refcnt;
-       bool is_gpl_compatible;
-       enum bpf_prog_type prog_type;
+       u32 used_map_cnt;
        const struct bpf_verifier_ops *ops;
        struct bpf_map **used_maps;
-       u32 used_map_cnt;
        struct bpf_prog *prog;
        struct work_struct work;
 };
index 5e3863d..9ee8c67 100644 (file)
@@ -308,9 +308,11 @@ 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? */
        u32                     len;            /* Number of filter blocks */
-       struct sock_fprog_kern  *orig_prog;     /* Original BPF program */
+       enum bpf_prog_type      type;           /* Type of BPF program */
        struct bpf_prog_aux     *aux;           /* Auxiliary fields */
+       struct sock_fprog_kern  *orig_prog;     /* Original BPF program */
        unsigned int            (*bpf_func)(const struct sk_buff *skb,
                                            const struct bpf_insn *filter);
        /* Instructions for interpreter */
index 536edc2..0d69449 100644 (file)
@@ -354,10 +354,11 @@ static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
        list_for_each_entry(tl, &bpf_prog_types, list_node) {
                if (tl->type == type) {
                        prog->aux->ops = tl->ops;
-                       prog->aux->prog_type = type;
+                       prog->type = type;
                        return 0;
                }
        }
+
        return -EINVAL;
 }
 
@@ -508,7 +509,7 @@ static int bpf_prog_load(union bpf_attr *attr)
        prog->jited = false;
 
        atomic_set(&prog->aux->refcnt, 1);
-       prog->aux->is_gpl_compatible = is_gpl;
+       prog->gpl_compatible = is_gpl;
 
        /* find program type: socket_filter vs tracing_filter */
        err = find_prog_type(type, prog);
@@ -517,7 +518,6 @@ static int bpf_prog_load(union bpf_attr *attr)
 
        /* run eBPF verifier */
        err = bpf_check(prog, attr);
-
        if (err < 0)
                goto free_used_maps;
 
@@ -528,7 +528,6 @@ static int bpf_prog_load(union bpf_attr *attr)
        bpf_prog_select_runtime(prog);
 
        err = anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog, O_RDWR | O_CLOEXEC);
-
        if (err < 0)
                /* failed to allocate fd */
                goto free_used_maps;
index 594d341..bdf4192 100644 (file)
@@ -852,7 +852,7 @@ static int check_call(struct verifier_env *env, int func_id)
        }
 
        /* eBPF programs must be GPL compatible to use GPL-ed functions */
-       if (!env->prog->aux->is_gpl_compatible && fn->gpl_only) {
+       if (!env->prog->gpl_compatible && fn->gpl_only) {
                verbose("cannot call GPL only function from proprietary program\n");
                return -EINVAL;
        }
@@ -1205,7 +1205,7 @@ static int check_ld_abs(struct verifier_env *env, struct bpf_insn *insn)
        struct reg_state *reg;
        int i, err;
 
-       if (!may_access_skb(env->prog->aux->prog_type)) {
+       if (!may_access_skb(env->prog->type)) {
                verbose("BPF_LD_ABS|IND instructions not allowed for this program type\n");
                return -EINVAL;
        }
index 514d408..ff000cb 100644 (file)
@@ -814,7 +814,7 @@ static void bpf_release_orig_filter(struct bpf_prog *fp)
 
 static void __bpf_prog_release(struct bpf_prog *prog)
 {
-       if (prog->aux->prog_type == BPF_PROG_TYPE_SOCKET_FILTER) {
+       if (prog->type == BPF_PROG_TYPE_SOCKET_FILTER) {
                bpf_prog_put(prog);
        } else {
                bpf_release_orig_filter(prog);
@@ -1105,7 +1105,7 @@ int sk_attach_bpf(u32 ufd, struct sock *sk)
        if (IS_ERR(prog))
                return PTR_ERR(prog);
 
-       if (prog->aux->prog_type != BPF_PROG_TYPE_SOCKET_FILTER) {
+       if (prog->type != BPF_PROG_TYPE_SOCKET_FILTER) {
                bpf_prog_put(prog);
                return -EINVAL;
        }