Blob Blame History Raw
From ee8a41cd30a99b39bd5d46280cc778e275cd2390 Mon Sep 17 00:00:00 2001
From: Fred Oh <fred.oh@linux.intel.com>
Date: Mon, 22 Jun 2020 10:13:48 -0500
Subject: [PATCH] ASoC: rt1011: fix KASAN out-of-bounds bug in find_next_bit()
Git-commit: ee8a41cd30a99b39bd5d46280cc778e275cd2390
Patch-mainline: v5.9-rc1
References: jsc#SLE-16518

KASAN throws the following warning in rt1011.c:
[ 170.777603] BUG: KASAN: stack-out-of-bounds in _find_next_bit.constprop.0+0x3e/0xf0

find_next_bit() relies on unsigned long pointer arguments, but this driver
uses a type cast that generates the KASAN warning. Replace find_next_bit()
and find_last_bit() with __ffs() and __fls() to pass the value and avoid
casting pointers to make the warning go away.

Signed-off-by: Fred Oh <fred.oh@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Link: https://lore.kernel.org/r/20200622151348.28063-1-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 sound/soc/codecs/rt1011.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c
index dec5638060c3..098ecf13814d 100644
--- a/sound/soc/codecs/rt1011.c
+++ b/sound/soc/codecs/rt1011.c
@@ -1849,13 +1849,13 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
 
 	/* Rx slot configuration */
 	rx_slotnum = hweight_long(rx_mask);
-	first_bit = find_next_bit((unsigned long *)&rx_mask, 32, 0);
-	if (rx_slotnum > 1 || rx_slotnum == 0) {
+	if (rx_slotnum > 1 || !rx_slotnum) {
 		ret = -EINVAL;
-		dev_dbg(component->dev, "too many rx slots or zero slot\n");
+		dev_err(component->dev, "too many rx slots or zero slot\n");
 		goto _set_tdm_err_;
 	}
 
+	first_bit = __ffs(rx_mask);
 	switch (first_bit) {
 	case 0:
 	case 2:
@@ -1892,11 +1892,17 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
 
 	/* Tx slot configuration */
 	tx_slotnum = hweight_long(tx_mask);
-	first_bit = find_next_bit((unsigned long *)&tx_mask, 32, 0);
-	last_bit = find_last_bit((unsigned long *)&tx_mask, 32);
-	if (tx_slotnum > 2 || (last_bit-first_bit) > 1) {
+	if (tx_slotnum > 2 || !tx_slotnum) {
 		ret = -EINVAL;
-		dev_dbg(component->dev, "too many tx slots or tx slot location error\n");
+		dev_err(component->dev, "too many tx slots or zero slot\n");
+		goto _set_tdm_err_;
+	}
+
+	first_bit = __ffs(tx_mask);
+	last_bit = __fls(tx_mask);
+	if (last_bit - first_bit > 1) {
+		ret = -EINVAL;
+		dev_err(component->dev, "tx slot location error\n");
 		goto _set_tdm_err_;
 	}
 
-- 
2.16.4