All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf v2 1/2] bpf, cgroup: Assign cgroup in cgroup_sk_alloc when called from interrupt
@ 2021-09-27 12:39 Daniel Borkmann
  2021-09-27 12:39 ` [PATCH bpf v2 2/2] bpf, test, cgroup: Use sk_{alloc,free} for test cases Daniel Borkmann
  2021-09-27 16:37 ` [PATCH bpf v2 1/2] bpf, cgroup: Assign cgroup in cgroup_sk_alloc when called from interrupt Tejun Heo
  0 siblings, 2 replies; 3+ messages in thread
From: Daniel Borkmann @ 2021-09-27 12:39 UTC (permalink / raw)
  To: alexei.starovoitov
  Cc: andrii, bpf, Daniel Borkmann, syzbot+df709157a4ecaf192b03,
	syzbot+533f389d4026d86a2a95, Tejun Heo, Stanislav Fomichev

If cgroup_sk_alloc() is called from interrupt context, then just assign the
root cgroup to skcd->cgroup. Prior to commit 8520e224f547 ("bpf, cgroups:
Fix cgroup v2 fallback on v1/v2 mixed mode") we would just return, and later
on in sock_cgroup_ptr(), we were NULL-testing the cgroup in fast-path, and
iff indeed NULL returning the root cgroup (v ?: &cgrp_dfl_root.cgrp). Rather
than re-adding the NULL-test to the fast-path we can just assign it once from
cgroup_sk_alloc() given v1/v2 handling has been simplified. The migration from
NULL test with returning &cgrp_dfl_root.cgrp to assigning &cgrp_dfl_root.cgrp
directly does /not/ change behavior for callers of sock_cgroup_ptr().

syzkaller was able to trigger a splat in the legacy netrom code base, where
the RX handler in nr_rx_frame() calls nr_make_new() which calls sk_alloc()
and therefore cgroup_sk_alloc() with in_interrupt() condition. Thus the NULL
skcd->cgroup, where it trips over on cgroup_sk_free() side given it expects
a non-NULL object. There are a few other candidates aside from netrom which
have similar pattern where in their accept-like implementation, they just call
to sk_alloc() and thus cgroup_sk_alloc() instead of sk_clone_lock() with the
corresponding cgroup_sk_clone() which then inherits the cgroup from the parent
socket. None of them are related to core protocols where BPF cgroup programs
are running from. However, in future, they should follow to implement a similar
inheritance mechanism.

Additionally, with a !CONFIG_CGROUP_NET_PRIO and !CONFIG_CGROUP_NET_CLASSID
configuration, the same issue was exposed also prior to 8520e224f547 due to
commit e876ecc67db8 ("cgroup: memcg: net: do not associate sock with unrelated
cgroup") which added the early in_interrupt() return back then.

Fixes: 8520e224f547 ("bpf, cgroups: Fix cgroup v2 fallback on v1/v2 mixed mode")
Fixes: e876ecc67db8 ("cgroup: memcg: net: do not associate sock with unrelated cgroup")
Reported-by: syzbot+df709157a4ecaf192b03@syzkaller.appspotmail.com
Reported-by: syzbot+533f389d4026d86a2a95@syzkaller.appspotmail.com
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Tested-by: syzbot+df709157a4ecaf192b03@syzkaller.appspotmail.com
Tested-by: syzbot+533f389d4026d86a2a95@syzkaller.appspotmail.com
Cc: Tejun Heo <tj@kernel.org>
Cc: Stanislav Fomichev <sdf@google.com>
---
 v1 -> v2:
   - Note down more details about the issue in commit message (Tejun)

 kernel/cgroup/cgroup.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 8afa8690d288..570b0c97392a 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -6574,22 +6574,29 @@ int cgroup_parse_float(const char *input, unsigned dec_shift, s64 *v)
 
 void cgroup_sk_alloc(struct sock_cgroup_data *skcd)
 {
-	/* Don't associate the sock with unrelated interrupted task's cgroup. */
-	if (in_interrupt())
-		return;
+	struct cgroup *cgroup;
 
 	rcu_read_lock();
+	/* Don't associate the sock with unrelated interrupted task's cgroup. */
+	if (in_interrupt()) {
+		cgroup = &cgrp_dfl_root.cgrp;
+		cgroup_get(cgroup);
+		goto out;
+	}
+
 	while (true) {
 		struct css_set *cset;
 
 		cset = task_css_set(current);
 		if (likely(cgroup_tryget(cset->dfl_cgrp))) {
-			skcd->cgroup = cset->dfl_cgrp;
-			cgroup_bpf_get(cset->dfl_cgrp);
+			cgroup = cset->dfl_cgrp;
 			break;
 		}
 		cpu_relax();
 	}
+out:
+	skcd->cgroup = cgroup;
+	cgroup_bpf_get(cgroup);
 	rcu_read_unlock();
 }
 
-- 
2.27.0


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

* [PATCH bpf v2 2/2] bpf, test, cgroup: Use sk_{alloc,free} for test cases
  2021-09-27 12:39 [PATCH bpf v2 1/2] bpf, cgroup: Assign cgroup in cgroup_sk_alloc when called from interrupt Daniel Borkmann
@ 2021-09-27 12:39 ` Daniel Borkmann
  2021-09-27 16:37 ` [PATCH bpf v2 1/2] bpf, cgroup: Assign cgroup in cgroup_sk_alloc when called from interrupt Tejun Heo
  1 sibling, 0 replies; 3+ messages in thread
From: Daniel Borkmann @ 2021-09-27 12:39 UTC (permalink / raw)
  To: alexei.starovoitov
  Cc: andrii, bpf, Daniel Borkmann, syzbot+664b58e9a40fbb2cec71,
	syzbot+33f36d0754d4c5c0e102, Stanislav Fomichev,
	Martin KaFai Lau, Song Liu

BPF test infra has some hacks in place which kzalloc() a socket and perform
minimum init via sock_net_set() and sock_init_data(). As a result, the sk's
skcd->cgroup is NULL since it didn't go through proper initialization as it
would have been the case from sk_alloc(). Rather than re-adding a NULL test
in sock_cgroup_ptr() just for this, use sk_{alloc,free}() pair for the test
socket. The latter also allows to get rid of the bpf_sk_storage_free() special
case.

Fixes: 8520e224f547 ("bpf, cgroups: Fix cgroup v2 fallback on v1/v2 mixed mode")
Fixes: b7a1848e8398 ("bpf: add BPF_PROG_TEST_RUN support for flow dissector")
Fixes: 2cb494a36c98 ("bpf: add tests for direct packet access from CGROUP_SKB")
Reported-by: syzbot+664b58e9a40fbb2cec71@syzkaller.appspotmail.com
Reported-by: syzbot+33f36d0754d4c5c0e102@syzkaller.appspotmail.com
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Tested-by: syzbot+664b58e9a40fbb2cec71@syzkaller.appspotmail.com
Tested-by: syzbot+33f36d0754d4c5c0e102@syzkaller.appspotmail.com
Cc: Stanislav Fomichev <sdf@google.com>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: Song Liu <songliubraving@fb.com>
---
 net/bpf/test_run.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index 2eb0e55ef54d..b5f4ef35357c 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -552,6 +552,12 @@ static void convert_skb_to___skb(struct sk_buff *skb, struct __sk_buff *__skb)
 	__skb->gso_segs = skb_shinfo(skb)->gso_segs;
 }
 
+static struct proto bpf_dummy_proto = {
+	.name   = "bpf_dummy",
+	.owner  = THIS_MODULE,
+	.obj_size = sizeof(struct sock),
+};
+
 int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
 			  union bpf_attr __user *uattr)
 {
@@ -596,20 +602,19 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
 		break;
 	}
 
