Skip to content

Commit 55f3259

Browse files
Al Viroanakryiko
authored andcommitted
bpf: switch maps to CLASS(fd, ...)
Calling conventions for __bpf_map_get() would be more convenient if it left fpdut() on failure to callers. Makes for simpler logics in the callers. Among other things, the proof of memory safety no longer has to rely upon file->private_data never being ERR_PTR(...) for bpffs files. Original calling conventions made it impossible for the caller to tell whether __bpf_map_get() has returned ERR_PTR(-EINVAL) because it has found the file not be a bpf map one (in which case it would've done fdput()) or because it found that ERR_PTR(-EINVAL) in file->private_data of a bpf map file (in which case fdput() would _not_ have been done). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Reviewed-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
1 parent 535ead4 commit 55f3259

File tree

5 files changed

+58
-139
lines changed

5 files changed

+58
-139
lines changed

include/linux/bpf.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2241,7 +2241,16 @@ void __bpf_obj_drop_impl(void *p, const struct btf_record *rec, bool percpu);
22412241

22422242
struct bpf_map *bpf_map_get(u32 ufd);
22432243
struct bpf_map *bpf_map_get_with_uref(u32 ufd);
2244-
struct bpf_map *__bpf_map_get(struct fd f);
2244+
2245+
static inline struct bpf_map *__bpf_map_get(struct fd f)
2246+
{
2247+
if (fd_empty(f))
2248+
return ERR_PTR(-EBADF);
2249+
if (unlikely(fd_file(f)->f_op != &bpf_map_fops))
2250+
return ERR_PTR(-EINVAL);
2251+
return fd_file(f)->private_data;
2252+
}
2253+
22452254
void bpf_map_inc(struct bpf_map *map);
22462255
void bpf_map_inc_with_uref(struct bpf_map *map);
22472256
struct bpf_map *__bpf_map_inc_not_zero(struct bpf_map *map, bool uref);

kernel/bpf/map_in_map.c

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,27 @@ struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
1111
{
1212
struct bpf_map *inner_map, *inner_map_meta;
1313
u32 inner_map_meta_size;
14-
struct fd f;
15-
int ret;
14+
CLASS(fd, f)(inner_map_ufd);
1615

17-
f = fdget(inner_map_ufd);
1816
inner_map = __bpf_map_get(f);
1917
if (IS_ERR(inner_map))
2018
return inner_map;
2119

2220
/* Does not support >1 level map-in-map */
23-
if (inner_map->inner_map_meta) {
24-
ret = -EINVAL;
25-
goto put;
26-
}
21+
if (inner_map->inner_map_meta)
22+
return ERR_PTR(-EINVAL);
2723

28-
if (!inner_map->ops->map_meta_equal) {
29-
ret = -ENOTSUPP;
30-
goto put;
31-
}
24+
if (!inner_map->ops->map_meta_equal)
25+
return ERR_PTR(-ENOTSUPP);
3226

3327
inner_map_meta_size = sizeof(*inner_map_meta);
3428
/* In some cases verifier needs to access beyond just base map. */
3529
if (inner_map->ops == &array_map_ops || inner_map->ops == &percpu_array_map_ops)
3630
inner_map_meta_size = sizeof(struct bpf_array);
3731

3832
inner_map_meta = kzalloc(inner_map_meta_size, GFP_USER);
39-
if (!inner_map_meta) {
40-
ret = -ENOMEM;
41-
goto put;
42-
}
33+
if (!inner_map_meta)
34+
return ERR_PTR(-ENOMEM);
4335

4436
inner_map_meta->map_type = inner_map->map_type;
4537
inner_map_meta->key_size = inner_map->key_size;
@@ -53,8 +45,9 @@ struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
5345
* invalid/empty/valid, but ERR_PTR in case of errors. During
5446
* equality NULL or IS_ERR is equivalent.
5547
*/
56-
ret = PTR_ERR(inner_map_meta->record);
57-
goto free;
48+
struct bpf_map *ret = ERR_CAST(inner_map_meta->record);
49+
kfree(inner_map_meta);
50+
return ret;
5851
}
5952
/* Note: We must use the same BTF, as we also used btf_record_dup above
6053
* which relies on BTF being same for both maps, as some members like
@@ -77,14 +70,7 @@ struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
7770
inner_array_meta->elem_size = inner_array->elem_size;
7871
inner_map_meta->bypass_spec_v1 = inner_map->bypass_spec_v1;
7972
}
80-
81-
fdput(f);
8273
return inner_map_meta;
83-
free:
84-
kfree(inner_map_meta);
85-
put:
86-
fdput(f);
87-
return ERR_PTR(ret);
8874
}
8975

9076
void bpf_map_meta_free(struct bpf_map *map_meta)
@@ -110,9 +96,8 @@ void *bpf_map_fd_get_ptr(struct bpf_map *map,
11096
int ufd)
11197
{
11298
struct bpf_map *inner_map, *inner_map_meta;
113-
struct fd f;
99+
CLASS(fd, f)(ufd);
114100

115-
f = fdget(ufd);
116101
inner_map = __bpf_map_get(f);
117102
if (IS_ERR(inner_map))
118103
return inner_map;
@@ -123,7 +108,6 @@ void *bpf_map_fd_get_ptr(struct bpf_map *map,
123108
else
124109
inner_map = ERR_PTR(-EINVAL);
125110

126-
fdput(f);
127111
return inner_map;
128112
}
129113

0 commit comments

Comments
 (0)