From nobody Mon Dec 1 20:56:55 2025 Received: from mail-yw1-f179.google.com (mail-yw1-f179.google.com [209.85.128.179]) (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 F25F231813F for ; Mon, 1 Dec 2025 18:07:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764612463; cv=none; b=WszegXQ78rMExg2EOxNU53EIJG6QEcwr+Rjpn0sofxnIxseQF+sK6TOS9940ie1gcy0X14BDWAg5qlDk00y9C954t77YwRagGidTsqFxpSy5Qpn8nurX2Qm6xIT33XUzrESSHCpYN54hNFl18lTQVXtcfaD+7PcTtWeBXVtEC4E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764612463; c=relaxed/simple; bh=yM6aPJxvxblAnvdThGStpTfIcE630fVs9OU3ye4pspM=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=noYGBhqkg8DcFUc2fflN2OdUFd8wBLHV95ybh/AypI8kTPIfKd91D5AZohdkKa7l55zXNakvHizCTqUZ7lhxy2Z3Pc/oUNsJLtxBOITevV/kdLzDZIolg8+lx32HeaatUFP+B7p1I2Bjcmz9oFculaoPOV0zheOhU6vOPvrYVl0= 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=cEMTX71O; arc=none smtp.client-ip=209.85.128.179 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="cEMTX71O" Received: by mail-yw1-f179.google.com with SMTP id 00721157ae682-78a6c7ac38fso46695387b3.0 for ; Mon, 01 Dec 2025 10:07:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764612461; x=1765217261; 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=0QyuTy6ek64uIdo9s8SZmB6RliPCLO8eDRQ9s+Wqlok=; b=cEMTX71OzhkRsoHVBjeOlMGoNlt6L3SXvO4yGZQBvr/W618hptEhfK69ZcnmlGDaJ2 GosCXu1exnh9rMMsISJKqNvO6VyjaPdqSu4K3lVb/aNwfZUxL509x/aiIbwYT2gzHNts 7Ic7vhY/uL6ammeGscxtO/dJ7nWKaJVLrUWExfUl94Gbkmfvos21HSbm1VKkCqkKnGrM QGJBe8c8isfgRN46G7vQqAeDGLK/RF0iUSH7LtfHZKv3FsdVO5Sn77u2+gYySQLL/Clw mLm/SCe47GgMJMLnYjerhFDqG+3Z8cl1OiuAcTfmXUKgyU8yGhIlOMACiJ8B9sysrOgh iMqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764612461; x=1765217261; 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=0QyuTy6ek64uIdo9s8SZmB6RliPCLO8eDRQ9s+Wqlok=; b=NPxJ37z7WesJYTrFTnhRoWojldGurqPlqXO3PVWauZzI03RdYPaYKYIcdQrCgU4ugA vd4Z5nIPKPxQKzU+GVYFuI7qIRcc7sRtzu0+giweglifFllQadGtCi7drf0HVBvQeb32 goi/fqWgabdWtI7O9HmbheE5nRcp9L6A/u+CKezlyTILCNxahG5FQAQj3I/Yra/W2aGf QZ36hzzP6et/on1A8ZXQsymJUR23XIbp98mJjZrKHCmgyjh5x640ysTJnDzZz74Zd/Li dVm8qdDvQKKpLgaFd+VVj+2TtPaMLNsJ+AKNAWRgveq0ztAPp8ehapfMevJDZfjoDOi/ 3CCw== X-Forwarded-Encrypted: i=1; AJvYcCV1FxcQEpvl+oMTRShGnwv91f5xWP2NDABZNBKm3y/PdISz3MDlg9ocYxOHEaXrESUIaXUGyhiaahLLkLQ=@vger.kernel.org X-Gm-Message-State: AOJu0Ywyh5UMPfkdOfqbET9wOuoOGsgYOyLgk51Whuci/oWfqFaF1gyE woE8Kda1wETclLhvlhYDXwzg1R/tws9HDzCJrxB08a66DjvASWwjtRa9 X-Gm-Gg: ASbGncuWqQTHciWXcOe6bVfDZAqmD0He/NLVLxXpG2MCMQvvA8XqCrzO+sbw1P4BdnZ aUIwrogPEIbaMDDfZfegIRUWKV2Iekn+AEikbjUif00rl8/G26nVFvoZBkhJ2zGq6x1GTqzWbnD K9VQp4PDlD4VD0McvKJDIeu2e3GkKDavUntUREDsKGwBA56fmJddEEi6cSNWDFgKzMnUh+YqUwt kEpOxTLj98A+9LyMdT7xAcZvr7sgM3ACkMf82UkOKjxHjV1JLoFPRO0zwGK2+3mGaIfFiMTyLfT lx7dqLDWOVzPbKm+3bDvvD33PHwwVxcCwOtaMlcip3dnF/bTgc5A2wGN9gekAlRZZ7iFX0NEb3h FneG/S/pJmgR4FUZ/03s48h5XWx+oQP6wn55hymj4aTCWM+vA+oH0MohpB3rUOm6xdLML6HpfdJ jAzxVbMSSJEhqsLdal/yEm/A== X-Google-Smtp-Source: AGHT+IGebBLF0eFSQu1V6/IZFq1lSrNOt+fw835UDZgXCTtz/zrjUyYDOacz1JvbW8Om1eqnkY9hqg== X-Received: by 2002:a05:690c:6087:b0:786:5926:edab with SMTP id 00721157ae682-78a8b491ceamr335684337b3.17.1764612460818; Mon, 01 Dec 2025 10:07:40 -0800 (PST) Received: from localhost ([2a03:2880:25ff:5b::]) by smtp.gmail.com with ESMTPSA id 00721157ae682-78ad0d5fe7fsm52262427b3.17.2025.12.01.10.07.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Dec 2025 10:07:40 -0800 (PST) From: Joshua Hahn To: Andrew Morton Cc: Vlastimil Babka , SeongJae Park , Jonathan Corbet , Mike Rapoport , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, kernel-team@meta.com Subject: [PATCH v3] mm/mm_init: Introduce a boot parameter for check_pages Date: Mon, 1 Dec 2025 10:07:38 -0800 Message-ID: <20251201180739.2330474-1-joshua.hahnjy@gmail.com> X-Mailer: git-send-email 2.47.3 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use-after-free and double-free bugs can be very difficult to track down. The kernel is good at tracking these and preventing bad pages from being used/created through simple checks gated behind "check_pages_enabled". Currently, the only ways to enable this flag is by building with CONFIG_DEBUG_VM, or as a side effect of other checks such as init_on_{alloc, free}, page_poisoning, or debug_pagealloc among others. These solutions are powerful, but may often be too coarse in balancing the performance vs. safety that a user may want, particularly in latency-sensitive production environments. Introduce a new boot parameter "check_pages", which enables page checking with no other side effects. It takes kstrbool-able inputs as an argument (i.e. 0/1, true/false, on/off, ...). This patch is backwards-compatible; setting CONFIG_DEBUG_VM still enables page checking. Acked-by: SeongJae Park Acked-by: Michal Hocko Signed-off-by: Joshua Hahn --- v2 --> v3: - Dropped the second patch. I may pursue it at another time : -) - Variable renaming (dropping leading _) and cleaner check in mem_debugging_and_hardening_init, as suggested by Mike Rapoport v1 --> v2: - Changed check_pages from a build config into a boot config, as suggested by Vlastimil. - Introduced the second patch, which decouples page checking from=20 init_on_page_alloc and init_on_page_free. --- Documentation/admin-guide/kernel-parameters.txt | 8 ++++++++ mm/mm_init.c | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentatio= n/admin-guide/kernel-parameters.txt index 6c42061ca20e..acdc7fbdecac 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -669,6 +669,14 @@ nokmem -- Disable kernel memory accounting. nobpf -- Disable BPF memory accounting. =20 + check_pages=3D [MM,EARLY] Enable sanity checking of pages after + allocations / before freeing. This adds checks to catch + double-frees, use-after-frees, and other sources of + page corruption by inspecting page internals (flags, + mapcount/refcount, memcg_data, etc.). + Format: { "0" | "1" } + Default: 0 (1 if CONFIG_DEBUG_VM is set) + checkreqprot=3D [SELINUX] Set initial checkreqprot flag value. Format: { "0" | "1" } See security/selinux/Kconfig help text. diff --git a/mm/mm_init.c b/mm/mm_init.c index c6812b4dbb2e..fc2a6f1e518f 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -2525,6 +2525,14 @@ early_param("init_on_free", early_init_on_free); =20 DEFINE_STATIC_KEY_MAYBE(CONFIG_DEBUG_VM, check_pages_enabled); =20 +static bool check_pages_enabled_early __initdata; + +static int __init early_check_pages(char *buf) +{ + return kstrtobool(buf, &check_pages_enabled_early); +} +early_param("check_pages", early_check_pages); + /* * Enable static keys related to various memory debugging and hardening op= tions. * Some override others, and depend on early params that are evaluated in = the @@ -2534,7 +2542,7 @@ DEFINE_STATIC_KEY_MAYBE(CONFIG_DEBUG_VM, check_pages_= enabled); static void __init mem_debugging_and_hardening_init(void) { bool page_poisoning_requested =3D false; - bool want_check_pages =3D false; + bool want_check_pages =3D check_pages_enabled_early; =20 #ifdef CONFIG_PAGE_POISONING /* --=20 2.47.3