--- include/linux/bpf.h | 4 +-- include/uapi/linux/bpf.h | 62 ++++++++++++++++++++++++++-------------- kernel/bpf/syscall.c | 15 ++++------ 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index d604c8251d88..80c6dfdbd9d9 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1617,8 +1617,8 @@ int cpu_map_generic_redirect(struct bpf_cpu_map_entry *rcpu, /* Return map's numa specified by userspace */ static inline int bpf_map_attr_numa_node(const union bpf_attr *attr) { - return (attr->map_flags & BPF_F_NUMA_NODE) ? - attr->numa_node : NUMA_NO_NODE; + return (attr->map_create.map_flags & BPF_F_NUMA_NODE) ? + attr->map_create.numa_node : NUMA_NO_NODE; } struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type type); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index c1b1ce0e26a6..f1c163778d7a 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1271,29 +1271,31 @@ enum { BPF_OBJ_NAME_LEN = 16U, }; +struct bpf_map_create_attr { + __u32 map_type; /* one of enum bpf_map_type */ + __u32 key_size; /* size of key in bytes */ + __u32 value_size; /* size of value in bytes */ + __u32 max_entries; /* max number of entries in a map */ + __u32 map_flags; /* BPF_MAP_CREATE related + * flags defined above. + */ + __u32 inner_map_fd; /* fd pointing to the inner map */ + __u32 numa_node; /* numa node (effective only if + * BPF_F_NUMA_NODE is set). + */ + char map_name[BPF_OBJ_NAME_LEN]; + __u32 map_ifindex; /* ifindex of netdev to create on */ + __u32 btf_fd; /* fd pointing to a BTF type data */ + __u32 btf_key_type_id; /* BTF type_id of the key */ + __u32 btf_value_type_id; /* BTF type_id of the value */ + __u32 btf_vmlinux_value_type_id; /* BTF type_id of a kernel- + * struct stored as the + * map value + */ +}; + union bpf_attr { - struct { /* anonymous struct used by BPF_MAP_CREATE command */ - __u32 map_type; /* one of enum bpf_map_type */ - __u32 key_size; /* size of key in bytes */ - __u32 value_size; /* size of value in bytes */ - __u32 max_entries; /* max number of entries in a map */ - __u32 map_flags; /* BPF_MAP_CREATE related - * flags defined above. - */ - __u32 inner_map_fd; /* fd pointing to the inner map */ - __u32 numa_node; /* numa node (effective only if - * BPF_F_NUMA_NODE is set). - */ - char map_name[BPF_OBJ_NAME_LEN]; - __u32 map_ifindex; /* ifindex of netdev to create on */ - __u32 btf_fd; /* fd pointing to a BTF type data */ - __u32 btf_key_type_id; /* BTF type_id of the key */ - __u32 btf_value_type_id; /* BTF type_id of the value */ - __u32 btf_vmlinux_value_type_id;/* BTF type_id of a kernel- - * struct stored as the - * map value - */ - }; + struct bpf_map_create_attr map_create; struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ __u32 map_fd; @@ -1506,6 +1508,22 @@ union bpf_attr { __u32 flags; /* extra flags */ } prog_bind_map; + /* DEPRECATED: these are kept for compatibility purposes. */ + struct { /* anonymous struct used by BPF_MAP_CREATE command */ + __u32 map_type; + __u32 key_size; + __u32 value_size; + __u32 max_entries; + __u32 map_flags; + __u32 inner_map_fd; + __u32 numa_node; + char map_name[BPF_OBJ_NAME_LEN]; + __u32 map_ifindex; + __u32 btf_fd; + __u32 btf_key_type_id; + __u32 btf_value_type_id; + __u32 btf_vmlinux_value_type_id; + }; } __attribute__((aligned(8))); /* The description below is an attempt at providing documentation to eBPF diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 14c2cfe6ef38..337fbd2f1874 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -103,7 +103,7 @@ const struct bpf_map_ops bpf_map_offload_ops = { .map_check_btf = map_check_no_btf, }; -static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) +static struct bpf_map *find_and_alloc_map(struct bpf_map_create_attr *attr) { const struct bpf_map_ops *ops; u32 type = attr->map_type; @@ -118,13 +118,13 @@ static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) return ERR_PTR(-EINVAL); if (ops->map_alloc_check) { - err = ops->map_alloc_check(attr); + err = ops->map_alloc_check((union bpf_attr *)attr); /* XXX: Dodgy cast */ if (err) return ERR_PTR(err); } if (attr->map_ifindex) ops = &bpf_map_offload_ops; - map = ops->map_alloc(attr); + map = ops->map_alloc((union bpf_attr *)attr); /* XXX: Dodgy cast */ if (IS_ERR(map)) return map; map->ops = ops; @@ -814,18 +814,14 @@ static int map_check_btf(struct bpf_map *map, const struct btf *btf, return ret; } -#define BPF_MAP_CREATE_LAST_FIELD btf_vmlinux_value_type_id /* called via syscall */ -static int map_create(union bpf_attr *attr) +static int map_create(struct bpf_map_create_attr *attr) { int numa_node = bpf_map_attr_numa_node(attr); struct bpf_map *map; int f_flags; int err; - err = CHECK_ATTR(BPF_MAP_CREATE); - if (err) - return -EINVAL; if (attr->btf_vmlinux_value_type_id) { if (attr->map_type != BPF_MAP_TYPE_STRUCT_OPS || @@ -4570,7 +4566,8 @@ static int __sys_bpf(int cmd, bpfptr_t uattr, unsigned int size) switch (cmd) { case BPF_MAP_CREATE: - err = map_create(&attr); + err = CHECK_ATTR_TAIL(&attr, map_create); + err = err ?: map_create(&attr.map_create); break; case BPF_MAP_LOOKUP_ELEM: err = map_lookup_elem(&attr); -- 2.30.2