All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf] bpf: Fix cgroup local storage prog tracking
@ 2019-12-17 12:28 Daniel Borkmann
  2019-12-17 17:32 ` Alexei Starovoitov
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Daniel Borkmann @ 2019-12-17 12:28 UTC (permalink / raw)
  To: ast; +Cc: netdev, bpf, Daniel Borkmann, Roman Gushchin, Martin KaFai Lau

Recently noticed that we're tracking programs related to local storage maps
through their prog pointer. This is a wrong assumption since the prog pointer
can still change throughout the verification process, for example, whenever
bpf_patch_insn_single() is called.

Therefore, the prog pointer that was assigned via bpf_cgroup_storage_assign()
is not guaranteed to be the same as we pass in bpf_cgroup_storage_release()
and the map would therefore remain in busy state forever. Fix this by using
the prog's aux pointer which is stable throughout verification and beyond.

Fixes: de9cbbaadba5 ("bpf: introduce cgroup storage maps")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Cc: Roman Gushchin <guro@fb.com>
Cc: Martin KaFai Lau <kafai@fb.com>
---
 include/linux/bpf-cgroup.h |  8 ++++----
 kernel/bpf/core.c          |  3 +--
 kernel/bpf/local_storage.c | 24 ++++++++++++------------
 kernel/bpf/verifier.c      |  2 +-
 4 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index 169fd25f6bc2..9be71c195d74 100644
--- a/include/linux/bpf-cgroup.h
+++ b/include/linux/bpf-cgroup.h
@@ -157,8 +157,8 @@ void bpf_cgroup_storage_link(struct bpf_cgroup_storage *storage,
 			     struct cgroup *cgroup,
 			     enum bpf_attach_type type);
 void bpf_cgroup_storage_unlink(struct bpf_cgroup_storage *storage);
-int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *map);
-void bpf_cgroup_storage_release(struct bpf_prog *prog, struct bpf_map *map);
+int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux, struct bpf_map *map);
+void bpf_cgroup_storage_release(struct bpf_prog_aux *aux, struct bpf_map *map);
 
 int bpf_percpu_cgroup_storage_copy(struct bpf_map *map, void *key, void *value);
 int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
@@ -360,9 +360,9 @@ static inline int cgroup_bpf_prog_query(const union bpf_attr *attr,
 
 static inline void bpf_cgroup_storage_set(
 	struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE]) {}
-static inline int bpf_cgroup_storage_assign(struct bpf_prog *prog,
+static inline int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux,
 					    struct bpf_map *map) { return 0; }
-static inline void bpf_cgroup_storage_release(struct bpf_prog *prog,
+static inline void bpf_cgroup_storage_release(struct bpf_prog_aux *aux,
 					      struct bpf_map *map) {}
 static inline struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(
 	struct bpf_prog *prog, enum bpf_cgroup_storage_type stype) { return NULL; }
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 6231858df723..af6b738cf435 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2043,8 +2043,7 @@ static void bpf_free_cgroup_storage(struct bpf_prog_aux *aux)
 	for_each_cgroup_storage_type(stype) {
 		if (!aux->cgroup_storage[stype])
 			continue;
-		bpf_cgroup_storage_release(aux->prog,
-					   aux->cgroup_storage[stype]);
+		bpf_cgroup_storage_release(aux, aux->cgroup_storage[stype]);
 	}
 }
 
diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
index 2ba750725cb2..6bf605dd4b94 100644
--- a/kernel/bpf/local_storage.c
+++ b/kernel/bpf/local_storage.c
@@ -20,7 +20,7 @@ struct bpf_cgroup_storage_map {
 	struct bpf_map map;
 
 	spinlock_t lock;
-	struct bpf_prog *prog;
+	struct bpf_prog_aux *aux;
 	struct rb_root root;
 	struct list_head list;
 };
@@ -420,7 +420,7 @@ const struct bpf_map_ops cgroup_storage_map_ops = {
 	.map_seq_show_elem = cgroup_storage_seq_show_elem,
 };
 
-int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *_map)
+int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux, struct bpf_map *_map)
 {
 	enum bpf_cgroup_storage_type stype = cgroup_storage_type(_map);
 	struct bpf_cgroup_storage_map *map = map_to_storage(_map);
@@ -428,14 +428,14 @@ int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *_map)
 
 	spin_lock_bh(&map->lock);
 
-	if (map->prog && map->prog != prog)
+	if (map->aux && map->aux != aux)
 		goto unlock;
-	if (prog->aux->cgroup_storage[stype] &&
-	    prog->aux->cgroup_storage[stype] != _map)
+	if (aux->cgroup_storage[stype] &&
+	    aux->cgroup_storage[stype] != _map)
 		goto unlock;
 
-	map->prog = prog;
-	prog->aux->cgroup_storage[stype] = _map;
+	map->aux = aux;
+	aux->cgroup_storage[stype] = _map;
 	ret = 0;
 unlock:
 	spin_unlock_bh(&map->lock);
@@ -443,16 +443,16 @@ int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *_map)
 	return ret;
 }
 
-void bpf_cgroup_storage_release(struct bpf_prog *prog, struct bpf_map *_map)
+void bpf_cgroup_storage_release(struct bpf_prog_aux *aux, struct bpf_map *_map)
 {
 	enum bpf_cgroup_storage_type stype = cgroup_storage_type(_map);
 	struct bpf_cgroup_storage_map *map = map_to_storage(_map);
 
 	spin_lock_bh(&map->lock);
-	if (map->prog == prog) {
-		WARN_ON(prog->aux->cgroup_storage[stype] != _map);
-		map->prog = NULL;
-		prog->aux->cgroup_storage[stype] = NULL;
+	if (map->aux == aux) {
+		WARN_ON(aux->cgroup_storage[stype] != _map);
+		map->aux = NULL;
+		aux->cgroup_storage[stype] = NULL;
 	}
 	spin_unlock_bh(&map->lock);
 }
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index a1acdce77070..6ef71429d997 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -8268,7 +8268,7 @@ static int replace_map_fd_with_map_ptr(struct bpf_verifier_env *env)
 			env->used_maps[env->used_map_cnt++] = map;
 
 			if (bpf_map_is_cgroup_storage(map) &&
-			    bpf_cgroup_storage_assign(env->prog, map)) {
+			    bpf_cgroup_storage_assign(env->prog->aux, map)) {
 				verbose(env, "only one cgroup storage of each type is allowed\n");
 				fdput(f);
 				return -EBUSY;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH bpf] bpf: Fix cgroup local storage prog tracking
  2019-12-17 12:28 [PATCH bpf] bpf: Fix cgroup local storage prog tracking Daniel Borkmann
@ 2019-12-17 17:32 ` Alexei Starovoitov
  2019-12-17 18:14 ` Roman Gushchin
  2019-12-20 21:00 ` kbuild test robot
  2 siblings, 0 replies; 4+ messages in thread
