diff options
-rw-r--r-- | include/linux/bpf.h | 5 | ||||
-rw-r--r-- | kernel/bpf/inode.c | 6 | ||||
-rw-r--r-- | kernel/bpf/syscall.c | 36 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 3 |
4 files changed, 17 insertions, 33 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 8eb8dfc66416..1dde66a4be98 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -40,7 +40,6 @@ struct bpf_map { struct user_struct *user; const struct bpf_map_ops *ops; struct work_struct work; - atomic_t usercnt; }; struct bpf_map_type_list { @@ -168,10 +167,8 @@ struct bpf_prog *bpf_prog_get(u32 ufd); void bpf_prog_put(struct bpf_prog *prog); void bpf_prog_put_rcu(struct bpf_prog *prog); -struct bpf_map *bpf_map_get_with_uref(u32 ufd); +struct bpf_map *bpf_map_get(u32 ufd); struct bpf_map *__bpf_map_get(struct fd f); -void bpf_map_inc(struct bpf_map *map, bool uref); -void bpf_map_put_with_uref(struct bpf_map *map); void bpf_map_put(struct bpf_map *map); extern int sysctl_unprivileged_bpf_disabled; diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index 5a8a797d50b7..be6d726e31c9 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c @@ -34,7 +34,7 @@ static void *bpf_any_get(void *raw, enum bpf_type type) atomic_inc(&((struct bpf_prog *)raw)->aux->refcnt); break; case BPF_TYPE_MAP: - bpf_map_inc(raw, true); + atomic_inc(&((struct bpf_map *)raw)->refcnt); break; default: WARN_ON_ONCE(1); @@ -51,7 +51,7 @@ static void bpf_any_put(void *raw, enum bpf_type type) bpf_prog_put(raw); break; case BPF_TYPE_MAP: - bpf_map_put_with_uref(raw); + bpf_map_put(raw); break; default: WARN_ON_ONCE(1); @@ -64,7 +64,7 @@ static void *bpf_fd_probe_obj(u32 ufd, enum bpf_type *type) void *raw; *type = BPF_TYPE_MAP; - raw = bpf_map_get_with_uref(ufd); + raw = bpf_map_get(ufd); if (IS_ERR(raw)) { *type = BPF_TYPE_PROG; raw = bpf_prog_get(ufd); diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 72a2272e370f..14bc36a91d5d 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -82,14 +82,6 @@ static void bpf_map_free_deferred(struct work_struct *work) map->ops->map_free(map); } -static void bpf_map_put_uref(struct bpf_map *map) -{ - if (atomic_dec_and_test(&map->usercnt)) { - if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) - bpf_fd_array_map_clear(map); - } -} - /* decrement map refcnt and schedule it for freeing via workqueue * (unrelying map implementation ops->map_free() might sleep) */ @@ -101,15 +93,17 @@ void bpf_map_put(struct bpf_map *map) } } -void bpf_map_put_with_uref(struct bpf_map *map) -{ - bpf_map_put_uref(map); - bpf_map_put(map); -} - static int bpf_map_release(struct inode *inode, struct file *filp) { - bpf_map_put_with_uref(filp->private_data); + struct bpf_map *map = filp->private_data; + + if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) + /* prog_array stores refcnt-ed bpf_prog pointers + * release them all when user space closes prog_array_fd + */ + bpf_fd_array_map_clear(map); + + bpf_map_put(map); return 0; } @@ -148,7 +142,6 @@ static int map_create(union bpf_attr *attr) return PTR_ERR(map); atomic_set(&map->refcnt, 1); - atomic_set(&map->usercnt, 1); err = bpf_map_charge_memlock(map); if (err) @@ -183,14 +176,7 @@ struct bpf_map *__bpf_map_get(struct fd f) return f.file->private_data; } -void bpf_map_inc(struct bpf_map *map, bool uref) -{ - atomic_inc(&map->refcnt); - if (uref) - atomic_inc(&map->usercnt); -} - -struct bpf_map *bpf_map_get_with_uref(u32 ufd) +struct bpf_map *bpf_map_get(u32 ufd) { struct fd f = fdget(ufd); struct bpf_map *map; @@ -199,7 +185,7 @@ struct bpf_map *bpf_map_get_with_uref(u32 ufd) if (IS_ERR(map)) return map; - bpf_map_inc(map, true); + atomic_inc(&map->refcnt); fdput(f); return map; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index a7945d10b378..c6073056badf 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -2021,7 +2021,8 @@ static int replace_map_fd_with_map_ptr(struct verifier_env *env) * will be used by the valid program until it's unloaded * and all maps are released in free_bpf_prog_info() */ - bpf_map_inc(map, false); + atomic_inc(&map->refcnt); + fdput(f); next_insn: insn++; |