summaryrefslogtreecommitdiffstats
path: root/bpf-fix-refcnt-overflow.patch
diff options
context:
space:
mode:
Diffstat (limited to 'bpf-fix-refcnt-overflow.patch')
-rw-r--r--bpf-fix-refcnt-overflow.patch158
1 files changed, 0 insertions, 158 deletions
diff --git a/bpf-fix-refcnt-overflow.patch b/bpf-fix-refcnt-overflow.patch
deleted file mode 100644
index 1143c8286..000000000
--- a/bpf-fix-refcnt-overflow.patch
+++ /dev/null
@@ -1,158 +0,0 @@
-From 86db8dac9286f8397434184a6b442b6419e54ec0 Mon Sep 17 00:00:00 2001
-From: Alexei Starovoitov <ast@fb.com>
-Date: Wed, 27 Apr 2016 18:56:20 -0700
-Subject: [PATCH] bpf: fix refcnt overflow
-
-On a system with >32Gbyte of phyiscal memory and infinite RLIMIT_MEMLOCK,
-the malicious application may overflow 32-bit bpf program refcnt.
-It's also possible to overflow map refcnt on 1Tb system.
-Impose 32k hard limit which means that the same bpf program or
-map cannot be shared by more than 32k processes.
-
-Fixes: 1be7f75d1668 ("bpf: enable non-root eBPF programs")
-Reported-by: Jann Horn <jannh@google.com>
-Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-Acked-by: Daniel Borkmann <daniel@iogearbox.net>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- include/linux/bpf.h | 3 ++-
- kernel/bpf/inode.c | 7 ++++---
- kernel/bpf/syscall.c | 24 ++++++++++++++++++++----
- kernel/bpf/verifier.c | 11 +++++++----
- 4 files changed, 33 insertions(+), 12 deletions(-)
-
-diff --git a/include/linux/bpf.h b/include/linux/bpf.h
-index 83d1926c61e4..67bc2da5d233 100644
---- a/include/linux/bpf.h
-+++ b/include/linux/bpf.h
-@@ -165,12 +165,13 @@ void bpf_register_prog_type(struct bpf_prog_type_list *tl);
- void bpf_register_map_type(struct bpf_map_type_list *tl);
-
- struct bpf_prog *bpf_prog_get(u32 ufd);
-+struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog);
- 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(struct fd f);
--void bpf_map_inc(struct bpf_map *map, bool uref);
-+struct bpf_map *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);
-
-diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
-index 5a8a797d50b7..d1a7646f79c5 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)
- {
- switch (type) {
- case BPF_TYPE_PROG:
-- atomic_inc(&((struct bpf_prog *)raw)->aux->refcnt);
-+ raw = bpf_prog_inc(raw);
- break;
- case BPF_TYPE_MAP:
-- bpf_map_inc(raw, true);
-+ raw = bpf_map_inc(raw, true);
- break;
- default:
- WARN_ON_ONCE(1);
-@@ -277,7 +277,8 @@ static void *bpf_obj_do_get(const struct filename *pathname,
- goto out;
-
- raw = bpf_any_get(inode->i_private, *type);
-- touch_atime(&path);
-+ if (!IS_ERR(raw))
-+ touch_atime(&path);
-
- path_put(&path);
- return raw;
-diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
-index 3b39550d8485..4e32cc94edd9 100644
---- a/kernel/bpf/syscall.c
-+++ b/kernel/bpf/syscall.c
-@@ -181,11 +181,18 @@ struct bpf_map *__bpf_map_get(struct fd f)
- return f.file->private_data;
- }
-
--void bpf_map_inc(struct bpf_map *map, bool uref)
-+/* prog's and map's refcnt limit */
-+#define BPF_MAX_REFCNT 32768
-+
-+struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref)
- {
-- atomic_inc(&map->refcnt);
-+ if (atomic_inc_return(&map->refcnt) > BPF_MAX_REFCNT) {
-+ atomic_dec(&map->refcnt);
-+ return ERR_PTR(-EBUSY);
-+ }
- if (uref)
- atomic_inc(&map->usercnt);
-+ return map;
- }
-
- struct bpf_map *bpf_map_get_with_uref(u32 ufd)
-@@ -197,7 +204,7 @@ struct bpf_map *bpf_map_get_with_uref(u32 ufd)
- if (IS_ERR(map))
- return map;
-
-- bpf_map_inc(map, true);
-+ map = bpf_map_inc(map, true);
- fdput(f);
-
- return map;
-@@ -580,6 +587,15 @@ static struct bpf_prog *__bpf_prog_get(struct fd f)
- return f.file->private_data;
- }
-
-+struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
-+{
-+ if (atomic_inc_return(&prog->aux->refcnt) > BPF_MAX_REFCNT) {
-+ atomic_dec(&prog->aux->refcnt);
-+ return ERR_PTR(-EBUSY);
-+ }
-+ return prog;
-+}
-+
- /* called by sockets/tracing/seccomp before attaching program to an event
- * pairs with bpf_prog_put()
- */
-@@ -592,7 +608,7 @@ struct bpf_prog *bpf_prog_get(u32 ufd)
- if (IS_ERR(prog))
- return prog;
-
-- atomic_inc(&prog->aux->refcnt);
-+ prog = bpf_prog_inc(prog);
- fdput(f);
-
- return prog;
-diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
-index 2e7f7ab739e4..060e4c4c37ea 100644
---- a/kernel/bpf/verifier.c
-+++ b/kernel/bpf/verifier.c
-@@ -2023,15 +2023,18 @@ static int replace_map_fd_with_map_ptr(struct verifier_env *env)
- return -E2BIG;
- }
-
-- /* remember this map */
-- env->used_maps[env->used_map_cnt++] = map;
--
- /* hold the map. If the program is rejected by verifier,
- * the map will be released by release_maps() or it
- * 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);
-+ map = bpf_map_inc(map, false);
-+ if (IS_ERR(map)) {
-+ fdput(f);
-+ return PTR_ERR(map);
-+ }
-+ env->used_maps[env->used_map_cnt++] = map;
-+
- fdput(f);
- next_insn:
- insn++;
---
-2.5.5
-