From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (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 50D8E33993 for ; Sun, 5 Jul 2026 17:51:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783273882; cv=none; b=uufM+5WNEYPLImSTqUkW5hW3ekZ+YC9L/G8fXq+dSK0/ZVWfly13k6gqXQlBR3gAufceh1nW9+amrLIWFApcZQ3jAZxnc3/f+Th54ZrhlJGh4VvkmwtDtgjGmQfBTjOWNKjSFdYBLzfKC/nt4q0aU06gFGh2sN8vVM5hKm7LVAI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783273882; c=relaxed/simple; bh=yGMOcgSSnwdfeGlCYuSo4QT353qVF28AI7kGYtRvJXI=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=ubLVSDMHH96PASiDbBO89IHix0wrPwAwDX7xwwr8NclNLMszjZbJ8+1uvUd0OELNpt3ap1Qu8U1UbbR66HB1oTmcw5qTaaVa8fhCgN5J3PAvt26PT77ZsJl0RcvV8V2SQRU5iQB2revT40FRCKNEtm42Ycdv2xBraGsqk+wcVA4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--souravpanda.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=PTyAEYEU; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--souravpanda.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="PTyAEYEU" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2c9ed5caa3bso31041635ad.1 for ; Sun, 05 Jul 2026 10:51:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1783273880; x=1783878680; darn=vger.kernel.org; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=hU/ax1hlB16SHvksohVR+E9FqY3jSZbakNJJzt+UJ7s=; b=PTyAEYEU/MljEEaOE7CDABO/K/BvwW9zSX1vqRiUV3iZ8DnoVOp9bnVwyjEhEUPAU5 Uo3TIrS4hXdre3KKSrQWIApisF5NB2Gh3sflOz7P8sovSxVlU3CFj657jcq5Fi6T1plA X/CCZPeDLvmrEbUHwhjPCByEF0UPazvbj4/uwlgf/vRdOM57IAIgBJOtUwEvSCjwKMrR OKvzfPW90TTYehEO5otyOJXtBYVC4v7uzP10in+LBO6blekIIecrZHl43s4DawS/NmAx Vr321QSi6AwOUtLTpTv4JM+xXjestvDyXeel6skOOeCXRMbr603diyeicIaXeJqGBj/W FzLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783273880; x=1783878680; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=hU/ax1hlB16SHvksohVR+E9FqY3jSZbakNJJzt+UJ7s=; b=DgO7/d6CyVUPqZ9cVTVW2ITP5IX1VOj8nBh6fmSN2UthgD1C3JNHXRlC1OAT4nnu9e wInEVNbL/wD0qh6simn1Wwd/Phf5JMmj934iGJfw1vEx8842dJQrBqY5wl1IrOstjY0p 5NAVcmGI5zlF9g+wrMKZKj7uX/h/JW5JqIQvBvX4dwnD/IouZHXgh/wyIWxJZp89dgXZ oFRCNJ9fb1XABpcrCXi9ZyQ5+y5Xdk5adAxl3eI4kryX+4GZGt9T2xbpvP444ylbqP9w prp2kHlruQXMk+y/x+AChlfwUmLMUEqwu5vVhaxcOLYbCE4onlL54wB4W2gXd7tg68TV 9itw== X-Forwarded-Encrypted: i=1; AHgh+RrAoQgm+2WYGFUijx1eAGcr8Z0dmAgnYdOvsPx77yrF91PXMkys/RHW9dEg10e0fNmvxr498NLsWkNfxQ8=@vger.kernel.org X-Gm-Message-State: AOJu0YxAUNhTeM8vNcKTFxgSuwtDHNFlcheFH0neJV8qx9XQsj3uek7d i4AJ0bCT7igNcfqG3iwE8o+CBO2Y5BHliLxrxnrkwoehUKmeKrJ3HU0cz54ra6t8fKgLotw5QXp BRB0BF69usjrSA5byoQ2QioOjXw== X-Received: from plrf4.prod.google.com ([2002:a17:902:ab84:b0:2c7:f2de:fc0c]) (user=souravpanda job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:1746:b0:2c9:ece2:822b with SMTP id d9443c01a7336-2cbea1a2b16mr46713705ad.3.1783273880227; Sun, 05 Jul 2026 10:51:20 -0700 (PDT) Date: Sun, 5 Jul 2026 17:51:19 +0000 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-Mailer: git-send-email 2.55.0.rc0.799.gd6f94ed593-goog Message-ID: <20260705175119.440599-1-souravpanda@google.com> Subject: [PATCH v3] mm/hugetlb: Fix null nodemask in alloc_fresh_hugetlb_folio From: Sourav Panda To: muchun.song@linux.dev, osalvador@suse.de, akpm@linux-foundation.org Cc: david@kernel.org, surenb@google.com, fvdl@google.com, gthelen@google.com, souravpanda@google.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" alloc_buddy_hugetlb_folio_with_mpol() can pass a NULL nodemask to alloc_fresh_hugetlb_folio() as a fallback to allocate from all nodes. If order is gigantic, alloc_fresh_hugetlb_folio() propagates the NULL nodemask down to hugetlb_cma_alloc_frozen_folio() which blindly dereferences it in for_each_node_mask(), leading to a null pointer dereference. Similarly, if the CMA allocation fails, the fallback alloc_contig_frozen_pages() is also called with a NULL nodemask, which may cause issues. Fix this by explicitly checking if nodemask is NULL in alloc_fresh_hugetlb_folio() and defaulting to cpuset_current_mems_allowed. This ensures that both the CMA and contiguous allocators receive a valid nodemask safely using a seqcount loop to prevent torn reads. >From a userspace perspective, this bug allows an unprivileged user to crash the kernel (trigger a panic) by requesting a gigantic hugepage allocation with MPOL_PREFERRED_MANY on a system where CMA is only configured on a subset of NUMA nodes. This can be reproduced by booting a VM with two NUMA nodes, restricting CMA to Node 1 (e.g., hugetlb_cma=1:1G default_hugepagesz=1G hugepagesz=1G hugepages=0), and running a program that allocates a 1GB hugepage area without reserving, restricts allocation to Node 0 using mbind() with MPOL_PREFERRED_MANY, and triggers a page fault: void *ptr = mmap(NULL, 1UL << 30, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_HUGE_1GB | MAP_NORESERVE, -1, 0); unsigned long nodemask = 1; /* Node 0 */ mbind(ptr, 1UL << 30, MPOL_PREFERRED_MANY, &nodemask, sizeof(nodemask) * 8, 0); memset(ptr, 0, 1UL << 30); /* Trigger fault */ This results in a NULL pointer dereference: BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page Oops: Oops: 0000 [#1] SMP NOPTI RIP: 0010:hugetlb_cma_alloc_frozen_folio+0x75/0x120 Call Trace: only_alloc_fresh_hugetlb_folio.isra.0+0x2c/0x160 alloc_surplus_hugetlb_folio+0x6d/0x100 alloc_hugetlb_folio+0x3c5/0x660 hugetlb_no_page+0x3d9/0x650 Additionally, this patch adds a missing node_isset(nid, *nodemask) check in hugetlb_cma_alloc_frozen_folio() to ensure the initial node allocation attempt respects the memory policy. Fixes: eb02f14c4a2b ("mm/hugetlb: allow overcommitting gigantic hugepages") Cc: stable@vger.kernel.org Signed-off-by: Sourav Panda --- Changes in v3: - Condensed the reproducer and QEMU setup from v1 discussion into a readable summary per Andrew Morton. - Safely read cpuset_current_mems_allowed using a seqcount loop to prevent torn reads. - v2: https://lore.kernel.org/linux-mm/20260704174930.2885785-1-souravpanda@google.com/ - v1: https://lore.kernel.org/linux-mm/20260702215713.627941-1-souravpanda@google.com/ mm/hugetlb.c | 12 ++++++++++++ mm/hugetlb_cma.c | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 571212b80835..ee67ea29c003 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1864,6 +1864,18 @@ static struct folio *alloc_fresh_hugetlb_folio(struct hstate *h, gfp_t gfp_mask, int nid, nodemask_t *nmask) { struct folio *folio; + nodemask_t local_node_mask; + + if (!nmask) { + unsigned int cpuset_mems_cookie; + + do { + cpuset_mems_cookie = read_mems_allowed_begin(); + local_node_mask = cpuset_current_mems_allowed; + } while (read_mems_allowed_retry(cpuset_mems_cookie)); + + nmask = &local_node_mask; + } folio = only_alloc_fresh_hugetlb_folio(h, gfp_mask, nid, nmask, NULL); if (folio) diff --git a/mm/hugetlb_cma.c b/mm/hugetlb_cma.c index 39344d6c78d8..79dbd0baafa3 100644 --- a/mm/hugetlb_cma.c +++ b/mm/hugetlb_cma.c @@ -34,7 +34,7 @@ struct folio *hugetlb_cma_alloc_frozen_folio(int order, gfp_t gfp_mask, if (!hugetlb_cma_size) return NULL; - if (hugetlb_cma[nid]) + if (hugetlb_cma[nid] && node_isset(nid, *nodemask)) page = cma_alloc_frozen_compound(hugetlb_cma[nid], order); if (!page && !(gfp_mask & __GFP_THISNODE)) { -- 2.55.0.rc0.799.gd6f94ed593-goog