vmalloc() is not allowed to be invoked from the NMI, hard-irq and softirq contexts because doing so may deadlock on internal locks. Commit 04aa71da5f35 ("mm/vmalloc: do not trigger BUG() on BH disabled context") replaced the deprecated in_interrupt() macro with explicit in_nmi() and in_hardirq() checks, but unintentionally dropped the softirq context check. Example: vzalloc() in a task spin_lock(&vn->busy.lock) <------ Hard irq irq_exit() process softirq on the same CPU vmalloc() spin_lock(&vn->busy.lock) spins forever Restore the check by checking the caller's context with the in_serving_softirq() helper. Note that, it is still allowed to invoke vmalloc() with disabled bottom halves. Replace BUG_ON() with WARN_ON_ONCE() for in_nmi() and in_hardirq() case. Cc: David Hildenbrand (Arm) Fixes: 04aa71da5f35 ("mm/vmalloc: do not trigger BUG() on BH disabled context") Signed-off-by: Uladzislau Rezki (Sony) --- mm/vmalloc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 7521b9b3bfd2..36e6e3be6ba4 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -3252,7 +3252,13 @@ struct vm_struct *__get_vm_area_node(unsigned long size, struct vm_struct *area; unsigned long requested_size = size; - BUG_ON(in_nmi() || in_hardirq()); + /* IRQ re-entrancy -> irq_exit() -> process softirq. */ + if (in_serving_softirq()) + return NULL; + + if (WARN_ON_ONCE(in_nmi() || in_hardirq())) + return NULL; + size = ALIGN(size, 1ul << shift); if (unlikely(!size)) return NULL; -- 2.47.3