All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnd Bergmann <arnd@kernel.org>
To: Vinod Koul <vkoul@kernel.org>,
	Maxime Coquelin <mcoquelin.stm32@gmail.com>,
	Alexandre Torgue <alexandre.torgue@foss.st.com>,
	Amelie Delaunay <amelie.delaunay@foss.st.com>,
	Pierre Yves MORDRET <pierre-yves.mordret@st.com>,
	"M'boumba Cedric Madianga" <cedric.madianga@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>,
	dmaengine@vger.kernel.org,
	linux-stm32@st-md-mailman.stormreply.com,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH] dmaengine: stm32-dma: avoid bitfield overflow assertion
Date: Tue, 14 Feb 2023 11:32:13 +0100	[thread overview]
Message-ID: <20230214103222.1193307-1-arnd@kernel.org> (raw)

From: Arnd Bergmann <arnd@arndb.de>

stm32_dma_get_burst() returns a negative error code for invalid
input, which gets turned into a large u32 value in stm32_dma_prep_dma_memcpy()
that in turn triggers an assertion because it does not fit into a
two-bit field:

drivers/dma/stm32-dma.c: In function 'stm32_dma_prep_dma_memcpy':
include/linux/compiler_types.h:399:38: error: call to '__compiletime_assert_310' declared with attribute error: FIELD_PREP: value too large for the field
  399 |  _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
      |                                      ^
include/linux/compiler_types.h:380:4: note: in definition of macro '__compiletime_assert'
  380 |    prefix ## suffix();    \
      |    ^~~~~~
include/linux/compiler_types.h:399:2: note: in expansion of macro '_compiletime_assert'
  399 |  _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
      |  ^~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
   39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
      |                                     ^~~~~~~~~~~~~~~~~~
include/linux/bitfield.h:68:3: note: in expansion of macro 'BUILD_BUG_ON_MSG'
   68 |   BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ?  \
      |   ^~~~~~~~~~~~~~~~
include/linux/bitfield.h:114:3: note: in expansion of macro '__BF_FIELD_CHECK'
  114 |   __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \
      |   ^~~~~~~~~~~~~~~~
drivers/dma/stm32-dma.c:1273:4: note: in expansion of macro 'FIELD_PREP'
 1273 |    FIELD_PREP(STM32_DMA_SCR_PBURST_MASK, dma_burst) |
      |    ^~~~~~~~~~

I only see this with older gcc versions like gcc-6.5 or gcc-9.5 but not
with gcc-12.2 or higher. My best guess is that this is the result of
changes to __builtin_constant_p(), which seems to treat the 'cold'
codepath after an error message as a constant branch, while in newer
gcc versions the range check is skipped after determining that
dma_burst is never a compile-time constant.

As an easy workaround, assume the error can happen, so try to handle this
by failing stm32_dma_prep_dma_memcpy() before the assertion.

Fixes: 1c32d6c37cc2 ("dmaengine: stm32-dma: use bitfield helpers")
Fixes: a2b6103b7a8a ("dmaengine: stm32-dma: Improve memory burst management")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/dma/stm32-dma.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index 37674029cb42..e3cd4b0525e6 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -1266,6 +1266,10 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
 		best_burst = stm32_dma_get_best_burst(len, STM32_DMA_MAX_BURST,
 						      threshold, max_width);
 		dma_burst = stm32_dma_get_burst(chan, best_burst);
+		if (dma_burst > 3) {
+			kfree(desc);
+			return NULL;
+		}
 
 		stm32_dma_clear_reg(&desc->sg_req[i].chan_reg);
 		desc->sg_req[i].chan_reg.dma_scr =
-- 
2.39.1


WARNING: multiple messages have this Message-ID (diff)
From: Arnd Bergmann <arnd@kernel.org>
To: Vinod Koul <vkoul@kernel.org>,
	Maxime Coquelin <mcoquelin.stm32@gmail.com>,
	Alexandre Torgue <alexandre.torgue@foss.st.com>,
	Amelie Delaunay <amelie.delaunay@foss.st.com>,
	Pierre Yves MORDRET <pierre-yves.mordret@st.com>,
	"M'boumba Cedric Madianga" <cedric.madianga@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>,
	dmaengine@vger.kernel.org,
	linux-stm32@st-md-mailman.stormreply.com,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH] dmaengine: stm32-dma: avoid bitfield overflow assertion
