summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Mason <mason@kernel.org>2026-10-31 10:40:06 +0100
committerDavid Hildenbrand (Arm) <david@kernel.org>2026-11-03 20:20:53 +0100
commit9f02ca8c15a74bc9e4e8e05ec089f63cb87cbf75 (patch)
treea163746c12739327d0fb0d6e3007334d3707fa06
parent7a81bc23dade8082187be6d9cc36e4be4b7207e2 (diff)
mm: fix unkillable fault loop on MAP_DROPPABLE memory
handle_mm_fault() suppresses VM_FAULT_OOM for VM_DROPPABLE mappings. For user-mode faults, pending signals are processed before retrying the access. Kernel-mode faults on user buffers instead return directly to the faulting instruction. With persistent allocation failures (esp. memcg limits), a syscall, such as write(), can therefore loop while not dropping locks. Only suppress VM_FAULT_OOM when FAULT_FLAG_USER is set, allowing kernel-mode faults and GUP to fail and signal allocation errors. Fix generated by an LLM and sent by Chris Mason in private. Fixes: 9651fcedf7b9 ("mm: add MAP_DROPPABLE for designating always lazily freeable mappings") Cc: stable@vger.kernel.org Signed-off-by: Chris Mason <mason@kernel.org> Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> [ david: simplify description ] Tested-by: Muhammad Usama Anjum <usama.anjum@arm.com> Link: https://patch.msgid.link/20261031-fixes_core-v3-37-d6437171ecc3@kernel.org Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
-rw-r--r--mm/memory.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 732b8f926de6..77d4bbf444bc 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -6957,8 +6957,12 @@ vm_fault_t handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
lru_gen_exit_fault();
- /* If the mapping is droppable, then errors due to OOM aren't fatal. */
- if (is_droppable)
+ /*
+ * If the mapping is droppable, then errors due to OOM aren't fatal: the
+ * task returns to user mode, handles its signals and tries again. A
+ * fault from kernel mode has no such return, so it must see the error.
+ */
+ if (is_droppable && (flags & FAULT_FLAG_USER))
ret &= ~VM_FAULT_OOM;
if (flags & FAULT_FLAG_USER) {