aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Fastabend <john.fastabend@gmail.com>2018-04-23 18:39:23 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-04-23 18:49:45 -0400
commitba6b8de423f8d0dee48d6030288ed81c03ddf9f0 (patch)
tree23b0256f0247694e37e4505d239245d1e460bc45
parent4dfe1bb95235c553e216222cf0c377faf191dacd (diff)
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: 3d9e952697de ("bpf: sockmap, fix leaking maps with attached but not detached progs") Signed-off-by: John Fastabend <john.fastabend@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--include/linux/bpf.h2
-rw-r--r--kernel/bpf/arraymap.c3
-rw-r--r--kernel/bpf/sockmap.c4
-rw-r--r--kernel/bpf/syscall.c4
4 files changed, 7 insertions, 6 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index dc586cc64bc2..469b20e1dd7e 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -31,6 +31,7 @@ struct bpf_map_ops {
31 void (*map_release)(struct bpf_map *map, struct file *map_file); 31 void (*map_release)(struct bpf_map *map, struct file *map_file);
32 void (*map_free)(struct bpf_map *map); 32 void (*map_free)(struct bpf_map *map);
33 int (*map_get_next_key)(struct bpf_map *map, void *key, void *next_key); 33 int (*map_get_next_key)(struct bpf_map *map, void *key, void *next_key);
34 void (*map_release_uref)(struct bpf_map *map);
34 35
35 /* funcs callable from userspace and from eBPF programs */ 36 /* funcs callable from userspace and from eBPF programs */
36 void *(*map_lookup_elem)(struct bpf_map *map, void *key); 37 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);
436int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file, 437int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file,
437 void *key, void *value, u64 map_flags); 438 void *key, void *value, u64 map_flags);
438int bpf_fd_array_map_lookup_elem(struct bpf_map *map, void *key, u32 *value); 439int bpf_fd_array_map_lookup_elem(struct bpf_map *map, void *key, u32 *value);
439void bpf_fd_array_map_clear(struct bpf_map *map);
440int bpf_fd_htab_map_update_elem(struct bpf_map *map, struct file *map_file, 440int bpf_fd_htab_map_update_elem(struct bpf_map *map, struct file *map_file,
441 void *key, void *value, u64 map_flags); 441 void *key, void *value, u64 map_flags);
442int bpf_fd_htab_map_lookup_elem(struct bpf_map *map, void *key, u32 *value); 442int bpf_fd_htab_map_lookup_elem(struct bpf_map *map, void *key, u32 *value);
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 14750e7c5ee4..027107f4be53 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -476,7 +476,7 @@ static u32 prog_fd_array_sys_lookup_elem(void *ptr)
476} 476}
477 477
478/* decrement refcnt of all bpf_progs that are stored in this map */ 478/* decrement refcnt of all bpf_progs that are stored in this map */
479void bpf_fd_array_map_clear(struct bpf_map *map) 479static void bpf_fd_array_map_clear(struct bpf_map *map)
480{ 480{
481 struct bpf_array *array = container_of(map, struct bpf_array, map); 481 struct bpf_array *array = container_of(map, struct bpf_array, map);
482 int i; 482 int i;
@@ -495,6 +495,7 @@ const struct bpf_map_ops prog_array_map_ops = {
495 .map_fd_get_ptr = prog_fd_array_get_ptr, 495 .map_fd_get_ptr = prog_fd_array_get_ptr,
496 .map_fd_put_ptr = prog_fd_array_put_ptr, 496 .map_fd_put_ptr = prog_fd_array_put_ptr,
497 .map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem, 497 .map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem,
498 .map_release_uref = bpf_fd_array_map_clear,
498}; 499};
499 500
500static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file, 501static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file,
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index a3b21385e947..a73d484b6e4c 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -1831,7 +1831,7 @@ static int sock_map_update_elem(struct bpf_map *map,
1831 return err; 1831 return err;
1832} 1832}
1833 1833
1834static void sock_map_release(struct bpf_map *map, struct file *map_file) 1834static void sock_map_release(struct bpf_map *map)
1835{ 1835{
1836 struct bpf_stab *stab = container_of(map, struct bpf_stab, map); 1836 struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
1837 struct bpf_prog *orig; 1837 struct bpf_prog *orig;
@@ -1855,7 +1855,7 @@ const struct bpf_map_ops sock_map_ops = {
1855 .map_get_next_key = sock_map_get_next_key, 1855 .map_get_next_key = sock_map_get_next_key,
1856 .map_update_elem = sock_map_update_elem, 1856 .map_update_elem = sock_map_update_elem,
1857 .map_delete_elem = sock_map_delete_elem, 1857 .map_delete_elem = sock_map_delete_elem,
1858 .map_release = sock_map_release, 1858 .map_release_uref = sock_map_release,
1859}; 1859};
1860 1860
1861BPF_CALL_4(bpf_sock_map_update, struct bpf_sock_ops_kern *, bpf_sock, 1861BPF_CALL_4(bpf_sock_map_update, struct bpf_sock_ops_kern *, bpf_sock,
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 4ca46df19c9a..ebfe9f29dae8 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -257,8 +257,8 @@ static void bpf_map_free_deferred(struct work_struct *work)
257static void bpf_map_put_uref(struct bpf_map *map) 257static void bpf_map_put_uref(struct bpf_map *map)
258{ 258{
259 if (atomic_dec_and_test(&map->usercnt)) { 259 if (atomic_dec_and_test(&map->usercnt)) {
260 if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) 260 if (map->ops->map_release_uref)
261 bpf_fd_array_map_clear(map); 261 map->ops->map_release_uref(map);
262 } 262 }
263} 263}
264 264