Blame SOURCES/CVE-2021-3609.patch

f48d8f
From 61fe578156c4c9bad13e83efdf4a1546c1bab3cd Mon Sep 17 00:00:00 2001
f48d8f
From: Artem Savkov <asavkov@redhat.com>
f48d8f
Date: Mon, 26 Jul 2021 12:27:34 +0200
f48d8f
Subject: [PATCH] can: bcm: delay release of struct bcm_op after
f48d8f
 synchronize_rcu()
f48d8f
f48d8f
Kernels:
f48d8f
4.18.0-305.el8
f48d8f
4.18.0-305.3.1.el8_4
f48d8f
4.18.0-305.7.1.el8_4
f48d8f
4.18.0-305.10.2.el8_4
f48d8f
f48d8f
Changes since last build:
f48d8f
arches: x86_64 ppc64le
f48d8f
bcm.o: changed function: bcm_release
f48d8f
bcm.o: changed function: bcm_sendmsg
f48d8f
---------------------------
f48d8f
f48d8f
Kernels:
f48d8f
4.18.0-305.el8
f48d8f
4.18.0-305.3.1.el8_4
f48d8f
4.18.0-305.7.1.el8_4
f48d8f
4.18.0-305.10.2.el8_4
f48d8f
f48d8f
Modifications: none
f48d8f
f48d8f
commit 14c1d51567d0ef31ef900f6d1641615924fdb239
f48d8f
Author: Hangbin Liu <haliu@redhat.com>
f48d8f
Date:   Mon Jun 28 14:50:49 2021 +0800
f48d8f
f48d8f
    can: bcm: delay release of struct bcm_op after synchronize_rcu()
f48d8f
f48d8f
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1975058
f48d8f
    Y-Commit: fc088504ba6bee277b7bdc93ab0988b648bb8b81
f48d8f
f48d8f
    Upstream Status: net.git commit d5f9023fa61e
f48d8f
    CVE: CVE-2021-3609
f48d8f
    O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1975059
f48d8f
f48d8f
    commit d5f9023fa61ee8b94f37a93f08e94b136cf1e463
f48d8f
    Author: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
f48d8f
    Date:   Sat Jun 19 13:18:13 2021 -0300
f48d8f
f48d8f
        can: bcm: delay release of struct bcm_op after synchronize_rcu()
f48d8f
f48d8f
        can_rx_register() callbacks may be called concurrently to the call to
f48d8f
        can_rx_unregister(). The callbacks and callback data, though, are
f48d8f
        protected by RCU and the struct sock reference count.
f48d8f
f48d8f
        So the callback data is really attached to the life of sk, meaning
f48d8f
        that it should be released on sk_destruct. However, bcm_remove_op()
f48d8f
        calls tasklet_kill(), and RCU callbacks may be called under RCU
f48d8f
        softirq, so that cannot be used on kernels before the introduction of
f48d8f
        HRTIMER_MODE_SOFT.
f48d8f
f48d8f
        However, bcm_rx_handler() is called under RCU protection, so after
f48d8f
        calling can_rx_unregister(), we may call synchronize_rcu() in order to
f48d8f
        wait for any RCU read-side critical sections to finish. That is,
f48d8f
        bcm_rx_handler() won't be called anymore for those ops. So, we only
f48d8f
        free them, after we do that synchronize_rcu().
f48d8f
f48d8f
        Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol")
f48d8f
        Link: https://lore.kernel.org/r/20210619161813.2098382-1-cascardo@canonical.com
f48d8f
        Cc: linux-stable <stable@vger.kernel.org>
f48d8f
        Reported-by: syzbot+0f7e7e5e2f4f40fa89c0@syzkaller.appspotmail.com
f48d8f
        Reported-by: Norbert Slusarek <nslusarek@gmx.net>
f48d8f
        Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
f48d8f
        Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
f48d8f
        Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
f48d8f
f48d8f
    Signed-off-by: Hangbin Liu <haliu@redhat.com>
f48d8f
f48d8f
Signed-off-by: Artem Savkov <asavkov@redhat.com>
f48d8f
Acked-by: Joe Lawrence <joe.lawrence@redhat.com>
f48d8f
---
f48d8f
 net/can/bcm.c | 7 ++++++-
f48d8f
 1 file changed, 6 insertions(+), 1 deletion(-)
f48d8f
f48d8f
diff --git a/net/can/bcm.c b/net/can/bcm.c
f48d8f
index 0af8f0db892a3..4ee2fd682afaa 100644
f48d8f
--- a/net/can/bcm.c
f48d8f
+++ b/net/can/bcm.c
f48d8f
@@ -802,6 +802,7 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
f48d8f
 						  bcm_rx_handler, op);
f48d8f
 
f48d8f
 			list_del(&op->list);
f48d8f
+			synchronize_rcu();
f48d8f
 			bcm_remove_op(op);
f48d8f
 			return 1; /* done */
f48d8f
 		}
f48d8f
@@ -1527,9 +1528,13 @@ static int bcm_release(struct socket *sock)
f48d8f
 					  REGMASK(op->can_id),
f48d8f
 					  bcm_rx_handler, op);
f48d8f
 
f48d8f
-		bcm_remove_op(op);
f48d8f
 	}
f48d8f
 
f48d8f
+	synchronize_rcu();
f48d8f
+
f48d8f
+	list_for_each_entry_safe(op, next, &bo->rx_ops, list)
f48d8f
+		bcm_remove_op(op);
f48d8f
+
f48d8f
 #if IS_ENABLED(CONFIG_PROC_FS)
f48d8f
 	/* remove procfs entry */
f48d8f
 	if (net->can.bcmproc_dir && bo->bcm_proc_read)
f48d8f
-- 
f48d8f
2.26.3
f48d8f