From: Alexei Starovoitov @ 2019-12-17 17:32 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: Alexei Starovoitov, Network Development, bpf, Roman Gushchin,
	Martin KaFai Lau

On Tue, Dec 17, 2019 at 4:28 AM Daniel Borkmann <daniel@iogearbox.net> wrote:
>
> Recently noticed that we're tracking programs related to local storage maps
> through their prog pointer. This is a wrong assumption since the prog pointer
> can still change throughout the verification process, for example, whenever
> bpf_patch_insn_single() is called.
>
> Therefore, the prog pointer that was assigned via bpf_cgroup_storage_assign()
> is not guaranteed to be the same as we pass in bpf_cgroup_storage_release()
> and the map would therefore remain in busy state forever. Fix this by using
> the prog's aux pointer which is stable throughout verification and beyond.
>
> Fixes: de9cbbaadba5 ("bpf: introduce cgroup storage maps")
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Roman Gushchin <guro@fb.com>
> Cc: Martin KaFai Lau <kafai@fb.com>

Applied. Thanks

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH bpf] bpf: Fix cgroup local storage prog tracking
  2019-12-17 12:28 [PATCH bpf] bpf: Fix cgroup local storage prog tracking Daniel Borkmann
  2019-12-17 17:32 ` Alexei Starovoitov
@ 2019-12-17 18:14 ` Roman Gushchin
  2019-12-20 21:00 ` kbuild test robot
  2 siblings, 0 replies; 4+ messages in thread
From: Roman Gushchin @ 2019-12-17 18:14 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: ast, netdev, bpf, Martin Lau

On Tue, Dec 17, 2019 at 01:28:16PM +0100, Daniel Borkmann wrote:
> Recently noticed that we're tracking programs related to local storage maps
> through their prog pointer. This is a wrong assumption since the prog pointer
> can still change throughout the verification process, for example, whenever
> bpf_patch_insn_single() is called.

Oh, I didn't know it.

> 
> Therefore, the prog pointer that was assigned via bpf_cgroup_storage_assign()
> is not guaranteed to be the same as we pass in bpf_cgroup_storage_release()
> and the map would therefore remain in busy state forever. Fix this by using
> the prog's aux pointer which is stable throughout verification and beyond.
> 
> Fixes: de9cbbaadba5 ("bpf: introduce cgroup storage maps")
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Roman Gushchin <guro@fb.com>
> Cc: Martin KaFai Lau <kafai@fb.com>

Acked-by: Roman Gushchin <guro@fb.com>

Thank you, Daniel!

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH bpf] bpf: Fix cgroup local storage prog tracking
  2019-12-17 12:28 [PATCH bpf] bpf: Fix cgroup local storage prog tracking Daniel Borkmann
  2019-12-17 17:32 ` Alexei Starovoitov
  2019-12-17 18:14 ` Roman Gushchin
@ 2019-12-20 21:00 ` kbuild test robot
  2 siblings, 0 replies; 4+ messages in thread
