Takashi Iwai 210d74
From 8d3c0c01cb2e36b2bf3c06a82b18b228d0c8f5d0 Mon Sep 17 00:00:00 2001
Takashi Iwai 210d74
From: Lukasz Bartosik <lb@semihalf.com>
Takashi Iwai 210d74
Date: Fri, 2 Apr 2021 00:51:48 +0200
Takashi Iwai 210d74
Subject: [PATCH] clk: fix invalid usage of list cursor in register
Takashi Iwai 210d74
Git-commit: 8d3c0c01cb2e36b2bf3c06a82b18b228d0c8f5d0
Takashi Iwai 210d74
Patch-mainline: v5.12-rc7
Takashi Iwai 210d74
References: git-fixes
Takashi Iwai 210d74
Takashi Iwai 210d74
Fix invalid usage of a list_for_each_entry cursor in
Takashi Iwai 210d74
clk_notifier_register(). When list is empty or if the list
Takashi Iwai 210d74
is completely traversed (without breaking from the loop on one
Takashi Iwai 210d74
of the entries) then the list cursor does not point to a valid
Takashi Iwai 210d74
entry and therefore should not be used.
Takashi Iwai 210d74
Takashi Iwai 210d74
The issue was dicovered when running 5.12-rc1 kernel on x86_64
Takashi Iwai 210d74
with KASAN enabled:
Takashi Iwai 210d74
Bug: KASAN: global-out-of-bounds in clk_notifier_register+0xab/0x230
Takashi Iwai 210d74
Read of size 8 at addr ffffffffa0d10588 by task swapper/0/1
Takashi Iwai 210d74
Takashi Iwai 210d74
Cpu: 1 PID: 1 Comm: swapper/0 Not tainted 5.12.0-rc1 #1
Takashi Iwai 210d74
Hardware name: Google Caroline/Caroline,
Takashi Iwai 210d74
BIOS Google_Caroline.7820.430.0 07/20/2018
Takashi Iwai 210d74
Call Trace:
Takashi Iwai 210d74
 dump_stack+0xee/0x15c
Takashi Iwai 210d74
 print_address_description+0x1e/0x2dc
Takashi Iwai 210d74
 kasan_report+0x188/0x1ce
Takashi Iwai 210d74
 ? clk_notifier_register+0xab/0x230
Takashi Iwai 210d74
 ? clk_prepare_lock+0x15/0x7b
Takashi Iwai 210d74
 ? clk_notifier_register+0xab/0x230
Takashi Iwai 210d74
 clk_notifier_register+0xab/0x230
Takashi Iwai 210d74
 dw8250_probe+0xc01/0x10d4
Takashi Iwai 210d74
...
Takashi Iwai 210d74
Memory state around the buggy address:
Takashi Iwai 210d74
 ffffffffa0d10480: 00 00 00 00 00 03 f9 f9 f9 f9 f9 f9 00 00 00 00
Takashi Iwai 210d74
 ffffffffa0d10500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f9 f9
Takashi Iwai 210d74
>ffffffffa0d10580: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00                      ^ ffffffffa0d10600: 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 00 00 00 00 ffffffffa0d10680: 00 00 00 00 00 00 00 00 f9 f9 f9 f9 00 00 00 00 ==================================================================
Takashi Iwai 210d74
Takashi Iwai 210d74
Fixes: b2476490ef11 ("clk: introduce the common clock framework")
Takashi Iwai 210d74
Reported-by: Lukasz Majczak <lma@semihalf.com>
Takashi Iwai 210d74
Signed-off-by: Lukasz Bartosik <lb@semihalf.com>
Takashi Iwai 210d74
Link: https://lore.kernel.org/r/20210401225149.18826-1-lb@semihalf.com
Takashi Iwai 210d74
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Takashi Iwai 210d74
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 210d74
Takashi Iwai 210d74
---
Takashi Iwai 210d74
 drivers/clk/clk.c | 17 ++++++++---------
Takashi Iwai 210d74
 1 file changed, 8 insertions(+), 9 deletions(-)
Takashi Iwai 210d74
Takashi Iwai 210d74
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
Takashi Iwai 210d74
index 5052541a0986..16634d5912be 100644
Takashi Iwai 210d74
--- a/drivers/clk/clk.c
Takashi Iwai 210d74
+++ b/drivers/clk/clk.c
Takashi Iwai 210d74
@@ -4357,20 +4357,19 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
Takashi Iwai 210d74
 	/* search the list of notifiers for this clk */
Takashi Iwai 210d74
 	list_for_each_entry(cn, &clk_notifier_list, node)
Takashi Iwai 210d74
 		if (cn->clk == clk)
Takashi Iwai 210d74
-			break;
Takashi Iwai 210d74
+			goto found;
Takashi Iwai 210d74
 
Takashi Iwai 210d74
 	/* if clk wasn't in the notifier list, allocate new clk_notifier */
Takashi Iwai 210d74
-	if (cn->clk != clk) {
Takashi Iwai 210d74
-		cn = kzalloc(sizeof(*cn), GFP_KERNEL);
Takashi Iwai 210d74
-		if (!cn)
Takashi Iwai 210d74
-			goto out;
Takashi Iwai 210d74
+	cn = kzalloc(sizeof(*cn), GFP_KERNEL);
Takashi Iwai 210d74
+	if (!cn)
Takashi Iwai 210d74
+		goto out;
Takashi Iwai 210d74
 
Takashi Iwai 210d74
-		cn->clk = clk;
Takashi Iwai 210d74
-		srcu_init_notifier_head(&cn->notifier_head);
Takashi Iwai 210d74
+	cn->clk = clk;
Takashi Iwai 210d74
+	srcu_init_notifier_head(&cn->notifier_head);
Takashi Iwai 210d74
 
Takashi Iwai 210d74
-		list_add(&cn->node, &clk_notifier_list);
Takashi Iwai 210d74
-	}
Takashi Iwai 210d74
+	list_add(&cn->node, &clk_notifier_list);
Takashi Iwai 210d74
 
Takashi Iwai 210d74
+found:
Takashi Iwai 210d74
 	ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
Takashi Iwai 210d74
 
Takashi Iwai 210d74
 	clk->core->notifier_count++;
Takashi Iwai 210d74
-- 
Takashi Iwai 210d74
2.26.2
Takashi Iwai 210d74