Blame SOURCES/CVE-2021-3609.patch

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