From: kbuild test robot @ 2019-12-20 21:00 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 4070 bytes --]

Hi Daniel,

I love your patch! Yet something to improve:

[auto build test ERROR on bpf-next/master]
[also build test ERROR on net-next/master v5.5-rc2]
[cannot apply to bpf/master net/master ipvs/master next-20191219]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Daniel-Borkmann/bpf-Fix-cgroup-local-storage-prog-tracking/20191220-202857
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: sparc64-randconfig-a001-20191220 (attached as .config)
compiler: sparc64-linux-gcc (GCC) 7.5.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.5.0 make.cross ARCH=sparc64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   kernel/bpf/verifier.c: In function 'release_maps':
>> kernel/bpf/verifier.c:8307:30: error: passing argument 1 of 'bpf_cgroup_storage_release' from incompatible pointer type [-Werror=incompatible-pointer-types]
      bpf_cgroup_storage_release(env->prog,
                                 ^~~
   In file included from include/linux/cgroup-defs.h:22:0,
                    from include/linux/cgroup.h:28,
                    from include/net/netprio_cgroup.h:11,
                    from include/linux/netdevice.h:42,
                    from include/linux/if_vlan.h:10,
                    from include/linux/filter.h:22,
                    from include/linux/bpf_verifier.h:8,
                    from kernel/bpf/verifier.c:12:
   include/linux/bpf-cgroup.h:161:6: note: expected 'struct bpf_prog_aux *' but argument is of type 'struct bpf_prog *'
    void bpf_cgroup_storage_release(struct bpf_prog_aux *aux, struct bpf_map *map);
         ^~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/bpf_cgroup_storage_release +8307 kernel/bpf/verifier.c

0246e64d9a5fcd Alexei Starovoitov 2014-09-26  8297  
0246e64d9a5fcd Alexei Starovoitov 2014-09-26  8298  /* drop refcnt of maps used by the rejected program */
58e2af8b3a6b58 Jakub Kicinski     2016-09-21  8299  static void release_maps(struct bpf_verifier_env *env)
0246e64d9a5fcd Alexei Starovoitov 2014-09-26  8300  {
8bad74f9840f87 Roman Gushchin     2018-09-28  8301  	enum bpf_cgroup_storage_type stype;
0246e64d9a5fcd Alexei Starovoitov 2014-09-26  8302  	int i;
0246e64d9a5fcd Alexei Starovoitov 2014-09-26  8303  
8bad74f9840f87 Roman Gushchin     2018-09-28  8304  	for_each_cgroup_storage_type(stype) {
8bad74f9840f87 Roman Gushchin     2018-09-28  8305  		if (!env->prog->aux->cgroup_storage[stype])
8bad74f9840f87 Roman Gushchin     2018-09-28  8306  			continue;
de9cbbaadba5ad Roman Gushchin     2018-08-02 @8307  		bpf_cgroup_storage_release(env->prog,
8bad74f9840f87 Roman Gushchin     2018-09-28  8308  			env->prog->aux->cgroup_storage[stype]);
8bad74f9840f87 Roman Gushchin     2018-09-28  8309  	}
de9cbbaadba5ad Roman Gushchin     2018-08-02  8310  
0246e64d9a5fcd Alexei Starovoitov 2014-09-26  8311  	for (i = 0; i < env->used_map_cnt; i++)
0246e64d9a5fcd Alexei Starovoitov 2014-09-26  8312  		bpf_map_put(env->used_maps[i]);
0246e64d9a5fcd Alexei Starovoitov 2014-09-26  8313  }
0246e64d9a5fcd Alexei Starovoitov 2014-09-26  8314  

:::::: The code at line 8307 was first introduced by commit
:::::: de9cbbaadba5adf88a19e46df61f7054000838f6 bpf: introduce cgroup storage maps

:::::: TO: Roman Gushchin <guro@fb.com>
:::::: CC: Daniel Borkmann <daniel@iogearbox.net>

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org Intel Corporation

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 32391 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-12-20 21:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-17 12:28 [PATCH bpf] bpf: Fix cgroup local storage prog tracking Daniel Borkmann
2019-12-17 17:32 ` Alexei Starovoitov
2019-12-17 18:14 ` Roman Gushchin
2019-12-20 21:00 ` kbuild test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.