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