-	sk = kzalloc(sizeof(struct sock), GFP_USER);
+	sk = sk_alloc(net, AF_UNSPEC, GFP_USER, &bpf_dummy_proto, 1);
 	if (!sk) {
 		kfree(data);
 		kfree(ctx);
 		return -ENOMEM;
 	}
-	sock_net_set(sk, net);
 	sock_init_data(NULL, sk);
 
 	skb = build_skb(data, 0);
 	if (!skb) {
 		kfree(data);
 		kfree(ctx);
-		kfree(sk);
+		sk_free(sk);
 		return -ENOMEM;
 	}
 	skb->sk = sk;
@@ -682,8 +687,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
 	if (dev && dev != net->loopback_dev)
 		dev_put(dev);
 	kfree_skb(skb);
-	bpf_sk_storage_free(sk);
-	kfree(sk);
+	sk_free(sk);
 	kfree(ctx);
 	return ret;
 }
-- 
2.27.0


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

* Re: [PATCH bpf v2 1/2] bpf, cgroup: Assign cgroup in cgroup_sk_alloc when called from interrupt
  2021-09-27 12:39 [PATCH bpf v2 1/2] bpf, cgroup: Assign cgroup in cgroup_sk_alloc when called from interrupt Daniel Borkmann
  2021-09-27 12:39 ` [PATCH bpf v2 2/2] bpf, test, cgroup: Use sk_{alloc,free} for test cases Daniel Borkmann
@ 2021-09-27 16:37 ` Tejun Heo
  1 sibling, 0 replies; 3+ messages in thread
