Skip to content

Commit ba6b8de

Browse files
jrfastabborkmann
authored andcommitted
bpf: sockmap, map_release does not hold refcnt for pinned maps
Relying on map_release hook to decrement the reference counts when a map is removed only works if the map is not being pinned. In the pinned case the ref is decremented immediately and the BPF programs released. After this BPF programs may not be in-use which is not what the user would expect. This patch moves the release logic into bpf_map_put_uref() and brings sockmap in-line with how a similar case is handled in prog array maps. Fixes: 3d9e952 ("bpf: sockmap, fix leaking maps with attached but not detached progs") Signed-off-by: John Fastabend <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 4dfe1bb commit ba6b8de

File tree

4 files changed

+7
-6
lines changed

4 files changed

+7
-6
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct bpf_map_ops {
3131
void (*map_release)(struct bpf_map *map, struct file *map_file);
3232
void (*map_free)(struct bpf_map *map);
3333
int (*map_get_next_key)(struct bpf_map *map, void *key, void *next_key);
34+
void (*map_release_uref)(struct bpf_map *map);
3435

3536
/* funcs callable from userspace and from eBPF programs */
3637
void *(*map_lookup_elem)(struct bpf_map *map, void *key);
@@ -436,7 +437,6 @@ int bpf_stackmap_copy(struct bpf_map *map, void *key, void *value);
436437
int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file,
437438
void *key, void *value, u64 map_flags);
438439
int bpf_fd_array_map_lookup_elem(struct bpf_map *map, void *key, u32 *value);
439-
void bpf_fd_array_map_clear(struct bpf_map *map);
440440
int bpf_fd_htab_map_update_elem(struct bpf_map *map, struct file *map_file,
441441
void *key, void *value, u64 map_flags);
442442
int bpf_fd_htab_map_lookup_elem(struct bpf_map *map, void *key, u32 *value);

kernel/bpf/arraymap.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ static u32 prog_fd_array_sys_lookup_elem(void *ptr)
476476
}
477477

478478
/* decrement refcnt of all bpf_progs that are stored in this map */
479-
void bpf_fd_array_map_clear(struct bpf_map *map)
479+
static void bpf_fd_array_map_clear(struct bpf_map *map)
480480
{
481481
struct bpf_array *array = container_of(map, struct bpf_array, map);
482482
int i;
@@ -495,6 +495,7 @@ const struct bpf_map_ops prog_array_map_ops = {
495495
.map_fd_get_ptr = prog_fd_array_get_ptr,
496496
.map_fd_put_ptr = prog_fd_array_put_ptr,
497497
.map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem,
498+
.map_release_uref = bpf_fd_array_map_clear,
498499
};
499500

500501
static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file,

kernel/bpf/sockmap.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,7 +1831,7 @@ static int sock_map_update_elem(struct bpf_map *map,
18311831
return err;
18321832
}
18331833

1834-
static void sock_map_release(struct bpf_map *map, struct file *map_file)
1834+
static void sock_map_release(struct bpf_map *map)
18351835
{
18361836
struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
18371837
struct bpf_prog *orig;
@@ -1855,7 +1855,7 @@ const struct bpf_map_ops sock_map_ops = {
18551855
.map_get_next_key = sock_map_get_next_key,
18561856
.map_update_elem = sock_map_update_elem,
18571857
.map_delete_elem = sock_map_delete_elem,
1858-
.map_release = sock_map_release,
1858+
.map_release_uref = sock_map_release,
18591859
};
18601860

18611861
BPF_CALL_4(bpf_sock_map_update, struct bpf_sock_ops_kern *, bpf_sock,

kernel/bpf/syscall.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ static void bpf_map_free_deferred(struct work_struct *work)
257257
static void bpf_map_put_uref(struct bpf_map *map)
258258
{
259259
if (atomic_dec_and_test(&map->usercnt)) {
260-
if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY)
261-
bpf_fd_array_map_clear(map);
260+
if (map->ops->map_release_uref)
261+
map->ops->map_release_uref(map);
262262
}
263263
}
264264

0 commit comments

Comments
 (0)