From: Geliang Tang <[email protected]>

The `gfp` parameter of alloc_buf() has been dead code since the
function was introduced. The underlying allocation was always
hardcoded to GFP_KERNEL - first via kmalloc(..., GFP_KERNEL), then
via kmalloc_flex(*buf, sg, pages, GFP_KERNEL), and most recently
via kmalloc_flex(*buf, sg, pages) which defaults to GFP_KERNEL.

This causes a "sleeping function called from invalid context" BUG
when the hvc console flush path calls put_chars() with IRQs
disabled:

  BUG: sleeping function called from invalid context at \
       include/linux/sched/mm.h:322
  in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 416, \
               name: test_progs
  ...
  Call Trace:
   __kmalloc_noprof+0x468/0x7c0
   alloc_buf.isra.0+0x42/0x260
   put_chars+0x1e5/0x2f0
   hvc_console_print+0x29d/0x6e0
   console_emit_next_record+0x21d/0x480
   console_flush_one_record+0x431/0x6a0
   console_unlock+0xda/0x1c0
   vprintk_emit+0x300/0x350

put_chars() correctly passes GFP_ATOMIC, but alloc_buf() silently
discards it and allocates with GFP_KERNEL, which may sleep.

Pass the caller-supplied gfp flag through to kmalloc_flex() so
that atomic callers get atomic allocations.

Fixes: 69050f8d6d07 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar 
types")
Signed-off-by: Geliang Tang <[email protected]>
---
 drivers/char/virtio_console.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 62eecfa61646..7f6cbe851d1e 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -426,7 +426,7 @@ static struct port_buffer *alloc_buf(struct virtio_device 
*vdev, size_t buf_size
         * Allocate buffer and the sg list. The sg list array is allocated
         * directly after the port_buffer struct.
         */
-       buf = kmalloc_flex(*buf, sg, pages);
+       buf = kmalloc_flex(*buf, sg, pages, gfp);
        if (!buf)
                goto fail;
 
-- 
2.53.0


Reply via email to