diff options
Diffstat (limited to 'bpf-fix-refcnt-overflow.patch')
-rw-r--r-- | bpf-fix-refcnt-overflow.patch | 158 |
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 - |