Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm/mmap: Fix error path in do_vmi_align_munmap()

The error unrolling was leaving the VMAs detached in many cases and
leaving the locked_vm statistic altered, and skipping the unrolling
entirely in the case of the vma tree write failing.

Fix the error path by re-attaching the detached VMAs and adding the
necessary goto for the failed vma tree write, and fix the locked_vm
statistic by only updating after the vma tree write succeeds.

Fixes: 763ecb035029 ("mm: remove the vma linked list")
Reported-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Liam R. Howlett and committed by
Linus Torvalds
606c812e 1b29d271

+17 -20
+17 -20
mm/mmap.c
··· 2318 2318 return __split_vma(vmi, vma, addr, new_below); 2319 2319 } 2320 2320 2321 - static inline int munmap_sidetree(struct vm_area_struct *vma, 2322 - struct ma_state *mas_detach) 2323 - { 2324 - vma_start_write(vma); 2325 - mas_set_range(mas_detach, vma->vm_start, vma->vm_end - 1); 2326 - if (mas_store_gfp(mas_detach, vma, GFP_KERNEL)) 2327 - return -ENOMEM; 2328 - 2329 - vma_mark_detached(vma, true); 2330 - if (vma->vm_flags & VM_LOCKED) 2331 - vma->vm_mm->locked_vm -= vma_pages(vma); 2332 - 2333 - return 0; 2334 - } 2335 - 2336 2321 /* 2337 2322 * do_vmi_align_munmap() - munmap the aligned region from @start to @end. 2338 2323 * @vmi: The vma iterator ··· 2339 2354 struct maple_tree mt_detach; 2340 2355 int count = 0; 2341 2356 int error = -ENOMEM; 2357 + unsigned long locked_vm = 0; 2342 2358 MA_STATE(mas_detach, &mt_detach, 0, 0); 2343 2359 mt_init_flags(&mt_detach, vmi->mas.tree->ma_flags & MT_FLAGS_LOCK_MASK); 2344 2360 mt_set_external_lock(&mt_detach, &mm->mmap_lock); ··· 2385 2399 if (error) 2386 2400 goto end_split_failed; 2387 2401 } 2388 - error = munmap_sidetree(next, &mas_detach); 2389 - if (error) 2390 - goto munmap_sidetree_failed; 2402 + vma_start_write(next); 2403 + mas_set_range(&mas_detach, next->vm_start, next->vm_end - 1); 2404 + if (mas_store_gfp(&mas_detach, next, GFP_KERNEL)) 2405 + goto munmap_gather_failed; 2406 + vma_mark_detached(next, true); 2407 + if (next->vm_flags & VM_LOCKED) 2408 + locked_vm += vma_pages(next); 2391 2409 2392 2410 count++; 2393 2411 #ifdef CONFIG_DEBUG_VM_MAPLE_TREE ··· 2437 2447 } 2438 2448 #endif 2439 2449 /* Point of no return */ 2450 + error = -ENOMEM; 2440 2451 vma_iter_set(vmi, start); 2441 2452 if (vma_iter_clear_gfp(vmi, start, end, GFP_KERNEL)) 2442 - return -ENOMEM; 2453 + goto clear_tree_failed; 2443 2454 2455 + mm->locked_vm -= locked_vm; 2444 2456 mm->map_count -= count; 2445 2457 /* 2446 2458 * Do not downgrade mmap_lock if we are next to VM_GROWSDOWN or ··· 2472 2480 validate_mm(mm); 2473 2481 return downgrade ? 1 : 0; 2474 2482 2483 + clear_tree_failed: 2475 2484 userfaultfd_error: 2476 - munmap_sidetree_failed: 2485 + munmap_gather_failed: 2477 2486 end_split_failed: 2487 + mas_set(&mas_detach, 0); 2488 + mas_for_each(&mas_detach, next, end) 2489 + vma_mark_detached(next, false); 2490 + 2478 2491 __mt_destroy(&mt_detach); 2479 2492 start_split_failed: 2480 2493 map_count_exceeded: