From patchwork Mon Feb 3 10:18:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Brodsky X-Patchwork-Id: 13957193 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id BFF10C02193 for ; Mon, 3 Feb 2025 10:20:46 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 4734B280019; Mon, 3 Feb 2025 05:20:46 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 3A8EC280002; Mon, 3 Feb 2025 05:20:46 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 22564280018; Mon, 3 Feb 2025 05:20:46 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id EF1D2280002 for ; Mon, 3 Feb 2025 05:20:45 -0500 (EST) Received: from smtpin02.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id B7ABB120AAF for ; Mon, 3 Feb 2025 10:20:41 +0000 (UTC) X-FDA: 83078239482.02.FEFC364 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf03.hostedemail.com (Postfix) with ESMTP id 0EE862000B for ; Mon, 3 Feb 2025 10:20:39 +0000 (UTC) Authentication-Results: imf03.hostedemail.com; dkim=none; spf=pass (imf03.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com; dmarc=pass (policy=none) header.from=arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738578040; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uAEP4bJ4DAnLZnFE79/GJlPC9W5ScHGYEPhyiOeUp20=; b=Ji+RW6OSjXEBiMFagQCMXZg29QBYVOXrwbeZV0SWzfYAWq7D2ADG09bzslrvHzTDbDyAhc f1LI3av6wkum5Hj9BEujAQGsaXN/fK/K6FCwY2zlNWqSfAdhzr4a6DgDZvG+yT6VGKcs6x D/1VUyEKQ3e7/FwPNgMFsuEklyW9UQA= ARC-Authentication-Results: i=1; imf03.hostedemail.com; dkim=none; spf=pass (imf03.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com; dmarc=pass (policy=none) header.from=arm.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738578040; a=rsa-sha256; cv=none; b=y1pHLqS1+jz8ES6MQtGRqbWqYwQtiW4y8FqQq+08vRn1a3iX8rvNd4fxIKpiWdtNODxbR7 iegBnOdKfS9d2709MfaTT1hy1rTAgH8OIGtAldhWR7XA7jeBQMP3G/8l0nG4HL5KUCayJ2 2MerBIY2gbjQG6L4wESBGhy5AfJ9gy0= Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C21571476; Mon, 3 Feb 2025 02:21:03 -0800 (PST) Received: from e123572-lin.arm.com (e123572-lin.cambridge.arm.com [10.1.194.54]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D01593F63F; Mon, 3 Feb 2025 02:20:35 -0800 (PST) From: Kevin Brodsky To: linux-hardening@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Kevin Brodsky , Andrew Morton , Mark Brown , Catalin Marinas , Dave Hansen , Jann Horn , Jeff Xu , Joey Gouly , Kees Cook , Linus Walleij , Andy Lutomirski , Marc Zyngier , Peter Zijlstra , Pierre Langlois , Quentin Perret , "Mike Rapoport (IBM)" , Ryan Roberts , Thomas Gleixner , Will Deacon , Matthew Wilcox , Qi Zheng , linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org, x86@kernel.org Subject: [RFC PATCH v3 15/15] mm: Add basic tests for kpkeys_hardened_pgtables Date: Mon, 3 Feb 2025 10:18:39 +0000 Message-ID: <20250203101839.1223008-16-kevin.brodsky@arm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250203101839.1223008-1-kevin.brodsky@arm.com> References: <20250203101839.1223008-1-kevin.brodsky@arm.com> MIME-Version: 1.0 X-Rspamd-Server: rspam02 X-Rspamd-Queue-Id: 0EE862000B X-Stat-Signature: qat41jphqkspcgdiks5foeoj4xa57bbk X-Rspam-User: X-HE-Tag: 1738578039-905027 X-HE-Meta: U2FsdGVkX1+7GsN4kuDtDCUzpjUOjcpAxdmsccb2gfp1JVz0KaiMbTnrABfwrQLXqKHYkwkAkjaintyBua4lvJvSj6s9EudTixNW7i32cx1LyEgS1lvGpSu/AuMB25pP1wcRnhJmrgZg2nx/1plo6BRs3E2m6jNmCPYVyu18P6ovCAHlmcoQFZ9iRNqt7oeMbHDQZ8oqpBCCD6syL/xsHHxE55uZrh8oOvQ4hjFjabiAkt309Dkcf/WE0Yfs8nz8CaSb0q4xFJPQT3Te3F0g2XA9VfVqhiReb4waEXQ4xVr27fFAOFbX+wtdQkqOvPOD+hW1bJMMAn01VmJH/hX02s+LXjQo/llJiQQfs4qZceqXehgs18UOXC56sq6Wa9DtyHx1G4MMMgqX1vTpNWFm9iI7xQDzDn7oMprTnydBGY5wkSJUEdPyTxc/fRsRg0pu+KlLxr6dCcfvSzjoxM/kYCDvb2dTU5bXr3w8WwT/KZR2+MJmE2pV7V2wvJVLtjit/HG40RkDtBwJ5gW0XX5pGax0VtbYNwp8fybsWN92KbT3y6Hlcrnj2kNdQGMXdKPM2Di4dlvU/sFHEIhUTI6iJ+CkbZtPwKCbggq9pRCVHXOv7Ky7HSgNpTK+5e+AuHCScjSIkQ6YlBF3YDzE8xclMiu79YbauoPvt0MhElLoJuDkXs8WHiUdeKABzdowVtBLOVt/eRZ5lMTBy8pjwjnMXTr1aPyKPNxoYfa4C9F++bUswTzXYHLT2ZjBpqyM7gjOcBRfBNdEylwcB7Hetf2L8D6v0mOIPsSQa/SEFV6uC7aXLUp7w2DHuTvY5XQFwb/QrgaJjFtVMQxiP258ro42/yJp1So7SwS1ID/IL/Sc90Gf+kLdl9FtYES5dHxIQoSTTEdeWqG9UsSm3gfpE0a+crfGM+llFDCyaKWBV7LP+SszePv1QHG9PyQRWOQNmfJGTFkfhL8qRSC1X/UyXeS 9BWo54vQ 48IG2LUmtsn8kweWRpZZNhK+BLRqFt8N8JwFKA64yY0GNgVM/f10GimqDow1uPhJXeORZzfHpGBoqwY9zy8GHKZdkXRyGrDhOMqRfB1X2JnKa4N8liXH/p/9X87M02Xi9z2mr5JM8sCZKJh6bbMFaec/Zkue11XZycPoRVsLMAN+GdBupAAg7JDVsU0u0AEYpOUDt31EU2Fdilhw= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add basic tests for the kpkeys_hardened_pgtables feature: try to perform a direct write to some kernel and user page table entry and ensure it fails. Signed-off-by: Kevin Brodsky --- mm/Makefile | 1 + mm/kpkeys_hardened_pgtables_test.c | 72 ++++++++++++++++++++++++++++++ security/Kconfig.hardening | 12 +++++ 3 files changed, 85 insertions(+) create mode 100644 mm/kpkeys_hardened_pgtables_test.c diff --git a/mm/Makefile b/mm/Makefile index 130691364172..f7263b7f45b8 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -148,3 +148,4 @@ obj-$(CONFIG_EXECMEM) += execmem.o obj-$(CONFIG_TMPFS_QUOTA) += shmem_quota.o obj-$(CONFIG_PT_RECLAIM) += pt_reclaim.o obj-$(CONFIG_KPKEYS_HARDENED_PGTABLES) += kpkeys_hardened_pgtables.o +obj-$(CONFIG_KPKEYS_HARDENED_PGTABLES_TEST) += kpkeys_hardened_pgtables_test.o diff --git a/mm/kpkeys_hardened_pgtables_test.c b/mm/kpkeys_hardened_pgtables_test.c new file mode 100644 index 000000000000..86d862d43bea --- /dev/null +++ b/mm/kpkeys_hardened_pgtables_test.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include + +static void write_kernel_pte(struct kunit *test) +{ + pte_t *ptep; + pte_t pte; + int ret; + + /* + * The choice of address is mostly arbitrary - we just need a page + * that is definitely mapped, such as the current function. + */ + ptep = virt_to_kpte((unsigned long)&write_kernel_pte); + KUNIT_ASSERT_NOT_NULL_MSG(test, ptep, "Failed to get PTE"); + + pte = ptep_get(ptep); + pte = set_pte_bit(pte, __pgprot(PTE_WRITE)); + ret = copy_to_kernel_nofault(ptep, &pte, sizeof(pte)); + KUNIT_EXPECT_EQ_MSG(test, ret, -EFAULT, + "Direct PTE write wasn't prevented"); +} + +static void write_user_pmd(struct kunit *test) +{ + pmd_t *pmdp; + pmd_t pmd; + unsigned long uaddr; + int ret; + + uaddr = kunit_vm_mmap(test, NULL, 0, PAGE_SIZE, PROT_READ, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_POPULATE, 0); + KUNIT_ASSERT_NE_MSG(test, uaddr, 0, "Could not create userspace mm"); + + /* We passed MAP_POPULATE so a PMD should already be allocated */ + pmdp = pmd_off(current->mm, uaddr); + KUNIT_ASSERT_NOT_NULL_MSG(test, pmdp, "Failed to get PMD"); + + pmd = pmdp_get(pmdp); + pmd = set_pmd_bit(pmd, __pgprot(PROT_SECT_NORMAL)); + ret = copy_to_kernel_nofault(pmdp, &pmd, sizeof(pmd)); + KUNIT_EXPECT_EQ_MSG(test, ret, -EFAULT, + "Direct PMD write wasn't prevented"); +} + +static int kpkeys_hardened_pgtables_suite_init(struct kunit_suite *suite) +{ + if (!arch_kpkeys_enabled()) { + pr_err("Cannot run kpkeys_hardened_pgtables tests: kpkeys are not supported\n"); + return 1; + } + + return 0; +} + +static struct kunit_case kpkeys_hardened_pgtables_test_cases[] = { + KUNIT_CASE(write_kernel_pte), + KUNIT_CASE(write_user_pmd), + {} +}; + +static struct kunit_suite kpkeys_hardened_pgtables_test_suite = { + .name = "Hardened pgtables using kpkeys", + .test_cases = kpkeys_hardened_pgtables_test_cases, + .suite_init = kpkeys_hardened_pgtables_suite_init, +}; +kunit_test_suite(kpkeys_hardened_pgtables_test_suite); + +MODULE_DESCRIPTION("Tests for the kpkeys_hardened_pgtables feature"); +MODULE_LICENSE("GPL"); diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index f729488eac56..649847535fc3 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -313,6 +313,18 @@ config KPKEYS_HARDENED_PGTABLES This option has no effect if the system does not support kernel pkeys. +config KPKEYS_HARDENED_PGTABLES_TEST + tristate "KUnit tests for kpkeys_hardened_pgtables" if !KUNIT_ALL_TESTS + depends on KPKEYS_HARDENED_PGTABLES + depends on KUNIT + default KUNIT_ALL_TESTS + help + Enable this option to check that the kpkeys_hardened_pgtables feature + functions as intended, i.e. prevents arbitrary writes to user and + kernel page tables. + + If unsure, say N. + endmenu config CC_HAS_RANDSTRUCT