Re: [RFC PATCH] cw1200: use kmalloc() allocation instead of stack
From: Arnd Bergmann <arnd@arndb.de>
Date: 2021-06-30 11:30:57
Also in:
linux-wireless, lkml
Subsystem:
multimedia card (mmc), secure digital (sd) and sdio subsystem, the rest · Maintainers:
Ulf Hansson, Linus Torvalds
On Wed, Jun 30, 2021 at 11:56 AM Ulf Hansson [off-list ref] wrote:
On Tue, 22 Jun 2021 at 22:33, Arnd Bergmann [off-list ref] wrote:quoted
On Tue, Jun 22, 2021 at 10:24 PM Jernej Skrabec [off-list ref] wrote:quoted
It turns out that if CONFIG_VMAP_STACK is enabled and src or dst is memory allocated on stack, SDIO operations fail due to invalid memory address conversion:Thank you for sending this! It's worth pointing out that even without CONFIG_VMAP_STACK, using dma_map_sg() on a stack variable is broken, though it will appear to work most of the time but rarely cause a stack data corruption when the cache management goes wrong. This clearly needs to be fixed somewhere, if not with your patch, then a similar one.quoted
diff --git a/drivers/net/wireless/st/cw1200/hwio.c b/drivers/net/wireless/st/cw1200/hwio.c index 3ba462de8e91..5521cb7f2233 100644 --- a/drivers/net/wireless/st/cw1200/hwio.c +++ b/drivers/net/wireless/st/cw1200/hwio.c@@ -66,33 +66,65 @@ static int __cw1200_reg_write(struct cw1200_common *priv, u16 addr, static inline int __cw1200_reg_read_32(struct cw1200_common *priv, u16 addr, u32 *val) { - __le32 tmp; - int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0); - *val = le32_to_cpu(tmp); + __le32 *tmp; + int i; + + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + i = __cw1200_reg_read(priv, addr, tmp, sizeof(*tmp), 0); + *val = le32_to_cpu(*tmp); + kfree(tmp); return i; }There is a possible problem here when the function gets called from atomic context, so it might need to use GFP_ATOMIC instead of GFP_KERNEL. If it's never called from atomic context, then this patch looks correct to me.I would be surprised if this is called from atomic context (when IRQs are turned off), because in most cases, to complete the read/write request the mmc controller driver relies on IRQs being delivered.
I thought I had seen a spinlock in the forked driver, but I don't see it now, so I probably misremembered that bit.
quoted
The alternative would be to add a bounce buffer check based on is_vmalloc_or_module_addr() in sdio_io_rw_ext_helper(), which would add a small bit of complexity there but solve the problem for all drivers at once. In this case, it would probably have to use GFP_ATOMIC regardless of whether __cw1200_reg_read_32() is allowed to sleep, since other callers might not.I like the idea, but... I don't think we should see this as an alternative, but rather as a complement which would have performance issues. A warning should be printed, if the buffer isn't properly allocated.
Fair enough. I found the function call I was looking for: object_is_on_stack(), the patch below should print a warning once when a driver passes a bad buffer, but I did not test that. There are some possible variations on that: an on-stack buffer by itself can work as long as the DMA is cache-coherent and stacks are not vmapped. For the is_vmalloc_or_module_addr() case, we may decide to just return an error, rather than running into a kernel oops.
Additionally, I don't think GFT_ATOMIC should be needed.
Ok, I now see the mmc_wait_for_req() in mmc_io_rw_extended()
that probably means it can not be called in atomic context at all,
and that GFP_KERNEL is safe, and that any driver calling it with
a spinlock held is already broken.
Arnd
8<---diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index 4c229dd2b6e5..845f9ca3b200 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c@@ -124,6 +124,7 @@ int mmc_io_rw_extended(struct mmc_card *card, intwrite, unsigned fn,
int err;
WARN_ON(blksz == 0);
+ WARN_ON_ONCE(is_vmalloc_or_module_addr(buf) || object_is_on_stack(buf));
/* sanity check */
if (addr & ~0x1FFFF)