From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 025C03B9952 for ; Wed, 8 Jul 2026 05:28:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.170 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783488507; cv=none; b=DYKAaoRoZO21fE6nxVu19s2Qf8DvXgYhvdVdr4UwwxAVkoDT8Ge6z31vcSMkmMN3+w48gJVToVo+eWSg/KPhyBAvhLDx9wkJenP5uCvOfDXCOot7E7Lr4+NOvhwbcW80L/gejZk6IP13uzXB/X31TMTAj9o3igvwMEq3FqAo6kw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783488507; c=relaxed/simple; bh=lkTMrtvO/zfQfcOrT2saigFCc3hXwgFESBoVZlTzTtA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=lwIY6tUeoC0hiZYVrMhCZSeZDp7/J5Njrvu/1ZpzOquPSikZBIXOrKwz+yZdS15IP1/Tv6YqdlX9/80tiva0UNBto3wq3VAy8IiA1ZUZMGEenKOjwjRKHa+79I8xPvWLTtRvLWGUed48tSZEIS+qAgNcapuIFTUp4J8R8XOflVs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=aB7wOZjY; arc=none smtp.client-ip=209.85.214.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aB7wOZjY" Received: by mail-pl1-f170.google.com with SMTP id d9443c01a7336-2cce6a0c9c3so3371005ad.1 for ; Tue, 07 Jul 2026 22:28:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783488505; x=1784093305; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=r8c658LFrC5kUpw1BBMNZ+UryPir01aUoDyxaQYNE1A=; b=aB7wOZjYbvYIPZ2Orx4i4gigblCwoag5fXFzIML5skZxHuCfyL0PtdaZY/str0le7H VIweYqRQbjfCla2OfSbfe5a7y4H9GprUaP0FORfT59K1ehzTyPwOP2HMrnpXt5AszWDo FILEg2MvfB9cJiGQXu+ors182ecDnt4GbXznlrYmBgVQj//g6fI5/VYXnrZxiqME8E05 xAXhpOKtYVwhaxdoNimvCapa0ne6AMDyxIwL2ta9vrjqfN19jR+Uyo20uPxLhDjnyT+H 4McvoA8tx9UiIuJ6POzpPvjzrvuT3ivFYLhQWXaggEdgLTqOECXw1I8bi/gJooRSptv5 sM0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783488505; x=1784093305; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=r8c658LFrC5kUpw1BBMNZ+UryPir01aUoDyxaQYNE1A=; b=pJWOLSvnnQebU4OAX5xBz5e83n05lkm1ypCxk5vKc9WeuD0JbVKJf8rDfk6FNm/BS2 3o4uAhMR5Uk/FIOo+N1o5et2s8yypRP/5TAO5oD9lvPYBxqA9dAVw28vQoxT3SLLYnXR l0P24kMlFwdLpQ5osWDCTLus2Xnhem9d6d/FQK7PoP/rajaIZoGGDsCJ4WVUm9G0M6OC TsUvb1e8yEfjRYvu4pzWD2ATngjZiQb0UeM7kYx4bWlAJL2dw+vYNY9m1fy2jOaRdFEq lhL3G8dwmx5cAnkkPsFavGpGNbfqL0W1El2CT+0OotSH9xdWHVQk84FUvNluA/saGAz0 87bg== X-Gm-Message-State: AOJu0Yyr0Lxr2lsadgiA1mvEEPdNJHF70jfc911dXUZDULTXtiuaXz8A uD23DVr42I+zsILITFz7xvtwt4gE6ALBRmJ+TZ2yZVaLsqSzpWd7I2ch X-Gm-Gg: AfdE7cke8cCkERqCfw8rE2pkWM8YQkktnt+mS+gH0DX3Jcand6zoP7LAEEvffaWQ3/l 7AWRBhOc+pQlfy/zvehUVfWzvfNuIiQ8NRYxP5n0gGoGaZbK0HDOmpP2YY36i8ZIL7sbc+2kJh1 x5Luiq0UJSMfPK6Lzf2IEfr91ii1xtckFhgUlSJjKLosF90+HjNQn6J/kkX0jH1Zvsl46HYbj9E rQHjLmkt1fP9xoB4opshebEs+g0tTuni0chInX1ftFhI1fD5gD/F1xuC5s/DkOfut6Ccnd21eis aJQlPRVjNNX0+q5Za1JfTuU3aGLwqRaKNuMu/nzb2k763RRc079Zau6J/L2SFiTctjglKURvLl6 MWzzImPf/QrZGJ8+i1t+wDQgp+zjrN86cyUgmQ5gLWVvkl3fFAsoo+IWdRKhclQmI8kemFa6uWF xdxtBCzCw+9ymbxa2d07We8Aq7p81plY1mvydM+3oz19dQ5yyr5xN6v+VyfGqX6zNc3XEUrrWQA zJT4ED81JeybV7rlA== X-Received: by 2002:a05:6a21:4910:b0:3bf:b08a:cded with SMTP id adf61e73a8af0-3c0bce9caf9mr1052310637.37.1783488505083; Tue, 07 Jul 2026 22:28:25 -0700 (PDT) Received: from ikb-h07-29-noble.in.iijlab.net ([202.214.97.5]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-ca75ef0c30dsm181962a12.17.2026.07.07.22.28.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jul 2026 22:28:24 -0700 (PDT) Received: by ikb-h07-29-noble.in.iijlab.net (Postfix, from userid 1010) id 34172148FCB3; Wed, 8 Jul 2026 14:28:23 +0900 (JST) From: Hajime Tazaki To: akpm@linux-foundation.org, liam@infradead.org, ljs@kernel.org, vbabka@kernel.org, jannh@google.com, pfalcato@suse.de, linux-mm@kvack.org, geert@linux-m68k.org Cc: linux-kernel@vger.kernel.org, Hajime Tazaki Subject: [PATCH v2] mm: nommu: fix the error path when vma_iter_prealloc() fails Date: Wed, 8 Jul 2026 14:28:20 +0900 Message-ID: <20260708052820.556085-1-thehajime@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit When vma_iter_prealloc() fails in do_mmap(), it jumps to error_just_free as a error path of this function, but there are several possible issues. 1) It jumps to error_just_free without updating ret to -ENOMEM, meaning do_mmap() will return 0 on failure. 2) The error path unconditionally frees the region struct. Since the region was already added to the global nommu_region_tree via add_nommu_region(), leaving it makes a potential dangling pointer in the tree and may cause a use-after-free on the next tree walk. 3) If do_mmap() finds an existing overlapping shared region, it increments its usage, sets region to this existing pregion, and jumps to share: region = pregion; result = start; goto share; When vma_iter_prealloc() fails and jumps to error_just_free, the error path unconditionally frees the region: error: ... if (region->vm_file) fput(region->vm_file); kmem_cache_free(vm_region_jar, region); This potentially leaves a dangling pointer in nommu_region_tree and causes RB-tree corruption. 4) When establishing a new private mapping, do_mmap_private() allocates physical pages and assigns them to region->vm_start: base = alloc_pages_exact(total << PAGE_SHIFT, GFP_KERNEL); ... region->vm_start = (unsigned long) base; If we later fail at vma_iter_prealloc() and jump to error_just_free, the region struct is freed, but the backing physical memory isn't freed via free_page_series(). 5) In the error label of do_mmap(), the vm_area_struct allocated is freed by vm_area_free(vma) but not called after vma_close(), leaving potential memory leak which should be handled by a custom .close handler of vm_ops. This commit fixes those issues by introducing new jump label, error_vma_iter_prealloc, to correctly handle the error case of vma_iter_prealloc(), updating ret value (1), and move the region updates after the place that the allocation is finished (2). Additionally, the commit removes the existing goto label, error, and consolidates to error_just_free as existing `goto error;` code blocks always release nommu_region_sem. Moreover, it only frees region allocated in this request to avoid freeing the shared, existing region shared by other processes (3), and free physical memory when do_mmap_private() allocates (4). It also add vma_close() before vm_area_free() to fix the potential leak (5). Those issues are discovered by Sashiko, linked below. Link: https://sashiko.dev/#/patchset/20260702012830.667205-1-thehajime%40gmail.com Link: https://sashiko.dev/#/patchset/c8513ee5aa8444ec9bf6c276043c9f833016a2fa.1783304131.git.thehajime%40gmail.com Link: https://sashiko.dev/#/patchset/20260707235137.498738-1-thehajime%40gmail.com Fixes: b5df09226450 ("mm: set up vma iterator for vma_iter_prealloc() calls") Signed-off-by: Hajime Tazaki -- v2: consolidate commits into a single patch, address additional Sashiko review (sorry for the noise: i have no working local environment of sashiko/gemini) v1: https://lore.kernel.org/linux-mm/20260707235137.498738-1-thehajime@gmail.com/T/#t --- mm/nommu.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/mm/nommu.c b/mm/nommu.c index 815ebefddfae..cbab1fe22be9 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1181,7 +1181,6 @@ unsigned long do_mmap(struct file *file, ret = do_mmap_private(vma, region, len, capabilities); if (ret < 0) goto error_just_free; - add_nommu_region(region); /* clear anonymous mappings that don't ask for uninitialized data */ if (!vma->vm_file && @@ -1199,7 +1198,9 @@ unsigned long do_mmap(struct file *file, BUG_ON(!vma->vm_region); vma_iter_config(&vmi, vma->vm_start, vma->vm_end); if (vma_iter_prealloc(&vmi, vma)) - goto error_just_free; + goto error_vma_iter_prealloc; + + add_nommu_region(region); setup_vma_to_mm(vma, current->mm); current->mm->map_count++; @@ -1218,22 +1219,41 @@ unsigned long do_mmap(struct file *file, return result; error_just_free: + /* if the error was from shared mapping/existing region, don't free the region. + * this has to be before releasing semaphore. + */ + if (region->vm_usage == 1) { + if (region->vm_file) + fput(region->vm_file); + kmem_cache_free(vm_region_jar, region); + + } else + region->vm_usage--; + up_write(&nommu_region_sem); -error: vma_iter_free(&vmi); - if (region->vm_file) - fput(region->vm_file); - kmem_cache_free(vm_region_jar, region); + + vma_close(vma); if (vma->vm_file) fput(vma->vm_file); vm_area_free(vma); return ret; sharing_violation: - up_write(&nommu_region_sem); pr_warn("Attempt to share mismatched mappings\n"); ret = -EINVAL; - goto error; + goto error_just_free; + +error_vma_iter_prealloc: + pr_warn("Allocation of vma iterator for process %d failed\n", current->pid); + show_mem(); + ret = -ENOMEM; + + /* in case that the region is allocated via do_mmap_private() */ + if ((region->vm_usage == 1) && (region->vm_flags & VM_MAPPED_COPY)) + free_page_series(region->vm_start, region->vm_top); + + goto error_just_free; error_getting_vma: kmem_cache_free(vm_region_jar, region); -- 2.43.0