Date: Tue, 14 Feb 2023 11:32:13 +0100	[thread overview]
Message-ID: <20230214103222.1193307-1-arnd@kernel.org> (raw)

From: Arnd Bergmann <arnd@arndb.de>

stm32_dma_get_burst() returns a negative error code for invalid
input, which gets turned into a large u32 value in stm32_dma_prep_dma_memcpy()
that in turn triggers an assertion because it does not fit into a
two-bit field:

drivers/dma/stm32-dma.c: In function 'stm32_dma_prep_dma_memcpy':
include/linux/compiler_types.h:399:38: error: call to '__compiletime_assert_310' declared with attribute error: FIELD_PREP: value too large for the field
  399 |  _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
      |                                      ^
include/linux/compiler_types.h:380:4: note: in definition of macro '__compiletime_assert'
  380 |    prefix ## suffix();    \
      |    ^~~~~~
include/linux/compiler_types.h:399:2: note: in expansion of macro '_compiletime_assert'
  399 |  _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
      |  ^~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
   39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
      |                                     ^~~~~~~~~~~~~~~~~~
include/linux/bitfield.h:68:3: note: in expansion of macro 'BUILD_BUG_ON_MSG'
   68 |   BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ?  \
      |   ^~~~~~~~~~~~~~~~
include/linux/bitfield.h:114:3: note: in expansion of macro '__BF_FIELD_CHECK'
  114 |   __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \
      |   ^~~~~~~~~~~~~~~~
drivers/dma/stm32-dma.c:1273:4: note: in expansion of macro 'FIELD_PREP'
 1273 |    FIELD_PREP(STM32_DMA_SCR_PBURST_MASK, dma_burst) |
      |    ^~~~~~~~~~

I only see this with older gcc versions like gcc-6.5 or gcc-9.5 but not
with gcc-12.2 or higher. My best guess is that this is the result of
changes to __builtin_constant_p(), which seems to treat the 'cold'
codepath after an error message as a constant branch, while in newer
gcc versions the range check is skipped after determining that
dma_burst is never a compile-time constant.

As an easy workaround, assume the error can happen, so try to handle this
by failing stm32_dma_prep_dma_memcpy() before the assertion.

Fixes: 1c32d6c37cc2 ("dmaengine: stm32-dma: use bitfield helpers")
Fixes: a2b6103b7a8a ("dmaengine: stm32-dma: Improve memory burst management")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/dma/stm32-dma.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index 37674029cb42..e3cd4b0525e6 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -1266,6 +1266,10 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
 		best_burst = stm32_dma_get_best_burst(len, STM32_DMA_MAX_BURST,
 						      threshold, max_width);
 		dma_burst = stm32_dma_get_burst(chan, best_burst);
+		if (dma_burst > 3) {
+			kfree(desc);
+			return NULL;
+		}
 
 		stm32_dma_clear_reg(&desc->sg_req[i].chan_reg);
 		desc->sg_req[i].chan_reg.dma_scr =
-- 
2.39.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

             reply	other threads:[~2023-02-14 10:32 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-14 10:32 Arnd Bergmann [this message]
2023-02-14 10:32 ` [PATCH] dmaengine: stm32-dma: avoid bitfield overflow assertion Arnd Bergmann
2023-02-15  8:51 ` Amelie Delaunay
2023-02-15  8:51   ` Amelie Delaunay

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230214103222.1193307-1-arnd@kernel.org \
    --to=arnd@kernel.org \
    --cc=alexandre.torgue@foss.st.com \
    --cc=amelie.delaunay@foss.st.com \
    --cc=arnd@arndb.de \
    --cc=cedric.madianga@gmail.com \
    --cc=dmaengine@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-stm32@st-md-mailman.stormreply.com \
    --cc=mcoquelin.stm32@gmail.com \
    --cc=pierre-yves.mordret@st.com \
    --cc=vkoul@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.