From: Tejun Heo @ 2021-09-27 16:37 UTC (permalink / raw)
  Cc: alexei.starovoitov, andrii, bpf, syzbot+df709157a4ecaf192b03,
	syzbot+533f389d4026d86a2a95, Stanislav Fomichev

On Mon, Sep 27, 2021 at 02:39:20PM +0200, Daniel Borkmann wrote:
> If cgroup_sk_alloc() is called from interrupt context, then just assign the
> root cgroup to skcd->cgroup. Prior to commit 8520e224f547 ("bpf, cgroups:
> Fix cgroup v2 fallback on v1/v2 mixed mode") we would just return, and later
> on in sock_cgroup_ptr(), we were NULL-testing the cgroup in fast-path, and
> iff indeed NULL returning the root cgroup (v ?: &cgrp_dfl_root.cgrp). Rather
> than re-adding the NULL-test to the fast-path we can just assign it once from
> cgroup_sk_alloc() given v1/v2 handling has been simplified. The migration from
> NULL test with returning &cgrp_dfl_root.cgrp to assigning &cgrp_dfl_root.cgrp
> directly does /not/ change behavior for callers of sock_cgroup_ptr().
> 
> syzkaller was able to trigger a splat in the legacy netrom code base, where
> the RX handler in nr_rx_frame() calls nr_make_new() which calls sk_alloc()
> and therefore cgroup_sk_alloc() with in_interrupt() condition. Thus the NULL
> skcd->cgroup, where it trips over on cgroup_sk_free() side given it expects
> a non-NULL object. There are a few other candidates aside from netrom which
> have similar pattern where in their accept-like implementation, they just call
> to sk_alloc() and thus cgroup_sk_alloc() instead of sk_clone_lock() with the
> corresponding cgroup_sk_clone() which then inherits the cgroup from the parent
> socket. None of them are related to core protocols where BPF cgroup programs
> are running from. However, in future, they should follow to implement a similar
> inheritance mechanism.
> 
> Additionally, with a !CONFIG_CGROUP_NET_PRIO and !CONFIG_CGROUP_NET_CLASSID
> configuration, the same issue was exposed also prior to 8520e224f547 due to
> commit e876ecc67db8 ("cgroup: memcg: net: do not associate sock with unrelated
> cgroup") which added the early in_interrupt() return back then.
> 
> Fixes: 8520e224f547 ("bpf, cgroups: Fix cgroup v2 fallback on v1/v2 mixed mode")
> Fixes: e876ecc67db8 ("cgroup: memcg: net: do not associate sock with unrelated cgroup")
> Reported-by: syzbot+df709157a4ecaf192b03@syzkaller.appspotmail.com
> Reported-by: syzbot+533f389d4026d86a2a95@syzkaller.appspotmail.com
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> Tested-by: syzbot+df709157a4ecaf192b03@syzkaller.appspotmail.com
> Tested-by: syzbot+533f389d4026d86a2a95@syzkaller.appspotmail.com
> Cc: Tejun Heo <tj@kernel.org>
> Cc: Stanislav Fomichev <sdf@google.com>

Acked-by: Tejun Heo <tj@kernel.org>

Thanks.

-- 
tejun

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

end of thread, other threads:[~2021-09-27 16:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-27 12:39 [PATCH bpf v2 1/2] bpf, cgroup: Assign cgroup in cgroup_sk_alloc when called from interrupt Daniel Borkmann
2021-09-27 12:39 ` [PATCH bpf v2 2/2] bpf, test, cgroup: Use sk_{alloc,free} for test cases Daniel Borkmann
2021-09-27 16:37 ` [PATCH bpf v2 1/2] bpf, cgroup: Assign cgroup in cgroup_sk_alloc when called from interrupt Tejun Heo

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.