bpf: add map_alloc_check callback
authorJakub Kicinski <jakub.kicinski@netronome.com>
Fri, 12 Jan 2018 04:29:03 +0000 (20:29 -0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Sun, 14 Jan 2018 22:36:29 +0000 (23:36 +0100)
.map_alloc callbacks contain a number of checks validating user-
-provided map attributes against constraints of a particular map
type.  For offloaded maps we will need to check map attributes
without actually allocating any memory on the host.  Add a new
callback for validating attributes before any memory is allocated.
This callback can be selectively implemented by map types for
sharing code with offloads, or simply to separate the logical
steps of validation and allocation.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
include/linux/bpf.h
kernel/bpf/syscall.c

index 3496977203a3548e27de190b531630d713aad7eb..263598619f908f9fb04d939f51d3ce26ebb15743 100644 (file)
@@ -25,6 +25,7 @@ struct bpf_map;
 /* map is generic key/value storage optionally accesible by eBPF programs */
 struct bpf_map_ops {
        /* funcs callable from userspace (via syscall) */
+       int (*map_alloc_check)(union bpf_attr *attr);
        struct bpf_map *(*map_alloc)(union bpf_attr *attr);
        void (*map_release)(struct bpf_map *map, struct file *map_file);
        void (*map_free)(struct bpf_map *map);
index 2bac0dc8babaa81c6134d6cfe0f8a23db6f81541..c0ac03a04880f85b2010dfc92381c113cf7855ed 100644 (file)
@@ -96,16 +96,25 @@ static int check_uarg_tail_zero(void __user *uaddr,
 
 static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
 {
+       const struct bpf_map_ops *ops;
        struct bpf_map *map;
+       int err;
 
-       if (attr->map_type >= ARRAY_SIZE(bpf_map_types) ||
-           !bpf_map_types[attr->map_type])
+       if (attr->map_type >= ARRAY_SIZE(bpf_map_types))
+               return ERR_PTR(-EINVAL);
+       ops = bpf_map_types[attr->map_type];
+       if (!ops)
                return ERR_PTR(-EINVAL);
 
-       map = bpf_map_types[attr->map_type]->map_alloc(attr);
+       if (ops->map_alloc_check) {
+               err = ops->map_alloc_check(attr);
+               if (err)
+                       return ERR_PTR(err);
+       }
+       map = ops->map_alloc(attr);
        if (IS_ERR(map))
                return map;
-       map->ops = bpf_map_types[attr->map_type];
+       map->ops = ops;
        map->map_type = attr->map_type;
        return map;
 }