@@ -1613,8 +1613,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);
@@ -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
@@ -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;
@@ -719,6 +719,15 @@ int bpf_get_file_flag(int flags)
offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
sizeof(attr->CMD##_LAST_FIELD)) != NULL
+/* helper macro to extract a field from union bpf_attr while checking that the tail is zero. */
+#define ATTR_FIELD(attr, field) ({ \
+ typeof(&((attr)->field)) __tmp = &((attr)->field); \
+ if (memchr_inv((void *)__tmp + sizeof((attr)->field), 0, sizeof(*(attr)) - sizeof((attr)->field))) { \
+ __tmp = NULL; \
+ } \
+ __tmp; \
+ })
+
/* dst and src must have at least "size" number of bytes.
* Return strlen on success and < 0 on error.
*/
@@ -810,19 +819,19 @@ 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);
+ int numa_node;
struct bpf_map *map;
int f_flags;
int err;
- err = CHECK_ATTR(BPF_MAP_CREATE);
- if (err)
+ if (!attr)
return -EINVAL;
+ numa_node = bpf_map_attr_numa_node((union bpf_attr *)attr); /* Dodgy cast */
+
if (attr->btf_vmlinux_value_type_id) {
if (attr->map_type != BPF_MAP_TYPE_STRUCT_OPS ||
attr->btf_key_type_id || attr->btf_value_type_id)
@@ -4566,7 +4575,7 @@ static int __sys_bpf(int cmd, bpfptr_t uattr, unsigned int size)
switch (cmd) {
case BPF_MAP_CREATE:
- err = map_create(&attr);
+ err = map_create(ATTR_FIELD(&attr, map_create));
break;
case BPF_MAP_LOOKUP_ELEM:
err = map_lookup_elem(&attr);