aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/bpf.h3
-rw-r--r--kernel/bpf/inode.c7
-rw-r--r--kernel/bpf/syscall.c24
-rw-r--r--kernel/bpf/verifier.c11
4 files changed, 33 insertions, 12 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 21ee41b92e8a..f1d5c5acc8dd 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -171,12 +171,13 @@ void bpf_register_prog_type(struct bpf_prog_type_list *tl);
171void bpf_register_map_type(struct bpf_map_type_list *tl); 171void bpf_register_map_type(struct bpf_map_type_list *tl);
172 172
173struct bpf_prog *bpf_prog_get(u32 ufd); 173struct bpf_prog *bpf_prog_get(u32 ufd);
174struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog);
174void bpf_prog_put(struct bpf_prog *prog); 175void bpf_prog_put(struct bpf_prog *prog);
175void bpf_prog_put_rcu(struct bpf_prog *prog); 176void bpf_prog_put_rcu(struct bpf_prog *prog);
176 177
177struct bpf_map *bpf_map_get_with_uref(u32 ufd); 178struct bpf_map *bpf_map_get_with_uref(u32 ufd);
178struct bpf_map *__bpf_map_get(struct fd f); 179struct bpf_map *__bpf_map_get(struct fd f);
179void bpf_map_inc(struct bpf_map *map, bool uref); 180struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref);
180void bpf_map_put_with_uref(struct bpf_map *map); 181void bpf_map_put_with_uref(struct bpf_map *map);
181void bpf_map_put(struct bpf_map *map); 182void bpf_map_put(struct bpf_map *map);
182int bpf_map_precharge_memlock(u32 pages); 183int bpf_map_precharge_memlock(u32 pages);
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index f2ece3c174a5..8f94ca1860cf 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -31,10 +31,10 @@ static void *bpf_any_get(void *raw, enum bpf_type type)
31{ 31{
32 switch (type) { 32 switch (type) {
33 case BPF_TYPE_PROG: 33 case BPF_TYPE_PROG:
34 atomic_inc(&((struct bpf_prog *)raw)->aux->refcnt); 34 raw = bpf_prog_inc(raw);
35 break; 35 break;
36 case BPF_TYPE_MAP: 36 case BPF_TYPE_MAP:
37 bpf_map_inc(raw, true); 37 raw = bpf_map_inc(raw, true);
38 break; 38 break;
39 default: 39 default:
40 WARN_ON_ONCE(1); 40 WARN_ON_ONCE(1);
@@ -297,7 +297,8 @@ static void *bpf_obj_do_get(const struct filename *pathname,
297 goto out; 297 goto out;
298 298
299 raw = bpf_any_get(inode->i_private, *type); 299 raw = bpf_any_get(inode->i_private, *type);
300 touch_atime(&path); 300 if (!IS_ERR(raw))
301 touch_atime(&path);
301 302
302 path_put(&path); 303 path_put(&path);
303 return raw; 304 return raw;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index adc5e4bd74f8..cf5e9f7ad13a 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -218,11 +218,18 @@ struct bpf_map *__bpf_map_get(struct fd f)
218 return f.file->private_data; 218 return f.file->private_data;
219} 219}
220 220
221void bpf_map_inc(struct bpf_map *map, bool uref) 221/* prog's and map's refcnt limit */
222#define BPF_MAX_REFCNT 32768
223
224struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref)
222{ 225{
223 atomic_inc(&map->refcnt); 226 if (atomic_inc_return(&map->refcnt) > BPF_MAX_REFCNT) {
227 atomic_dec(&map->refcnt);
228 return ERR_PTR(-EBUSY);
229 }
224 if (uref) 230 if (uref)
225 atomic_inc(&map->usercnt); 231 atomic_inc(&map->usercnt);
232 return map;
226} 233}
227 234
228struct bpf_map *bpf_map_get_with_uref(u32 ufd) 235struct bpf_map *bpf_map_get_with_uref(u32 ufd)
@@ -234,7 +241,7 @@ struct bpf_map *bpf_map_get_with_uref(u32 ufd)
234 if (IS_ERR(map)) 241 if (IS_ERR(map))
235 return map; 242 return map;
236 243
237 bpf_map_inc(map, true); 244 map = bpf_map_inc(map, true);
238 fdput(f); 245 fdput(f);
239 246
240 return map; 247 return map;
@@ -658,6 +665,15 @@ static struct bpf_prog *__bpf_prog_get(struct fd f)
658 return f.file->private_data; 665 return f.file->private_data;
659} 666}
660 667
668struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
669{
670 if (atomic_inc_return(&prog->aux->refcnt) > BPF_MAX_REFCNT) {
671 atomic_dec(&prog->aux->refcnt);
672 return ERR_PTR(-EBUSY);
673 }
674 return prog;
675}
676
661/* called by sockets/tracing/seccomp before attaching program to an event 677/* called by sockets/tracing/seccomp before attaching program to an event
662 * pairs with bpf_prog_put() 678 * pairs with bpf_prog_put()
663 */ 679 */
@@ -670,7 +686,7 @@ struct bpf_prog *bpf_prog_get(u32 ufd)
670 if (IS_ERR(prog)) 686 if (IS_ERR(prog))
671 return prog; 687 return prog;
672 688
673 atomic_inc(&prog->aux->refcnt); 689 prog = bpf_prog_inc(prog);
674 fdput(f); 690 fdput(f);
675 691
676 return prog; 692 return prog;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index db2574e7b8b0..89bcaa0966da 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2049,15 +2049,18 @@ static int replace_map_fd_with_map_ptr(struct verifier_env *env)
2049 return -E2BIG; 2049 return -E2BIG;
2050 } 2050 }
2051 2051
2052 /* remember this map */
2053 env->used_maps[env->used_map_cnt++] = map;
2054
2055 /* hold the map. If the program is rejected by verifier, 2052 /* hold the map. If the program is rejected by verifier,
2056 * the map will be released by release_maps() or it 2053 * the map will be released by release_maps() or it
2057 * will be used by the valid program until it's unloaded 2054 * will be used by the valid program until it's unloaded
2058 * and all maps are released in free_bpf_prog_info() 2055 * and all maps are released in free_bpf_prog_info()
2059 */ 2056 */
2060 bpf_map_inc(map, false); 2057 map = bpf_map_inc(map, false);
2058 if (IS_ERR(map)) {
2059 fdput(f);
2060 return PTR_ERR(map);
2061 }
2062 env->used_maps[env->used_map_cnt++] = map;
2063
2061 fdput(f); 2064 fdput(f);
2062next_insn: 2065next_insn:
2063 insn++; 2066 insn++;