1 /* Copyright (c) 2017 Facebook
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
7 #include <linux/slab.h>
10 #include "map_in_map.h"
12 struct bpf_map
*bpf_map_meta_alloc(int inner_map_ufd
)
14 struct bpf_map
*inner_map
, *inner_map_meta
;
17 f
= fdget(inner_map_ufd
);
18 inner_map
= __bpf_map_get(f
);
19 if (IS_ERR(inner_map
))
22 /* prog_array->owner_prog_type and owner_jited
23 * is a runtime binding. Doing static check alone
24 * in the verifier is not enough.
26 if (inner_map
->map_type
== BPF_MAP_TYPE_PROG_ARRAY
||
27 inner_map
->map_type
== BPF_MAP_TYPE_CGROUP_STORAGE
) {
29 return ERR_PTR(-ENOTSUPP
);
32 /* Does not support >1 level map-in-map */
33 if (inner_map
->inner_map_meta
) {
35 return ERR_PTR(-EINVAL
);
38 inner_map_meta
= kzalloc(sizeof(*inner_map_meta
), GFP_USER
);
39 if (!inner_map_meta
) {
41 return ERR_PTR(-ENOMEM
);
44 inner_map_meta
->map_type
= inner_map
->map_type
;
45 inner_map_meta
->key_size
= inner_map
->key_size
;
46 inner_map_meta
->value_size
= inner_map
->value_size
;
47 inner_map_meta
->map_flags
= inner_map
->map_flags
;
48 inner_map_meta
->ops
= inner_map
->ops
;
49 inner_map_meta
->max_entries
= inner_map
->max_entries
;
52 return inner_map_meta
;
55 void bpf_map_meta_free(struct bpf_map
*map_meta
)
60 bool bpf_map_meta_equal(const struct bpf_map
*meta0
,
61 const struct bpf_map
*meta1
)
63 /* No need to compare ops because it is covered by map_type */
64 return meta0
->map_type
== meta1
->map_type
&&
65 meta0
->key_size
== meta1
->key_size
&&
66 meta0
->value_size
== meta1
->value_size
&&
67 meta0
->map_flags
== meta1
->map_flags
&&
68 meta0
->max_entries
== meta1
->max_entries
;
71 void *bpf_map_fd_get_ptr(struct bpf_map
*map
,
72 struct file
*map_file
/* not used */,
75 struct bpf_map
*inner_map
;
79 inner_map
= __bpf_map_get(f
);
80 if (IS_ERR(inner_map
))
83 if (bpf_map_meta_equal(map
->inner_map_meta
, inner_map
))
84 inner_map
= bpf_map_inc(inner_map
, false);
86 inner_map
= ERR_PTR(-EINVAL
);
92 void bpf_map_fd_put_ptr(void *ptr
)
94 /* ptr->ops->map_free() has to go through one
95 * rcu grace period by itself.
100 u32
bpf_map_fd_sys_lookup_elem(void *ptr
)
102 return ((struct bpf_map
*)ptr
)->id
;