From patchwork Mon Feb 3 10:28:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Brodsky X-Patchwork-Id: 13957219 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 0810EC02192 for ; Mon, 3 Feb 2025 10:28:56 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 36255280010; Mon, 3 Feb 2025 05:28:56 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 2EAC8280002; Mon, 3 Feb 2025 05:28:56 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 18B9628000E; Mon, 3 Feb 2025 05:28:56 -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 F070D280002 for ; Mon, 3 Feb 2025 05:28:55 -0500 (EST) Received: from smtpin09.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id 8C981162545 for ; Mon, 3 Feb 2025 10:28:33 +0000 (UTC) X-FDA: 83078259306.09.37350BA Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf05.hostedemail.com (Postfix) with ESMTP id F002C10000D for ; Mon, 3 Feb 2025 10:28:31 +0000 (UTC) Authentication-Results: imf05.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf05.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738578512; 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=vkmJBE2xe1rD7fvTP6vWNu0WpILKMHVEtvlvMXZaL4Q=; b=6UI11T6wUVeA75ptUzphN+IEwm7/opB3nRC6vaad/u5jSf5PSsG8tZOSfFZbXOwI9wTVpm 1XRe9SUNc3sO3sh3eozA9e2kuWhtwPIhPtwOmsWcFLElCi8VQOY1snp55PdXc8kTvf0m32 MrCt1ORCs//4AasHtU+ADQOzY7gUHPo= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738578512; a=rsa-sha256; cv=none; b=yHHbByUP1N/eG6yOHkint94oC41ycTdwf+WnlLnJC4SqbrJl5fx6NHQk4ftwZUCRyD5Z5C UT2mCpAgKJhAzAYPKaZJknlhOJ63acM/bF65Z/g5a6RALFWA7Pxce86gXsvF3On8bDgjLY 8ZzIN07tp7uR0SgjpKcLQq+8XNI71u4= ARC-Authentication-Results: i=1; imf05.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf05.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com 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 AA49E1476; Mon, 3 Feb 2025 02:28:55 -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 7B5A13F63F; Mon, 3 Feb 2025 02:28:27 -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 , David Howells , "Eric W. Biederman" , 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 1/8] arm64: kpkeys: Avoid unnecessary writes to POR_EL1 Date: Mon, 3 Feb 2025 10:28:02 +0000 Message-ID: <20250203102809.1223255-2-kevin.brodsky@arm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250203102809.1223255-1-kevin.brodsky@arm.com> References: <20250203102809.1223255-1-kevin.brodsky@arm.com> MIME-Version: 1.0 X-Stat-Signature: qphpdhxxff13xsfbqt3ff6968mnmphmi X-Rspam-User: X-Rspamd-Queue-Id: F002C10000D X-Rspamd-Server: rspam03 X-HE-Tag: 1738578511-227497 X-HE-Meta: U2FsdGVkX19x66Bnn82JozGmfcdC8pRx9c4a1cVTF23EsK1n3VJJCZYh21RvOgI31iV+HUy6D9dC/b2Pu1Au4VLH8w0BRDx5J2UBw0/3LQ56kJJjPdf/kx2Nq1uMK8HUmkqW2Wl1FjU7xdx6P5Ui4Nm0vQakLu9whFivVAh9+MCyVdgWxu50dJ/amTdsx98l9KgA6lvRQYwlvIwtPWABNNnsqTm+aJaf9YXJgd403BH5VNmHySiBBQwLlOd+jM1kwy3Ve1+n+nQrqqxHUHSyfZNE+IPf7M7t4B02J0XYt5sdCOZ/wKvuGZ/JbVZtPllvl679ye48gbue2ixFcnaN1VCcqwDfL5RuRuSJd2Hut40TDNHyY6YPLph9jEdjEr/J0ad3viBMqAEnO2iJDFr4DX6CXyTk0G4RNcedQ2pJxdtC2bA+5vlsapNRK8oeIpuKfubhqJMNhnHrO6GMCo9KUj3Lwzuc+tD7eTEPvdX08k0Ka0tZjjNBBDVvlcpBww435uO7hk1VTShqJ9nhenyWIaWW4Xa+vFV1UCXFUzpk+s7jou2vPDHNWAd6kSvTD1Iq89IcaC6utCvWJhqI1WCsXQLtWxJfZDhCM7lvytRKK0UoqwA4++aJMI3oqeDeeD6guwG3ldtMn6weEOSrmab3vsqYo76S+YlAnWaTLrH+v+gHjl1Q0RjcCaQ/IyyMxGXVGGowjkb12cUDu2x0nhnNlYYMIwi88kNoXe4a1+k17Qf8ObHmBX4wK9QUSgpELMXHJ54uGkLvFRmD0fDee/FE9z/42/JLl+n6Y7tXx99UCyUP23mxnGThOmjZOvL6fJJhmnfJbQy6e0JI4QZ4bsC2wAGtrDC1ciAhJ8VlvE5azqPZr1faSGq3J9liDN5MKTDzjl0Wnhf8XY7uMrCzY5nUQCn8AwVakg1CBnXO5Fzr6/r8AKepiqmqOPyDhXLdmfMuiIbD8W/YzxhqYO8rq71 OMz9tkkV IB27Mk97ylgLLqdWza1ShZUtl4ChmG3TlYZK3WgsrbJ6HVBL0Wony8AiOu1PYYUZgc7Nw+b/7hfLLSIo7K6jxl0jog6gf+JTy/+5paqFPQ831Psy+FRkPwRhEUkRtnI3lbH2g/y7xnq7l8zFvIeSHmgrLQmlzlgiSM2vTeB+sojBHJFnDEIy+q7MEafrOL/vRmt8mQu3oOeTG7Mw= 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: Nested uses of kpkeys guards are about to be introduced, which means that kpkeys_set_level() may not actually need to change the value of POR_EL1. Since updating POR_EL1 requires an expensive ISB, let's skip the write if the value is unchanged, by returning KPKEYS_PKEY_REG_INVAL. This will cause the matching kpkeys_restore_pkey_reg() call to bail out without calling arch_kpkeys_restore_pkey_reg(). Signed-off-by: Kevin Brodsky --- arch/arm64/include/asm/kpkeys.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kpkeys.h b/arch/arm64/include/asm/kpkeys.h index 4854e1f3babd..3f16584d495a 100644 --- a/arch/arm64/include/asm/kpkeys.h +++ b/arch/arm64/include/asm/kpkeys.h @@ -27,8 +27,12 @@ static inline u64 por_set_kpkeys_level(u64 por, int level) static inline int arch_kpkeys_set_level(int level) { u64 prev_por = read_sysreg_s(SYS_POR_EL1); + u64 new_por = por_set_kpkeys_level(prev_por, level); - write_sysreg_s(por_set_kpkeys_level(prev_por, level), SYS_POR_EL1); + if (new_por == prev_por) + return KPKEYS_PKEY_REG_INVAL; + + write_sysreg_s(new_por, SYS_POR_EL1); isb(); return prev_por; From patchwork Mon Feb 3 10:28:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Brodsky X-Patchwork-Id: 13957222 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 EB7BEC02193 for ; Mon, 3 Feb 2025 10:29:09 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 86B15280013; Mon, 3 Feb 2025 05:29:09 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 81BBD28000E; Mon, 3 Feb 2025 05:29:09 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6E300280013; Mon, 3 Feb 2025 05:29:09 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 4DAB828000E for ; Mon, 3 Feb 2025 05:29:09 -0500 (EST) Received: from smtpin21.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 84E0882654 for ; Mon, 3 Feb 2025 10:28:37 +0000 (UTC) X-FDA: 83078259474.21.3A82BE6 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf15.hostedemail.com (Postfix) with ESMTP id F1B82A000E for ; Mon, 3 Feb 2025 10:28:35 +0000 (UTC) Authentication-Results: imf15.hostedemail.com; dkim=none; spf=pass (imf15.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=1738578516; 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=oHzh0GIvxYZInKVNXjFtmOiyhq3s9+3Bn3ETwjH4vJU=; b=x5G1Maxe7MCWwxjVKfyMlXUYNwxIBGQUHAaP1KyHLZZX0RTxVN1b1+GNqysie4brHiAHzi /ifp9f3n7pRY4quJG6iE74rxG6g9BqAtkTFhkfSSDRQNvxrR+vlOgpXG5t6T4e0Gwl3BDi 6YMeUoV+S6yETot4cciZb8b3l4B7ZAo= ARC-Authentication-Results: i=1; imf15.hostedemail.com; dkim=none; spf=pass (imf15.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=1738578516; a=rsa-sha256; cv=none; b=NDKc7VNL6thKWNHnqsYV7+HIkVWJQb5buXUNwN04eGmTfXlA8O1dYJrjeXqhfhourkGeQr 3+Og4Rp+m8ReHbEC4qBy3t1Zz35im9ZnUvK8PeXta1aGZAMhk1Px9TN62PMZlvCOdD47CK cqOQzOINd5yNvPBcfYwKBQVaeL2E6Jk= 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 BBF761682; Mon, 3 Feb 2025 02:28:59 -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 8CF223F63F; Mon, 3 Feb 2025 02:28:31 -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 , David Howells , "Eric W. Biederman" , 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 2/8] mm: kpkeys: Introduce unrestricted level Date: Mon, 3 Feb 2025 10:28:03 +0000 Message-ID: <20250203102809.1223255-3-kevin.brodsky@arm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250203102809.1223255-1-kevin.brodsky@arm.com> References: <20250203102809.1223255-1-kevin.brodsky@arm.com> MIME-Version: 1.0 X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: F1B82A000E X-Stat-Signature: 8aif7baynfj353kwddowkiroinj6bmbx X-Rspam-User: X-HE-Tag: 1738578515-798696 X-HE-Meta: U2FsdGVkX19CEVRiKOqr5Mcel6Oyc4IWUljiK+K/FlEnOVnzHuw6u7sVuofsepTIC8ovosS5AJhxfLbZIL33k4di3BcFu0rMZZnDTKiw1S5QxRKGmFbhwstUphZMLzWY2i09s/m9An9FQ87PFxvm106FmfHcStXmMZUcrPay1fGXCKBjzOXbyThRfhAY6F7TmPwYud58gD8e4QzWre+vgewXFKi5kQhWxqOcrG6Z49OgqEUoyn5LnRUC545PW7d3BcoWOFOT46CjSwIXNhIDsOBqFMoKj4n0Im0LL7O6y7bI8hk+VGRry613i7z8qW35qofQ7cqQEsUxCNly1EQ8STRK2TFqszWJzstfcH57EleVLZYQAxm3s/DEhPlORXrz/OedctZ7/JXHAk8UmusqcbBA2Sr5i8q1NBENtZCi4o1kIKzsvwO0vvnDjKcq9+fbOzXalgogvKgV/Uup47Ijo7yha1opN84hcG34smIOUO/pMDO11H+ZE8u188nFe3R/Xhh1lTCZfTKeBC56By2KD9qrXmRCAk7HUSnhZbZMD5W0DsPnvOXp15l3l7Ytvc65TLQz8WKryH4MmbRw1mCgLsMnRHd/TklK1UzWxzK1AVpLsj50UuZMNJ4tTuHCPt7IfbMAGOx1e7FgjeJcv3u57mGFhiQoeLyw3FUiwlQHN5n42vnL8YglCGSNj569dKdry/Bu5EVIfLnsIMbeTiTIK+48woxT0E/3hZHbyO3/2HRlMZPMmXyCxmekDF2+uMbLvNt8kXIIEiVh1g7ibOLf8D9DtoKBI4bkM9/4+Qf4RoZwX7LpfkcjJnVL/A0Cyku4WWNfcIBUduaE/3e3Tgi5iGpSEUfVMgt7+3TphVZYUujlH/Pyqdo/lo+gyia/j3QBJ6XxW9q0G2ICwH8fYDo9MZrZQlOTZSPXJwhpwyhHq47m/Z8b2W2L+bgO5ZP1HnlvvTtzIlV32HwMAHb8qzB KCIXAkqw GVvonKDyizFDyGyRT/CHgMlR1Dc5S7rqVxBBhYojaOb7SV8cakgfNG6lqHGDnteRAWAZ946kFhvTjJtJxLbymvQYN6OxbqFLbXamPzw1nwmkarc8MRG69SNYStWycJls8OPYhIt+nyUsPZyozB+vgDmpCiQ== 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: Highly privileged components, such as allocators, may require write access to arbitrary data. To that end, introduce a kpkeys level that grants write access to all kpkeys. Signed-off-by: Kevin Brodsky --- arch/arm64/include/asm/kpkeys.h | 4 +++- include/linux/kpkeys.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kpkeys.h b/arch/arm64/include/asm/kpkeys.h index 3f16584d495a..ab2305ca24b7 100644 --- a/arch/arm64/include/asm/kpkeys.h +++ b/arch/arm64/include/asm/kpkeys.h @@ -19,7 +19,9 @@ static inline u64 por_set_kpkeys_level(u64 por, int level) { por = por_set_pkey_perms(por, KPKEYS_PKEY_DEFAULT, POE_RXW); por = por_set_pkey_perms(por, KPKEYS_PKEY_PGTABLES, - level == KPKEYS_LVL_PGTABLES ? POE_RW : POE_R); + level == KPKEYS_LVL_PGTABLES || + level == KPKEYS_LVL_UNRESTRICTED + ? POE_RW : POE_R); return por; } diff --git a/include/linux/kpkeys.h b/include/linux/kpkeys.h index 645eaf00096c..9d9feec83ccf 100644 --- a/include/linux/kpkeys.h +++ b/include/linux/kpkeys.h @@ -10,9 +10,10 @@ struct folio; #define KPKEYS_LVL_DEFAULT 0 #define KPKEYS_LVL_PGTABLES 1 +#define KPKEYS_LVL_UNRESTRICTED 2 #define KPKEYS_LVL_MIN KPKEYS_LVL_DEFAULT -#define KPKEYS_LVL_MAX KPKEYS_LVL_PGTABLES +#define KPKEYS_LVL_MAX KPKEYS_LVL_UNRESTRICTED #define __KPKEYS_GUARD(name, set_level, restore_pkey_reg, set_arg, ...) \ __DEFINE_CLASS_IS_CONDITIONAL(name, false); \ From patchwork Mon Feb 3 10:28:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Brodsky X-Patchwork-Id: 13957242 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 40086C02193 for ; Mon, 3 Feb 2025 10:29:43 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id CB290280016; Mon, 3 Feb 2025 05:29:42 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id C620128000E; Mon, 3 Feb 2025 05:29:42 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B510E280016; Mon, 3 Feb 2025 05:29:42 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 97E6B28000E for ; Mon, 3 Feb 2025 05:29:42 -0500 (EST) Received: from smtpin13.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id E8F0EA2577 for ; Mon, 3 Feb 2025 10:28:41 +0000 (UTC) X-FDA: 83078259642.13.B011B6B Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf07.hostedemail.com (Postfix) with ESMTP id 4C3AE4000C for ; Mon, 3 Feb 2025 10:28:40 +0000 (UTC) Authentication-Results: imf07.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf07.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738578520; 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=wydQ6t7sf5CwaeBJ0WjER4INB2IsNUN8+Dj6vCyx8B4=; b=2jw78TuIm6AoNWM/zWtxAYRD0TB2IUkAYmlNmiO+3e4V/2seQ1RV6dgJAW1w8Yb4aXQMyF UtXnmdI/HlMiof3UT75ERvOdWibU5G4h1+rohPKpnzyNfQn64SaElW5+V0RTdPAVB5TLQo oLvpvzmymkJIRJRJetpwJHt0hSpBg+s= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738578520; a=rsa-sha256; cv=none; b=CfZ0PvJX86upvKdB1e92VgzWcLUdIH0aPvLbFvfhfJKYcvwiOiv2o1DRJNxfdguahO9oMp gzUqQQqvU3IedeaObetweDUuT+Oq9wQv+tGCuFXnSXT1pKcPVxW5eBzvEEJqRotteBcR6E ibcFp+Q8NJkD6lKKZwm17HXdlOD4zNY= ARC-Authentication-Results: i=1; imf07.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf07.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com 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 0159F1A32; Mon, 3 Feb 2025 02:29:04 -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 9F1B53F63F; Mon, 3 Feb 2025 02:28: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 , David Howells , "Eric W. Biederman" , 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 3/8] slab: Introduce SLAB_SET_PKEY Date: Mon, 3 Feb 2025 10:28:04 +0000 Message-ID: <20250203102809.1223255-4-kevin.brodsky@arm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250203102809.1223255-1-kevin.brodsky@arm.com> References: <20250203102809.1223255-1-kevin.brodsky@arm.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4C3AE4000C X-Stat-Signature: geiurjdd7n773p145qzjc8hk7i7qjk14 X-Rspam-User: X-Rspamd-Server: rspam12 X-HE-Tag: 1738578520-903913 X-HE-Meta: U2FsdGVkX1/pMdv9kXXYD36zl3k7IN1Di9tXULNX0zbdINPMuT1dXQiPk84tJX5sxC5UkPXYpst98zWU1F6saE3Z07hahR0IzxTeuHpZSEz3parWh7MznS19Q5OIvlJfiNBcQTLNLM/4swwtC7r5bRoJBbNO2lz3mFC5ywsbo5l5loENN3M1Ao3e2JrjjfBgwltxfrS4qR4Xv0UiTlWLUozl4iRslTZa+Mkwivn10dTrFwwIzng0DoB7pwbA7DoRhunej4lqfdFaCyKyRfWIjGjQKd1jlnJGFBumrmhnw87vbNJJ1X0ryxieazluHvsUfItX9Qf2Q4MdR7WNnAxEwdE4DfFxCs0i0IpZutPedYpdWe0MvZRTR3Pq/+1L1GNDkXeGLahU/T7uf5CQxKrtY1v8eylau0S6rKUvuJAFl/jLejYKrBuPcJqXiQdu/rS2aPO21Dp+3A6pzM27AfvwzwqGyyE1uetTcrYuLtigpvmpE/ORu7LznsNeHcbYawkTQfjv41i8TAmqVn99jvcNDlkWBL0vbkFtPVdvrNaBFyhFX5C9wXMZn43VDP1g6m/q3ve+PqYXeWS0JNJf9oKvSE4bPBpZzoQFVmjeOseyF1JZg82okaJ6Pk9icB3n/Xvc/08I/mzJflu/s7ukEXOQgdRfeSsxXj+eoDA/5vQCIbccPQsHWoQUs5k8ZIVT5l+7ScTM6RUe2fU30DlYexzlYLzc+euZrrm5+ya2ejSOUb4P+aj8Af5pufFLhDDHLwxTphV2PkAKB8UPI9cWFZPHzFJM2vidtC2HgSGSc+JzbhD7QkzVhR7l+JUWv6SCrgQeKD3sknc21kABx/oTDdp/ZIbi1k0/Yn1R/CAgxPPcO1xZaigTWTtmTslMKipqS5D+spHXYDBFI4rd4i09G1mDwrB18EIzrFoMN8wxHby6RLoWEhfGPGONR37grOCdouIDdWFLuzH7VEgiWaKphoS EXVTK1Dy PPQXUCIn7OG3R1zyjWW1I2FztYSXvJ1YpVXOfT4AsRQeU2URe3SEwqpm2FU5Rh9Z5kWmGZL1grvNVtsUZVI02yG3GXOTHnL1DntIMI7MHt4Ns5TyVgR0r0AsbMzoWHnNTiy4CiAXIl6tJumEQ/y/BR0qjohvs9D9t5jCZ2g0om7d1EIj63zrWKRxgG9pzA9dAQ2axxGOWRumIYdg= 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: Introduce the SLAB_SET_PKEY flag to request a kmem_cache whose slabs are mapped with a non-default pkey, if kernel pkeys (kpkeys) are supported. The pkey to be used is specified via a new pkey field in struct kmem_cache_args. The setting/resetting of the pkey is done directly at the slab level (allocate_slab/__free_slab) to avoid having to propagate the pkey value down to the page level. Memory mapped with a non-default pkey cannot be written to at the default kpkeys level. This is handled by switching to the unrestricted kpkeys level (granting write access to all pkeys) when writing to a slab with SLAB_SET_PKEY. The merging of slabs with SLAB_SET_PKEY is conservatively prevented, though it should be possible to merge slabs with the same configured pkey. Signed-off-by: Kevin Brodsky --- include/linux/slab.h | 21 ++++++++++++++++ mm/slab.h | 7 +++++- mm/slab_common.c | 2 +- mm/slub.c | 58 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 85 insertions(+), 3 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 09eedaecf120..cc2e757b16ec 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -58,6 +58,9 @@ enum _slab_flag_bits { _SLAB_CMPXCHG_DOUBLE, #ifdef CONFIG_SLAB_OBJ_EXT _SLAB_NO_OBJ_EXT, +#endif +#ifdef CONFIG_ARCH_HAS_KPKEYS + _SLAB_SET_PKEY, #endif _SLAB_FLAGS_LAST_BIT }; @@ -234,6 +237,12 @@ enum _slab_flag_bits { #define SLAB_NO_OBJ_EXT __SLAB_FLAG_UNUSED #endif +#ifdef CONFIG_ARCH_HAS_KPKEYS +#define SLAB_SET_PKEY __SLAB_FLAG_BIT(_SLAB_SET_PKEY) +#else +#define SLAB_SET_PKEY __SLAB_FLAG_UNUSED +#endif + /* * freeptr_t represents a SLUB freelist pointer, which might be encoded * and not dereferenceable if CONFIG_SLAB_FREELIST_HARDENED is enabled. @@ -331,6 +340,18 @@ struct kmem_cache_args { * %NULL means no constructor. */ void (*ctor)(void *); + /** + * @pkey: The pkey to map the allocated pages with. + * + * If the SLAB flags include SLAB_SET_PKEY, and if kernel pkeys are + * supported, objects are allocated in pages mapped with the protection + * key specified by @pkey. Otherwise, this field is ignored. + * + * Note that if @pkey is a non-default pkey, some overhead is incurred + * when internal slab functions switch the pkey register to write to the + * slab (e.g. setting a free pointer). + */ + int pkey; }; struct kmem_cache *__kmem_cache_create_args(const char *name, diff --git a/mm/slab.h b/mm/slab.h index 1a081f50f947..d5cf5927634a 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -311,6 +311,10 @@ struct kmem_cache { unsigned int usersize; /* Usercopy region size */ #endif +#ifdef CONFIG_ARCH_HAS_KPKEYS + int pkey; +#endif + struct kmem_cache_node *node[MAX_NUMNODES]; }; @@ -462,7 +466,8 @@ static inline bool is_kmalloc_normal(struct kmem_cache *s) SLAB_TYPESAFE_BY_RCU | SLAB_DEBUG_OBJECTS | \ SLAB_NOLEAKTRACE | SLAB_RECLAIM_ACCOUNT | \ SLAB_TEMPORARY | SLAB_ACCOUNT | \ - SLAB_NO_USER_FLAGS | SLAB_KMALLOC | SLAB_NO_MERGE) + SLAB_NO_USER_FLAGS | SLAB_KMALLOC | SLAB_NO_MERGE | \ + SLAB_SET_PKEY) #define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \ SLAB_TRACE | SLAB_CONSISTENCY_CHECKS) diff --git a/mm/slab_common.c b/mm/slab_common.c index 69f9afd85f9f..21323d2a108e 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -47,7 +47,7 @@ struct kmem_cache *kmem_cache; */ #define SLAB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \ SLAB_TRACE | SLAB_TYPESAFE_BY_RCU | SLAB_NOLEAKTRACE | \ - SLAB_FAILSLAB | SLAB_NO_MERGE) + SLAB_FAILSLAB | SLAB_NO_MERGE | SLAB_SET_PKEY) #define SLAB_MERGE_SAME (SLAB_RECLAIM_ACCOUNT | SLAB_CACHE_DMA | \ SLAB_CACHE_DMA32 | SLAB_ACCOUNT) diff --git a/mm/slub.c b/mm/slub.c index 1f50129dcfb3..75b543e255d9 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -459,6 +460,15 @@ static nodemask_t slab_nodes; static struct workqueue_struct *flushwq; #endif +#ifdef CONFIG_ARCH_HAS_KPKEYS +KPKEYS_GUARD_COND(kpkeys_slab_write, + KPKEYS_LVL_UNRESTRICTED, + unlikely(s->flags & SLAB_SET_PKEY), + struct kmem_cache *s) +#else +KPKEYS_GUARD_NOOP(kpkeys_slab_write, struct kmem_cache *s) +#endif + /******************************************************************** * Core slab cache functions *******************************************************************/ @@ -545,6 +555,8 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp) BUG_ON(object == fp); /* naive detection of double free or corruption */ #endif + guard(kpkeys_slab_write)(s); + freeptr_addr = (unsigned long)kasan_reset_tag((void *)freeptr_addr); *(freeptr_t *)freeptr_addr = freelist_ptr_encode(s, fp, freeptr_addr); } @@ -765,6 +777,8 @@ static inline void set_orig_size(struct kmem_cache *s, p += get_info_end(s); p += sizeof(struct track) * 2; + guard(kpkeys_slab_write)(s); + *(unsigned int *)p = orig_size; } @@ -949,6 +963,8 @@ static void set_track_update(struct kmem_cache *s, void *object, { struct track *p = get_track(s, object, alloc); + guard(kpkeys_slab_write)(s); + #ifdef CONFIG_STACKDEPOT p->handle = handle; #endif @@ -973,6 +989,8 @@ static void init_tracking(struct kmem_cache *s, void *object) if (!(s->flags & SLAB_STORE_USER)) return; + guard(kpkeys_slab_write)(s); + p = get_track(s, object, TRACK_ALLOC); memset(p, 0, 2*sizeof(struct track)); } @@ -1137,6 +1155,8 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) u8 *p = kasan_reset_tag(object); unsigned int poison_size = s->object_size; + guard(kpkeys_slab_write)(s); + if (s->flags & SLAB_RED_ZONE) { /* * Here and below, avoid overwriting the KMSAN shadow. Keeping @@ -2335,6 +2355,8 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init, int rsize; unsigned int inuse, orig_size; + guard(kpkeys_slab_write)(s); + inuse = get_info_end(s); orig_size = get_orig_size(s, x); if (!kasan_has_integrated_init()) @@ -2563,6 +2585,8 @@ static __always_inline void unaccount_slab(struct slab *slab, int order, -(PAGE_SIZE << order)); } +static void __free_slab(struct kmem_cache *s, struct slab *slab); + static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) { struct slab *slab; @@ -2612,6 +2636,18 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) setup_slab_debug(s, slab, start); +#ifdef CONFIG_ARCH_HAS_KPKEYS + if (unlikely(s->flags & SLAB_SET_PKEY)) { + int ret = set_memory_pkey((unsigned long)start, + 1 << oo_order(oo), s->pkey); + + if (WARN_ON(ret)) { + __free_slab(s, slab); + return NULL; + } + } +#endif + shuffle = shuffle_freelist(s, slab); if (!shuffle) { @@ -2652,6 +2688,11 @@ static void __free_slab(struct kmem_cache *s, struct slab *slab) __folio_clear_slab(folio); mm_account_reclaimed_pages(pages); unaccount_slab(slab, order, s); +#ifdef CONFIG_ARCH_HAS_KPKEYS + if (unlikely(s->flags & SLAB_SET_PKEY)) + WARN_ON(set_memory_pkey((unsigned long)folio_address(folio), + pages, 0)); +#endif free_frozen_pages(&folio->page, order); } @@ -4053,9 +4094,11 @@ static __always_inline void maybe_wipe_obj_freeptr(struct kmem_cache *s, void *obj) { if (unlikely(slab_want_init_on_free(s)) && obj && - !freeptr_outside_object(s)) + !freeptr_outside_object(s)) { + guard(kpkeys_slab_write)(s); memset((void *)((char *)kasan_reset_tag(obj) + s->offset), 0, sizeof(void *)); + } } static __fastpath_inline @@ -4798,6 +4841,7 @@ __do_krealloc(const void *p, size_t new_size, gfp_t flags) /* Zero out spare memory. */ if (want_init_on_alloc(flags)) { kasan_disable_current(); + guard(kpkeys_slab_write)(s); if (orig_size && orig_size < new_size) memset(kasan_reset_tag(p) + orig_size, 0, new_size - orig_size); else @@ -4807,6 +4851,7 @@ __do_krealloc(const void *p, size_t new_size, gfp_t flags) /* Setup kmalloc redzone when needed */ if (s && slub_debug_orig_size(s)) { + guard(kpkeys_slab_write)(s); set_orig_size(s, (void *)p, new_size); if (s->flags & SLAB_RED_ZONE && new_size < ks) memset_no_sanitize_memory(kasan_reset_tag(p) + new_size, @@ -6162,6 +6207,17 @@ int do_kmem_cache_create(struct kmem_cache *s, const char *name, s->useroffset = args->useroffset; s->usersize = args->usersize; #endif +#ifdef CONFIG_ARCH_HAS_KPKEYS + s->pkey = args->pkey; + + if (s->flags & SLAB_SET_PKEY) { + if (s->pkey >= arch_max_pkey()) + goto out; + + if (!arch_kpkeys_enabled() || s->pkey == KPKEYS_PKEY_DEFAULT) + s->flags &= ~SLAB_SET_PKEY; + } +#endif if (!calculate_sizes(args, s)) goto out; From patchwork Mon Feb 3 10:28:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Brodsky X-Patchwork-Id: 13957221 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 DDE9DC02193 for ; Mon, 3 Feb 2025 10:29:01 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 6701E280011; Mon, 3 Feb 2025 05:29:01 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 61FF528000E; Mon, 3 Feb 2025 05:29:01 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 4C0BC280011; Mon, 3 Feb 2025 05:29:01 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 2946028000E for ; Mon, 3 Feb 2025 05:29:01 -0500 (EST) Received: from smtpin13.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id D985B1C9D8F for ; Mon, 3 Feb 2025 10:28:45 +0000 (UTC) X-FDA: 83078259810.13.0DF4AFC Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf19.hostedemail.com (Postfix) with ESMTP id 4713C1A0008 for ; Mon, 3 Feb 2025 10:28:44 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf19.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738578524; 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=gXEcaQ/nat4AynYmLE14uvl2r7aUGOOMKf84Ghy3AwI=; b=F+Jd/lEPd1GsFTzmGdV7DzhZhv7KE7RhnRSF6Xdp6n8ACWGSP6sh7MIYXEKNSe/P+pT2E1 +PKp+rolQa6XwGriqrfAbhuzx+9Sg9IbiDM1mPGDC2+vIqriOEAxIqEU50UW61OHLxGeyQ sDX6Qr5LXnfR9M3SJ6wwHyyvN2DPZ5M= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf19.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738578524; a=rsa-sha256; cv=none; b=F0nPnhCTaTY14N++No//UUDyxzaLm4biRX8HePQ2Uhg3rdVSmgfchCbAIoEFs2DTp6e7ml yGACaK1HMFhz14D3OF3Tpwdot8spbG6BYLn9KFAfAecCnvsuButADMfZLAvMPKRQtF184c A62bfcschTupCmnYN6emz5kHSG8UV64= 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 128781BA8; Mon, 3 Feb 2025 02:29:08 -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 D8CF83F63F; Mon, 3 Feb 2025 02:28:39 -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 , David Howells , "Eric W. Biederman" , 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 4/8] rcu: Allow processing kpkeys-protected data Date: Mon, 3 Feb 2025 10:28:05 +0000 Message-ID: <20250203102809.1223255-5-kevin.brodsky@arm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250203102809.1223255-1-kevin.brodsky@arm.com> References: <20250203102809.1223255-1-kevin.brodsky@arm.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4713C1A0008 X-Stat-Signature: zoxo9cn1eqroxx9j1p4w1993e9f8qrri X-Rspamd-Server: rspam08 X-Rspam-User: X-HE-Tag: 1738578524-612693 X-HE-Meta: U2FsdGVkX1/NSxoSuRfhTw+dJFLWX2xZDfdr9rCby3Ii4vjGBkON/WUk8QwKXOBzT/8nx5mxs11Mp3kEY+bwzIo5Bg35t5RRTaR7JMmOopppVwDvDoq4iw3fDo62tfZq6wTWD/BZ8hiiImn1R8I2xPVdqyP2F1tr3XBQoQHnFxxsgUlieFF+htdiFdDr0vXpkpcXOVsKKq66e3UiperDf/BRP23XQ1hkYk64CyJX0DGTH99VpI4tsAdEt7sOT76dm4N3Z6ONMDFTni0/ZkAT4YdktYdDJBshHkYyui6+5nG31fsqUAPkLSgMjATfPfwIY9G1Bz+Ac3oPaH26obJIazhluy2/dghEke5+j/MxGJXrEY5KyL0mpCsj6iJg3pde1DbfZlVt3tvukyCa59dPFv9K8X9UG8MhyfbuUrqz3Kkazx68LO4Nv4QHbieKbsSWTthZhzQWgXwiZ8aMEyHKxkra5p/WhMmACLFP+LLKVPIvmx5ukR+r0PDr8spuA3g+LwIpoIgC1SqH/J2F39Gp3eebxl1giH75JdH0eeK+sSEwH1e2JmcgV00fEMr81SrLorsP0q2gpIj/9uN+XSOvI14DF+Fo5W76JtIvYLSsoTgf+iR9xtpgycYWWx39Ne+TAaMrOKBvzmNX2AaFT+O0bwcIaczV9mnGUZ611AvDqiBLO5LHS+osQHuwlxMzquXTWMg9ECh4c+IiQPWhPcr1eand/SmJVZ6LEkw3f+lf4DAqiIMVe9NWj4m9nEIJP9adKp3jOgo/dUsdc5CA+mGOLNGJeG2h2orUQZ/+E+wckSUxVy4EQqL8edXWhNQyH86NdghrKp+kNWCmP/BaPLvFRWseJydUKB/U2z2AkKrJ6gBK7mdpDD/JOA2mEKS0h49ufGmDZnFNDcgNa039cKkNcsY8pe2Tma4Iuh3yuWFmUnJP+QiVBW1SVrDux2ZsiNiLPabtY/5YKpDyxfiH7up DQEwab+Y OCId9MxRbY9M29Q7KjbgEKHXi0cf+35GGM78ailWsCaZpSgmLUqKOGumMAP1IUcqN5wcNo7s6IyY8BvYXteO8uJeXyHoCnn1/0lhdEdHhTf8xY0b95LwzE41sfYLMjPtwiL1UBgxhKgOmiX0GXyEq5xxvDbWNANJrS5CqoOyccZ9veKREAIh8SflVvs7FRInXkNEE 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: Data assigned a non-default pkey is not writable at the default kpkeys level. If such data is managed via RCU, some mechanism is required to temporarily grant write access to the data's struct rcu_head, for instance when zeroing the callback pointer. There is unfortunately no straightforward way for RCU to know whether the managed data is mapped with a non-default pkey. This patch takes the easy route and switches to the unrestricted kpkeys level whenever struct rcu_head is written; this should work reliably but it is clearly suboptimal. That behaviour is enabled by selecting CONFIG_KPKEYS_UNRESTRICTED_RCU. This patch isn't comprehensive, in particular it does not take care of Tiny RCU. Signed-off-by: Kevin Brodsky --- include/linux/kpkeys.h | 6 ++++++ kernel/rcu/rcu_segcblist.c | 10 +++++++--- kernel/rcu/tree.c | 4 +++- mm/Kconfig | 2 ++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/include/linux/kpkeys.h b/include/linux/kpkeys.h index 9d9feec83ccf..c5d804c1ab7b 100644 --- a/include/linux/kpkeys.h +++ b/include/linux/kpkeys.h @@ -154,4 +154,10 @@ static inline void kpkeys_hardened_pgtables_enable(void) {} #endif /* CONFIG_KPKEYS_HARDENED_PGTABLES */ +#ifdef CONFIG_KPKEYS_UNRESTRICTED_RCU +KPKEYS_GUARD(kpkeys_rcu, KPKEYS_LVL_UNRESTRICTED) +#else +KPKEYS_GUARD_NOOP(kpkeys_rcu) +#endif + #endif /* _LINUX_KPKEYS_H */ diff --git a/kernel/rcu/rcu_segcblist.c b/kernel/rcu/rcu_segcblist.c index 298a2c573f02..a9b5552b53a5 100644 --- a/kernel/rcu/rcu_segcblist.c +++ b/kernel/rcu/rcu_segcblist.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "rcu_segcblist.h" @@ -332,7 +333,8 @@ void rcu_segcblist_enqueue(struct rcu_segcblist *rsclp, rcu_segcblist_inc_len(rsclp); rcu_segcblist_inc_seglen(rsclp, RCU_NEXT_TAIL); rhp->next = NULL; - WRITE_ONCE(*rsclp->tails[RCU_NEXT_TAIL], rhp); + scoped_guard(kpkeys_rcu) + WRITE_ONCE(*rsclp->tails[RCU_NEXT_TAIL], rhp); WRITE_ONCE(rsclp->tails[RCU_NEXT_TAIL], &rhp->next); } @@ -381,7 +383,8 @@ void rcu_segcblist_extract_done_cbs(struct rcu_segcblist *rsclp, rclp->len = rcu_segcblist_get_seglen(rsclp, RCU_DONE_TAIL); *rclp->tail = rsclp->head; WRITE_ONCE(rsclp->head, *rsclp->tails[RCU_DONE_TAIL]); - WRITE_ONCE(*rsclp->tails[RCU_DONE_TAIL], NULL); + scoped_guard(kpkeys_rcu) + WRITE_ONCE(*rsclp->tails[RCU_DONE_TAIL], NULL); rclp->tail = rsclp->tails[RCU_DONE_TAIL]; for (i = RCU_CBLIST_NSEGS - 1; i >= RCU_DONE_TAIL; i--) if (rsclp->tails[i] == rsclp->tails[RCU_DONE_TAIL]) @@ -436,7 +439,8 @@ void rcu_segcblist_insert_done_cbs(struct rcu_segcblist *rsclp, if (!rclp->head) return; /* No callbacks to move. */ rcu_segcblist_add_seglen(rsclp, RCU_DONE_TAIL, rclp->len); - *rclp->tail = rsclp->head; + scoped_guard(kpkeys_rcu) + *rclp->tail = rsclp->head; WRITE_ONCE(rsclp->head, rclp->head); for (i = RCU_DONE_TAIL; i < RCU_CBLIST_NSEGS; i++) if (&rsclp->head == rsclp->tails[i]) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 475f31deed14..48d9d14a2af6 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -64,6 +64,7 @@ #include #include #include +#include #include "../time/tick-internal.h" #include "tree.h" @@ -2542,7 +2543,8 @@ static void rcu_do_batch(struct rcu_data *rdp) f = rhp->func; debug_rcu_head_callback(rhp); - WRITE_ONCE(rhp->func, (rcu_callback_t)0L); + scoped_guard(kpkeys_rcu) + WRITE_ONCE(rhp->func, (rcu_callback_t)0L); f(rhp); rcu_lock_release(&rcu_callback_map); diff --git a/mm/Kconfig b/mm/Kconfig index 2a8ebe780e64..e2671c57e047 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -1152,6 +1152,8 @@ config ARCH_HAS_KPKEYS # ARCH_HAS_KPKEYS must be selected when selecting this option config ARCH_HAS_KPKEYS_HARDENED_PGTABLES bool +config KPKEYS_UNRESTRICTED_RCU + bool config ARCH_USES_PG_ARCH_2 bool From patchwork Mon Feb 3 10:28:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Brodsky X-Patchwork-Id: 13957220 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 B31FBC02196 for ; Mon, 3 Feb 2025 10:28:57 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 86BB3280002; Mon, 3 Feb 2025 05:28:56 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 81B5028000E; Mon, 3 Feb 2025 05:28:56 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6BC79280002; Mon, 3 Feb 2025 05:28:56 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id 31D0028000E for ; Mon, 3 Feb 2025 05:28:56 -0500 (EST) Received: from smtpin02.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id EAE4D4CDFE for ; Mon, 3 Feb 2025 10:28:49 +0000 (UTC) X-FDA: 83078259978.02.39E536F Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf06.hostedemail.com (Postfix) with ESMTP id 5EA1F180003 for ; Mon, 3 Feb 2025 10:28:48 +0000 (UTC) Authentication-Results: imf06.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf06.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738578528; a=rsa-sha256; cv=none; b=3LsHkL+DOEY15lQRCU2BrKljuN/rBr2plo/7nIsJnKVEu81+x61iUMXZwOl/V+MQLFzc0X K1rF/dZvTfeKGVigdQG26CH2y7QWqjByeQRThSh5JECEiTpugy0av786utZkdmj1skh7J3 J8LSzc2hHcyqten7ah+QrqA1tK2C6gA= ARC-Authentication-Results: i=1; imf06.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf06.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738578528; 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=tqpNjfnw7iMi+gWoBv0avsygAJN2y4ykdULl/ADYxb8=; b=mxfbNfmpkDs6tySXA5c0ww+VxCIo8w3TIINuTIs7JiLtVwIIuVTqTaEIFAB9c7Er38kMVA VssDGQ2AGkQvR7wOfc1U4j3SkdZEVt0ad6fPHSgPIt/vW/Ps+27m1VFXXZU3VpcvNHgUpQ jC8iQAc4w+iuBFK7onW9r1hFmSoQE7k= 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 23BF31BB0; Mon, 3 Feb 2025 02:29:12 -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 E99793F63F; Mon, 3 Feb 2025 02:28:43 -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 , David Howells , "Eric W. Biederman" , 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 5/8] mm: kpkeys: Introduce cred pkey/level Date: Mon, 3 Feb 2025 10:28:06 +0000 Message-ID: <20250203102809.1223255-6-kevin.brodsky@arm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250203102809.1223255-1-kevin.brodsky@arm.com> References: <20250203102809.1223255-1-kevin.brodsky@arm.com> MIME-Version: 1.0 X-Rspamd-Server: rspam04 X-Rspamd-Queue-Id: 5EA1F180003 X-Stat-Signature: smmx4yu8bcukaacmcsf8drxxjmp64ec3 X-Rspam-User: X-HE-Tag: 1738578528-135936 X-HE-Meta: U2FsdGVkX1+LI4SBuOQtofM65Napi2fA3s3omNqXIHnsLnkswl12GdvLhXdaylEKET9+IW086Js/6L3nExDOhC+paF4AtPLweqm+9siZ4oZjf4SSOXz2ezTFhowVeLVcWosa4pB4vrnDVI3qmbcaqQNPlEsnkc0Nmpj++O5PVMRiejLSr4G6isBu2t7PPqpKa/tD9WEFNjZOa3qfwfsU/CiebCGXQgHmRJNijQwOvTNcrKviSq7MkNWMNIB0Qp2BMNlbHQvB46H6esjB78f57fMDJaWTNsO5oAq0RRQk/y24mYNyaxH+SKMS1U2n4WQzHcXpRAdAsthKBATCQTNkZ+bWNH+3cTfGzcgY9UlObOMXMoSxK79y6vYIO/XvhiPaaZqcqlK1+0UJDUWidzm5dtxdpH6X9z0FJP215ZvLtURQsPLL7GwEGpjFqAuoRN0/SGRKCXsKLAdzPYEzkL9y8QwRCUdb2q6z+vE2k7HkZVbGbPm8jAYwSeURr4yz6ov5MphC3VtDXy6d+dsnBS3fqPYx1pJXpGgfEDj2/PXz3LsmF3T5fjQColeild+MtwHyy4iyY0kAzR8F93phlvGYJcbhdTieX00l94qJGKrDa/668Egc4YyomRvkOvbeH+P1a2pOrO4GqC26XOKPb1u9lUayEjPdWmbaCa68Sc64aPKP37KIZGU+hxBj+h3+wwyALV27i0W4FW9NKWYySFnPlE+kVlVeVqxvZqsA1FgopvACnuFA/vUyfY743B3meVqhXw7rovi0gKPGypJJprtKtfHIjXqd4NUG4aCtd/egKX3Z92zEUxRaWcorqZ4D99O11snb9PX3l0358TJidMNKv4RyCNKBhxsBnyYaze2hQw1AwXHyoEr3RVhbEXfZdVD8PjUps3QFq+WIIuEYEhDnZaBCyQG28XT2RLDpnjag3K6NzCUyef1x5+bPrUCYZiNZQdix15TwNsTiKipOj9+ TScOcpDk c11RR6+G5cZMEwOLIRceBI88mIafg8S4dw/2MQ4LUym0PzAPOznMDNphRALc9eC0kLSZ2bIiFtOMPARAEKk+dPqPd8zoepRB5N4xtprAr9bTgbPh67sgCOyvhjgX3Cp+EuNaOohYgX0MocUMmzEhPPTnQ8Q== 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: We will need a separate pkey to protect struct cred. Allocate one as well as a new kpkeys level that grants write access to that pkey, and add a guard that switches to that level. Signed-off-by: Kevin Brodsky --- arch/arm64/include/asm/kpkeys.h | 4 ++++ include/asm-generic/kpkeys.h | 4 ++++ include/linux/kpkeys.h | 9 ++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kpkeys.h b/arch/arm64/include/asm/kpkeys.h index ab2305ca24b7..f5797e579fb9 100644 --- a/arch/arm64/include/asm/kpkeys.h +++ b/arch/arm64/include/asm/kpkeys.h @@ -22,6 +22,10 @@ static inline u64 por_set_kpkeys_level(u64 por, int level) level == KPKEYS_LVL_PGTABLES || level == KPKEYS_LVL_UNRESTRICTED ? POE_RW : POE_R); + por = por_set_pkey_perms(por, KPKEYS_PKEY_CRED, + level == KPKEYS_LVL_CRED || + level == KPKEYS_LVL_UNRESTRICTED + ? POE_RW : POE_R); return por; } diff --git a/include/asm-generic/kpkeys.h b/include/asm-generic/kpkeys.h index cec92334a9f3..56a2fc9fe4a6 100644 --- a/include/asm-generic/kpkeys.h +++ b/include/asm-generic/kpkeys.h @@ -2,6 +2,10 @@ #ifndef __ASM_GENERIC_KPKEYS_H #define __ASM_GENERIC_KPKEYS_H +#ifndef KPKEYS_PKEY_CRED +#define KPKEYS_PKEY_CRED 2 +#endif + #ifndef KPKEYS_PKEY_PGTABLES #define KPKEYS_PKEY_PGTABLES 1 #endif diff --git a/include/linux/kpkeys.h b/include/linux/kpkeys.h index c5d804c1ab7b..a478eaf2e14f 100644 --- a/include/linux/kpkeys.h +++ b/include/linux/kpkeys.h @@ -10,7 +10,8 @@ struct folio; #define KPKEYS_LVL_DEFAULT 0 #define KPKEYS_LVL_PGTABLES 1 -#define KPKEYS_LVL_UNRESTRICTED 2 +#define KPKEYS_LVL_CRED 2 +#define KPKEYS_LVL_UNRESTRICTED 3 #define KPKEYS_LVL_MIN KPKEYS_LVL_DEFAULT #define KPKEYS_LVL_MAX KPKEYS_LVL_UNRESTRICTED @@ -160,4 +161,10 @@ KPKEYS_GUARD(kpkeys_rcu, KPKEYS_LVL_UNRESTRICTED) KPKEYS_GUARD_NOOP(kpkeys_rcu) #endif +#ifdef CONFIG_KPKEYS_HARDENED_CRED +KPKEYS_GUARD(kpkeys_hardened_cred, KPKEYS_LVL_CRED) +#else +KPKEYS_GUARD_NOOP(kpkeys_hardened_cred) +#endif + #endif /* _LINUX_KPKEYS_H */ From patchwork Mon Feb 3 10:28:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Brodsky X-Patchwork-Id: 13957224 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 DC42BC02192 for ; Mon, 3 Feb 2025 10:29:16 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 6E564280014; Mon, 3 Feb 2025 05:29:16 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 694B928000E; Mon, 3 Feb 2025 05:29:16 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5357A280014; Mon, 3 Feb 2025 05:29:16 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 3691D28000E for ; Mon, 3 Feb 2025 05:29:16 -0500 (EST) Received: from smtpin25.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 1DD971CA953 for ; Mon, 3 Feb 2025 10:28:54 +0000 (UTC) X-FDA: 83078260230.25.F8A048E Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf24.hostedemail.com (Postfix) with ESMTP id 782F8180009 for ; Mon, 3 Feb 2025 10:28:52 +0000 (UTC) Authentication-Results: imf24.hostedemail.com; dkim=none; spf=pass (imf24.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=1738578532; 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=H8lNEuBGD5WSMCCeKCge9CS2olSopCyu/v81KbZt5Mo=; b=geS2R/+ac/UnzzstXBZWILzXCLyHF/eMqK6JCSjEZ/gi1ydYcqtEWlrxFDVtnxZbWm207F jFyVBqOieXKmdzMDalGY8cuNhzW5pohnU3lFZZ0rt/P6hunK1LKOkYChB1hJGs+1/oIFQb TDVyAJ3S1qM6b1SuKB22Jx8BrWSQgQ0= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738578532; a=rsa-sha256; cv=none; b=p11Di9v+d1S313uJ8YlwC52i44+8JCBhf7GOsHdSqNioArJObNwbQSvuWUdXa7gMIRkY1H 20ZCWpk3q6aNYVhwdVPmUA+RtNt34fZ2x9qJH8DzjAjVuNp1nVDf5sHGbsLAtMl+oG+Fsk wGVig5RotgfKe9Oin3+47LWv0u3BK2c= ARC-Authentication-Results: i=1; imf24.hostedemail.com; dkim=none; spf=pass (imf24.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 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 3737B1BB2; Mon, 3 Feb 2025 02:29:16 -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 074ED3F63F; Mon, 3 Feb 2025 02:28:47 -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 , David Howells , "Eric W. Biederman" , 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 6/8] cred: Protect live struct cred with kpkeys Date: Mon, 3 Feb 2025 10:28:07 +0000 Message-ID: <20250203102809.1223255-7-kevin.brodsky@arm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250203102809.1223255-1-kevin.brodsky@arm.com> References: <20250203102809.1223255-1-kevin.brodsky@arm.com> MIME-Version: 1.0 X-Stat-Signature: miipmwcaug8jwcimtcqmcxsnbfgfd68a X-Rspamd-Queue-Id: 782F8180009 X-Rspam-User: X-Rspamd-Server: rspam06 X-HE-Tag: 1738578532-921591 X-HE-Meta: U2FsdGVkX1+36evf3J9vXYi0HJxjwueFP/s/BLdNcxQctgb3MGtDS1zA/L9EsyGZ7AeL1AQmB6D6l+3I2VZBJB7tR3h7LGr8LL2JH4yT6Q2D+Jn3zXTk5poN77y3z5SNwQluvWEYDcLQ5XsIHPLf9yy1qkNya8rPQdM7ZIHiqjHcWc9EqSIeiPWSo1xSq1V2FglXDsFfHRbd08UR8DapwSaqk65c/gB8qhaz55MWAv8s0dtc2HA88WjmJj/KEDlTZSmT3fwhSOLeIz9OOMlrwqt03Fiycn+XuVSM/EMqc0vADI5fY8Ru9Gz8bzoLEApZ34h1OELksLRs2zzOOML5IoVgdMQjeY+PbFww3DH2o9HhMvg7s6HbFGyMhDqeb8cnwRipau++kF/DW4OXwKFfUDCF9g7A8cC4vd593ZHOQqyePKSuxLMachnkVvorWODhAVBfk+gCFrDyGwTladO2fQm7QVJqmr3tI+k0zQ8L9RmbXY3lC+pOsjXTIN+r+1p8lmrdijh1Fy4KALmn/R7tyDIQG6mm+vrIrAgHf1ytpcbYm4O6aYykkL5s5W1sqFmR80OmAYzZ2NmfyxGOW+0/zvFNqZX+jsOGy+W/Lnz2Tsfo2TPXe9vpbv8bSQPOoxXQJg0djjXahw5zcj+f7ajpTax8XweOsOPzwiX9tiUxH1MazhqSSw2WjqSOFRY2nkV2e4YID81pnqiZ2IeQg284GXJu+6+jB3yKANWeIeABPRxxniwnIWe/zepWye41ieICUQqa1MXFihCURcwQye3OfbnZ4bRDIIaSagg3Wxm7vH7+FKrSAWEw/y6OY7Eh3bhnJoodD1IYxZwTUPyvoQRNHuJzjFFlA39teIuBwRzWVoUmvtFXx+f9Sr08bQYRmp2XvrMmntyiuaZUiobl5cIadKSHRbbyr1EvVYCzKj+6ANuTakx9IaukjoPFqzXf4O+UW/ZAVjECW6wSCo25VEH i7buq5bW Ki/SzYW15WPj+nWJEhQMlanacAk6qtlu1tWvTZFX8Cy/BblDLMuPHFoGabYOmqawQSF8WTIZfTJhUMPSKpF7Lk9YB9P8wicJIHO6HIkCtr7rfnC+hLABwChcE9BuVf81sKO4HXscB9wwpx0KGHkO1c92zKw== 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: This patch introduces a feature to prevent unintended modifications of live credentials, by moving them to protected memory when they are installed via commit_creds(). The protection mechanism is kernel pkeys (kpkeys): protected memory is mapped with a non-default pkey and write access is disabled by default. As a result, task->{cred,real_cred} can only be written to by switching to a higher kpkeys level. The kpkeys_hardened_cred feature is enabled by choosing CONFIG_KPKEYS_HARDENED_CRED=y and running on a system supporting kpkeys. Credentials are not directly allocated in protected memory, as that would force all code preparing new credentials to switch kpkeys level. To avoid such disruption, prepare_creds() and variants still allocate standard memory. When commit_creds() is called, the credentials are copied to protected memory, and the temporary object (in a standard kmalloc slab) is freed. This approach does not work so transparently when it comes to override_creds(), because it does not consume the reference: the object it gets passed cannot be moved. Callers of override_creds() will need to explicitly call a new protect_creds() helper to move the credentials to protected memory once they are done preparing them. Some of these callers use the unmodified output of prepare_creds(); prepare_protected_creds() is introduced to avoid an unnecessary copy in such cases. This patch does not handle these situations, but it does not break them either (credentials installed by override_creds() will simply be unprotected). Various helpers need to modify live credentials. To that end, guard(kpkeys_hardened_cred) is introduced to switch to the kpkeys level that enables write access to KPKEYS_PKEY_CRED. Signed-off-by: Kevin Brodsky --- include/linux/cred.h | 6 ++ kernel/cred.c | 178 +++++++++++++++++++++++++++++++------ security/Kconfig.hardening | 13 +++ 3 files changed, 170 insertions(+), 27 deletions(-) diff --git a/include/linux/cred.h b/include/linux/cred.h index 0c3c4b16b469..b854adce7462 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h @@ -16,6 +16,7 @@ #include #include #include +#include struct cred; struct inode; @@ -162,6 +163,8 @@ extern int set_create_files_as(struct cred *, struct inode *); extern int cred_fscmp(const struct cred *, const struct cred *); extern void __init cred_init(void); extern int set_cred_ucounts(struct cred *); +extern struct cred *prepare_protected_creds(void); +extern struct cred *protect_creds(struct cred *); static inline bool cap_ambient_invariant_ok(const struct cred *cred) { @@ -205,6 +208,7 @@ static inline const struct cred *get_cred_many(const struct cred *cred, int nr) struct cred *nonconst_cred = (struct cred *) cred; if (!cred) return cred; + guard(kpkeys_hardened_cred)(); nonconst_cred->non_rcu = 0; atomic_long_add(nr, &nonconst_cred->usage); return cred; @@ -229,6 +233,7 @@ static inline const struct cred *get_cred_rcu(const struct cred *cred) struct cred *nonconst_cred = (struct cred *) cred; if (!cred) return NULL; + guard(kpkeys_hardened_cred)(); if (!atomic_long_inc_not_zero(&nonconst_cred->usage)) return NULL; nonconst_cred->non_rcu = 0; @@ -252,6 +257,7 @@ static inline void put_cred_many(const struct cred *_cred, int nr) struct cred *cred = (struct cred *) _cred; if (cred) { + guard(kpkeys_hardened_cred)(); if (atomic_long_sub_and_test(nr, &cred->usage)) __put_cred(cred); } diff --git a/kernel/cred.c b/kernel/cred.c index 9676965c0981..81664ffef8f7 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -20,6 +20,8 @@ #include #include +#include "../mm/slab.h" + #if 0 #define kdebug(FMT, ...) \ printk("[%-5.5s%5u] " FMT "\n", \ @@ -62,6 +64,48 @@ struct cred init_cred = { .ucounts = &init_ucounts, }; +static bool hardened_cred_enabled(void) +{ + return IS_ENABLED(CONFIG_KPKEYS_HARDENED_CRED) && arch_kpkeys_enabled(); +} + +static bool cred_is_protected(const struct cred *cred) +{ + struct slab *slab; + + slab = virt_to_slab(cred); + if (!slab) + return false; + + return slab->slab_cache->flags & SLAB_SET_PKEY; +} + +static struct cred *alloc_unprotected_creds(gfp_t flags) +{ + if (hardened_cred_enabled()) + return kmalloc(sizeof(struct cred), flags); + else + return kmem_cache_alloc(cred_jar, flags); +} + +static struct cred *alloc_protected_creds(gfp_t flags) +{ + return kmem_cache_alloc(cred_jar, flags); +} + +static void free_creds(struct cred *cred) +{ + bool cred_in_jar = true; + + if (hardened_cred_enabled()) + cred_in_jar = cred_is_protected(cred); + + if (cred_in_jar) + kmem_cache_free(cred_jar, cred); + else + kfree(cred); +} + /* * The RCU callback to actually dispose of a set of credentials */ @@ -75,7 +119,8 @@ static void put_cred_rcu(struct rcu_head *rcu) panic("CRED: put_cred_rcu() sees %p with usage %ld\n", cred, atomic_long_read(&cred->usage)); - security_cred_free(cred); + scoped_guard(kpkeys_hardened_cred) + security_cred_free(cred); key_put(cred->session_keyring); key_put(cred->process_keyring); key_put(cred->thread_keyring); @@ -86,7 +131,7 @@ static void put_cred_rcu(struct rcu_head *rcu) if (cred->ucounts) put_ucounts(cred->ucounts); put_user_ns(cred->user_ns); - kmem_cache_free(cred_jar, cred); + free_creds(cred); } /** @@ -174,7 +219,7 @@ struct cred *cred_alloc_blank(void) { struct cred *new; - new = kmem_cache_zalloc(cred_jar, GFP_KERNEL); + new = alloc_unprotected_creds(GFP_KERNEL | __GFP_ZERO); if (!new) return NULL; @@ -189,29 +234,10 @@ struct cred *cred_alloc_blank(void) return NULL; } -/** - * prepare_creds - Prepare a new set of credentials for modification - * - * Prepare a new set of task credentials for modification. A task's creds - * shouldn't generally be modified directly, therefore this function is used to - * prepare a new copy, which the caller then modifies and then commits by - * calling commit_creds(). - * - * Preparation involves making a copy of the objective creds for modification. - * - * Returns a pointer to the new creds-to-be if successful, NULL otherwise. - * - * Call commit_creds() or abort_creds() to clean up. - */ -struct cred *prepare_creds(void) +static struct cred *__prepare_creds(struct cred *new) { struct task_struct *task = current; const struct cred *old; - struct cred *new; - - new = kmem_cache_alloc(cred_jar, GFP_KERNEL); - if (!new) - return NULL; kdebug("prepare_creds() alloc %p", new); @@ -248,8 +274,57 @@ struct cred *prepare_creds(void) abort_creds(new); return NULL; } + +/** + * prepare_creds - Prepare a new set of credentials for modification + * + * Prepare a new set of task credentials for modification. A task's creds + * shouldn't generally be modified directly, therefore this function is used to + * prepare a new copy, which the caller then modifies and then commits by + * calling commit_creds(). + * + * Preparation involves making a copy of the objective creds for modification. + * + * Returns a pointer to the new creds-to-be if successful, NULL otherwise. + * + * Call commit_creds() or abort_creds() to clean up. + */ +struct cred *prepare_creds(void) +{ + struct cred *new; + + new = alloc_unprotected_creds(GFP_KERNEL); + if (!new) + return NULL; + + return __prepare_creds(new); +} EXPORT_SYMBOL(prepare_creds); + +/** + * prepare_protected_creds - Prepare a new set of credentials in protected + * memory + * + * This function is equivalent to protect_creds(prepare_creds()), but avoids + * the copy in prepare_creds() by directly allocating the credentials in + * protected memory. The returned object may only be modified by switching to + * a higher kpkeys level, if kpkeys_hardened_cred is enabled. + */ +struct cred *prepare_protected_creds(void) +{ + struct cred *new; + + new = alloc_protected_creds(GFP_KERNEL); + if (!new) + return NULL; + + guard(kpkeys_hardened_cred)(); + + return __prepare_creds(new); +} +EXPORT_SYMBOL(prepare_protected_creds); + /* * Prepare credentials for current to perform an execve() * - The caller must hold ->cred_guard_mutex @@ -309,7 +384,9 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) return 0; } - new = prepare_creds(); + guard(kpkeys_hardened_cred)(); + + new = prepare_protected_creds(); if (!new) return -ENOMEM; @@ -400,6 +477,10 @@ int commit_creds(struct cred *new) BUG_ON(task->cred != old); BUG_ON(atomic_long_read(&new->usage) < 1); + guard(kpkeys_hardened_cred)(); + + new = protect_creds(new); + get_cred(new); /* we will require a ref for the subj creds too */ /* dumpability changes */ @@ -555,9 +636,16 @@ int set_cred_ucounts(struct cred *new) */ void __init cred_init(void) { + slab_flags_t flags = SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT; + struct kmem_cache_args args = {}; + + if (hardened_cred_enabled()) { + flags |= SLAB_SET_PKEY; + args.pkey = KPKEYS_PKEY_CRED; + } + /* allocate a slab in which we can store credentials */ - cred_jar = KMEM_CACHE(cred, - SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT); + cred_jar = kmem_cache_create("cred", sizeof(struct cred), &args, flags); } /** @@ -584,7 +672,7 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) if (WARN_ON_ONCE(!daemon)) return NULL; - new = kmem_cache_alloc(cred_jar, GFP_KERNEL); + new = alloc_unprotected_creds(GFP_KERNEL); if (!new) return NULL; @@ -627,6 +715,42 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) } EXPORT_SYMBOL(prepare_kernel_cred); +/** + * protect_creds - Move a set of credentials to protected memory + * @cred: The credentials to protect + * + * If kpkeys_hardened_cred is enabled, this function transfers @cred to + * protected memory. The returned object may only be modified by switching to a + * higher kpkeys level, for instance by using guard(kpkeys_hardened_cred). + * + * Because the credentials are copied to a new location and the old location is + * freed, any exising reference to @cred becomes invalid after this function is + * called. For this reason only the caller should have a reference to @cred. + * + * If any failure occurs, or if kpkeys_hardened_cred is disabled, @cred is + * returned unmodified. + */ +struct cred *protect_creds(struct cred *cred) +{ + struct cred *protected_cred; + + if (!hardened_cred_enabled()) + return cred; + + if (WARN_ON(atomic_long_read(&cred->usage) != 1)) + return cred; + + protected_cred = alloc_protected_creds(GFP_KERNEL); + if (WARN_ON(!protected_cred)) + return cred; + + guard(kpkeys_hardened_cred)(); + + *protected_cred = *cred; + kfree(cred); + return protected_cred; +} + /** * set_security_override - Set the security ID in a set of credentials * @new: The credentials to alter diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index 649847535fc3..1af3a9dae645 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -325,6 +325,19 @@ config KPKEYS_HARDENED_PGTABLES_TEST If unsure, say N. +config KPKEYS_HARDENED_CRED + bool "Harden task credentials using kernel pkeys" + depends on ARCH_HAS_KPKEYS + select KPKEYS_UNRESTRICTED_RCU + help + This option enforces the immutability of tasks credentials + (struct cred) by allocating them with a non-default protection (pkey) + and only enabling write access to that pkey in a limited set of cred + helpers. + + This option has no effect if the system does not support + kernel pkeys. + endmenu config CC_HAS_RANDSTRUCT From patchwork Mon Feb 3 10:28:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Brodsky X-Patchwork-Id: 13957241 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 0B2BDC02192 for ; Mon, 3 Feb 2025 10:29:33 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 8E1ED280015; Mon, 3 Feb 2025 05:29:32 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 8913328000E; Mon, 3 Feb 2025 05:29:32 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 73357280015; Mon, 3 Feb 2025 05:29:32 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 50E9128000E for ; Mon, 3 Feb 2025 05:29:32 -0500 (EST) Received: from smtpin04.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 2E43AA2641 for ; Mon, 3 Feb 2025 10:28:58 +0000 (UTC) X-FDA: 83078260398.04.42FBE5C Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf05.hostedemail.com (Postfix) with ESMTP id 8CC66100002 for ; Mon, 3 Feb 2025 10:28:56 +0000 (UTC) Authentication-Results: imf05.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf05.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738578536; 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=VjrjF09VQnxDeNYh4e1Ha75V6UufRCaFP71EexFz7fY=; b=SwWZmEl0/j1+2z5Ks5x5bKtwbrKkSUMbULt573k/uKc1YCrjpqnPVcSQ/HJB4tuvZag9iD H7wXtMnV6kpeS8MASF2umdjo7wzv+Nuo/X3rsJB1ry4QEBkxkjE216WlEjOVTVwevulFT6 3GVo8+Kg8m4MDAoynUXqvXJZ3j0pkmk= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738578536; a=rsa-sha256; cv=none; b=IsHNiQOvA53zA75XzCoeMR2CwD7Xe0NRvIXHp9iOZ27omnNJdijBinT1pOIs7qkQiIStw+ K5LnEroI7Hr9iBG6B46ucKI7BKvETHFq93CLZvFUyJMXEH/HITcVrhTqkYG7sV7begE0q1 JmamnxVb6POsS/MK1cuDFs4yuZ/m2sk= ARC-Authentication-Results: i=1; imf05.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf05.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com 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 480031BC0; Mon, 3 Feb 2025 02:29:20 -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 196943F63F; Mon, 3 Feb 2025 02:28:51 -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 , David Howells , "Eric W. Biederman" , 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 7/8] fs: Protect creds installed by override_creds() Date: Mon, 3 Feb 2025 10:28:08 +0000 Message-ID: <20250203102809.1223255-8-kevin.brodsky@arm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250203102809.1223255-1-kevin.brodsky@arm.com> References: <20250203102809.1223255-1-kevin.brodsky@arm.com> MIME-Version: 1.0 X-Stat-Signature: 8fe3ae394qfs96k8hmx48bwz5gt48gmg X-Rspam-User: X-Rspamd-Queue-Id: 8CC66100002 X-Rspamd-Server: rspam03 X-HE-Tag: 1738578536-802863 X-HE-Meta: U2FsdGVkX1/+xzJ6jwpZ/faauB3uXDnV1xY/s0P16x/eA/aNVbe9JA2Aa51Mqs2yfhtHL5W/yUw8S/Bj+Sif9zkOcCrFsrDLFnV6mH0ucI+EJ4qeqXiAm/GU+h/UxERv8kZKtsifmkKGg544YW7Ks8GDuj9crtp2VnX3N7OXiCwE8hGSO6Rn4P6EveHMZ78DuafTuxLLm0tJXYXSgyUCrcRKmqMrsvEYX1XkboJpOgJ/OCAm86YOK+/lF7rp9+5rPAxHeo8Ap8uSCqvJMWE3pXBUuhbBCtWZIwhzDqnSIm4+qjthluvMSw9/eJQIg+21NPFAD0BRIyXQXTgsYrChXY+RG5e6lCWssMuApHs7ybvnmKPdFmlD6DCbpCZjfFn1HUfNwffbWp3zIwVNYsudjr2JZ49duinFwidrS1FzDbMh/NJnAEDvk/VePlfEUIX5GuwUvKJV/plnKK/sbIW/xGckgOYHYxerzJApvsfjr6J3LmMNyWgB+sKOgDt8vO7OpTZ3gv9mECrljOQ3Xr3nS1+ilxPP1zoQpddD/pAb9gzkjxjB+dB1/ygbRY0Rq3mor6RVgqdC9vZP+SimD4j50wcS3bTpxTPPbbopS/P8kHOTFElh5vtGL/90z6WeWibE3D3IUo0vXosgfoC8xSHrmvG8SpZvZjHqOZGyXlfKI7Eg9j0eGFzFRJrgW/JobgcmWcq0nNzIdUUbAZmXVzVtChXoRwAnQ7LhEXMpM2nAb2Gza+TZJogaPsChOChFURe7A/9iueUHuLjw2pn74fmTcz4Y1hE4zVoX+GuoHJ23Hrxt/Y69AGUG1X7g5Ar/IfdhOP4XpQmBGRMfI71aZJaxLbXGwS3Uftg7O+8fvowUQUN5pIIr7G+cJjIDkjIBiFL0PNA753BUpjPQkojdz8oL8+jaFUMIvWgmLuLisFq9n49Pp/JYBCX0bPU1NpA5UCZvA8vITEcErcaUecziHKm X+vY8JFm IfBQg/jzvbadeKeoqHZ6zeFKOcFLPGd+sQCXQlLbSeDzPHZScCP9Eh97AXapbBnT8BCe335IhMlOeV5kls66Fou69abmWBbMN1w1LnE6jraNKvPYQXb0TGLV1K5hE/Y3wZ7SdUp5gwhSyjCsWm3PBK7NOGcBPiUl1Er2BbVsCoR0dxKNoyS9QSUEYz0gJmhU9BwCfbxVGa4s56uc= 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: The kpkeys_hardened_cred feature, when enabled, automatically protects credentials installed by commit_creds(). However, because override_creds() does not consume its argument, it is up to its callers to protect the credentials before calling override_creds(). This is done by calling protect_creds(), moving the credentials to a protected memory location. In some cases, the credentials returned by prepare_creds() are passed to override_creds() as-is. In such situation where write access to the credentials is not needed, prepare_protected_creds() is used to avoid the copy incurred by a separate call to protect_creds(). This patch covers the main users of override_creds(), but it is not comprehensive. This patch is a no-op if kpkeys_hardened_cred isn't enabled. Signed-off-by: Kevin Brodsky --- fs/aio.c | 2 +- fs/fuse/passthrough.c | 2 +- fs/nfs/nfs4idmap.c | 2 +- fs/nfsd/auth.c | 2 +- fs/nfsd/nfs4recover.c | 2 +- fs/nfsd/nfsfh.c | 2 +- fs/open.c | 2 +- fs/overlayfs/dir.c | 2 +- fs/overlayfs/super.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 7b976b564cfc..ab9f4c8d778a 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1657,7 +1657,7 @@ static int aio_fsync(struct fsync_iocb *req, const struct iocb *iocb, if (unlikely(!req->file->f_op->fsync)) return -EINVAL; - req->creds = prepare_creds(); + req->creds = prepare_protected_creds(); if (!req->creds) return -ENOMEM; diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index 607ef735ad4a..4451651b1e51 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -248,7 +248,7 @@ int fuse_backing_open(struct fuse_conn *fc, struct fuse_backing_map *map) goto out_fput; fb->file = file; - fb->cred = prepare_creds(); + fb->cred = prepare_protected_creds(); refcount_set(&fb->count, 1); res = fuse_backing_id_alloc(fc, fb); diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c index 25a7c771cfd8..6ff25dd5c2fb 100644 --- a/fs/nfs/nfs4idmap.c +++ b/fs/nfs/nfs4idmap.c @@ -228,7 +228,7 @@ int nfs_idmap_init(void) set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; - id_resolver_cache = cred; + id_resolver_cache = protect_creds(cred); return 0; failed_reg_legacy: diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c index 4dc327e02456..09b377a97147 100644 --- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c @@ -79,7 +79,7 @@ int nfsd_setuser(struct svc_cred *cred, struct svc_export *exp) else new->cap_effective = cap_raise_nfsd_set(new->cap_effective, new->cap_permitted); - put_cred(override_creds(new)); + put_cred(override_creds(protect_creds(new))); return 0; oom: diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 28f4d5311c40..095664648103 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -81,7 +81,7 @@ nfs4_save_creds(const struct cred **original_creds) new->fsuid = GLOBAL_ROOT_UID; new->fsgid = GLOBAL_ROOT_GID; - *original_creds = override_creds(new); + *original_creds = override_creds(protect_creds(new)); return 0; } diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 32019751a41e..d64d23e9357e 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -221,7 +221,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct net *net, new->cap_effective = cap_raise_nfsd_set(new->cap_effective, new->cap_permitted); - put_cred(override_creds(new)); + put_cred(override_creds(protect_creds(new))); } else { error = nfsd_setuser_and_check_port(rqstp, cred, exp); if (error) diff --git a/fs/open.c b/fs/open.c index 932e5a6de63b..3b5331b7c0f0 100644 --- a/fs/open.c +++ b/fs/open.c @@ -457,7 +457,7 @@ static const struct cred *access_override_creds(void) * freeing. */ override_cred->non_rcu = 1; - return override_creds(override_cred); + return override_creds(protect_creds(override_cred)); } static long do_faccessat(int dfd, const char __user *filename, int mode, int flags) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index c9993ff66fc2..943ec4300ddb 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -580,7 +580,7 @@ static const struct cred *ovl_setup_cred_for_create(struct dentry *dentry, * We must be called with creator creds already, otherwise we risk * leaking creds. */ - old_cred = override_creds(override_cred); + old_cred = override_creds(protect_creds(override_cred)); WARN_ON_ONCE(old_cred != ovl_creds(dentry->d_sb)); return override_cred; diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 86ae6f6da36b..3489a62c5d8a 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -1318,7 +1318,7 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_d_op = &ovl_dentry_operations; err = -ENOMEM; - ofs->creator_cred = cred = prepare_creds(); + ofs->creator_cred = cred = prepare_protected_creds(); if (!cred) goto out_err; From patchwork Mon Feb 3 10:28:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Brodsky X-Patchwork-Id: 13957223 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 A3C78C02192 for ; Mon, 3 Feb 2025 10:29:11 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 38B30280012; Mon, 3 Feb 2025 05:29:11 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 3131B28000E; Mon, 3 Feb 2025 05:29:11 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 20272280012; Mon, 3 Feb 2025 05:29:11 -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 F1F6828000E for ; Mon, 3 Feb 2025 05:29:10 -0500 (EST) Received: from smtpin04.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id 3AD8E4B3FC for ; Mon, 3 Feb 2025 10:29:02 +0000 (UTC) X-FDA: 83078260524.04.1524288 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf23.hostedemail.com (Postfix) with ESMTP id 89636140002 for ; Mon, 3 Feb 2025 10:29:00 +0000 (UTC) Authentication-Results: imf23.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf23.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1738578540; 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=zoyyTWy8+Zu7JkfSAKSCzAU5xw+8zxp6lIz7/LeWBsU=; b=sD4QuTXsxYTSiLE6oEEF6NJE2HrAsOPR7zYwaRVS/QrGcrNjN6QU1KtXYnnZ5Qm62cS/3P ZezmcciGEZd5Er/J5O25SpjruCrcPazvNZ0nj4dircV1VEDvrhqfbb28eWjzt5Cs8CTIDq y+Aj00ELxnGJSaGsl6iECDpnUS7gJbk= ARC-Authentication-Results: i=1; imf23.hostedemail.com; dkim=none; dmarc=pass (policy=none) header.from=arm.com; spf=pass (imf23.hostedemail.com: domain of kevin.brodsky@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=kevin.brodsky@arm.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1738578540; a=rsa-sha256; cv=none; b=ve4ABVwC6m2syg75U9bnc0PGnySsz7trQTu38q4+NUwKP3Yd1Vq9H99Vs9IJogSDRrr/Xn 52P54gPIrNjU4gssVvXYQPXVD23V0ez0fno0qMU/NoOJ5SSXa/qqNwfMq8D1zo8v1rLaqu vOfUYwne9njicO6z3LxmNfIXE9u1kpA= 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 5909D1BCA; Mon, 3 Feb 2025 02:29:24 -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 2AE363F7BD; Mon, 3 Feb 2025 02:28:56 -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 , David Howells , "Eric W. Biederman" , 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 8/8] mm: Add basic tests for kpkeys_hardened_cred Date: Mon, 3 Feb 2025 10:28:09 +0000 Message-ID: <20250203102809.1223255-9-kevin.brodsky@arm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250203102809.1223255-1-kevin.brodsky@arm.com> References: <20250203102809.1223255-1-kevin.brodsky@arm.com> MIME-Version: 1.0 X-Rspamd-Server: rspam05 X-Rspamd-Queue-Id: 89636140002 X-Stat-Signature: 3crr676owubnjmbng853ztn3r1hwmish X-Rspam-User: X-HE-Tag: 1738578540-105660 X-HE-Meta: U2FsdGVkX1/aT2GzGMxcdfPC6EMadn3LGMolaV2cZlu9udNBhRiC0IeQI8bW/JCJIcNzq+e1hnWR0fJBzz2+8uig04FOokB3ngUSt4T1HEO97Tain6a/oI5Ctq8oIOy+VmRFaN2LVCE6Hd9ySK8wvpqiJj53x+wCiHdllWz+3gynLrD7i6ocsNnfQ/bToJaIVZ/zkQ9wVMPm5UiHYdHgoZvi0Dye7fHp9r3qqB1iazB0BvxEt8lEq0DPEv7SPuJ1pkmU/CTZnLQVMKKpE4PZXyRes86qcjd9LGv1arxCfQi/c/8c/eyfZLiAvOia0H3GjM8zlvvM7CJjrv4CY90bCh8rTFn+rs+2qFHDnuffI/QKCqCTPW7Qfgb9R0FeZwq0GozEInST0f8nvso3+lZHVwL94nHM/NVngJmBEptHJUdKcqMW8KfTLA5hCDm3m7pqvxJhF5RHvysAZ00oPgSOBtvtR+2r7zALWIQRY78YYCQREstf9KEpiSIXqzIxPC6uJvepemIolyPXZHAZ+S3am//eCyPJVJItLc9Awd9jXuAAX4nbFhpGUl6no3IIZqiuhB/NVpX0OtIIrwxGNZ4CCxUMaetUxu03zJ4/8zTQzD7sm/4ZSw3KF/hXQh5Ol5JPRWNkKRjRKSHIVBVMqTgZ0SqgJR+hSuFpnJm7NPuEVzf93pYgtjjSyXlZAY4yN/z70ZrW6y5WPuNvPpywYytD5Z55MN9ysJo/JI3ql2qUmgHrGwtSKBD4NmOyn3w5zqTvZ9PjpNTBOEwPKfO8msh5czyZmyUvggSbRPbWsWjREW9WeuEjoJPJz4fqjvFH+eLOZZdsnZTCQK1Zs6ok6Ls7cBjkjEZxiLAypDGMuQPO3398//uUqNjAHlMOkckCyU/Ib5UdM0d9mDCaSKAqgZ6fhjniWfJoeKpeliqUFHRp6WpTYwPjmYJPN/nXEMLk+Pjrr7QMyqZgIfvDTonaIKj 34nYPnYk 2nlmI+i+PnUGiNBL2UkNiEuYtgUcE8vJwec/zuIkB6KFiTjTbTRxiPyMzXpPZdO1Nqya5F0+aK7VVYfTkS6fe7SqoLhnrgaJomGt+bystIZaqFp6ZlxLx2RCeFyBk2AMp7axlEh0ITuDXPOUNbXoWB+gJy2F/F6eQxPIYzgs737YgagBEvpW+th/bO7ningLNafVGM7mwS7lV7RI= 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 current->{cred,real_cred} and ensure it fails. Signed-off-by: Kevin Brodsky --- mm/Makefile | 1 + mm/kpkeys_hardened_cred_test.c | 42 ++++++++++++++++++++++++++++++++++ security/Kconfig.hardening | 11 +++++++++ 3 files changed, 54 insertions(+) create mode 100644 mm/kpkeys_hardened_cred_test.c diff --git a/mm/Makefile b/mm/Makefile index f7263b7f45b8..2024226902d4 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -149,3 +149,4 @@ 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 +obj-$(CONFIG_KPKEYS_HARDENED_CRED_TEST) += kpkeys_hardened_cred_test.o diff --git a/mm/kpkeys_hardened_cred_test.c b/mm/kpkeys_hardened_cred_test.c new file mode 100644 index 000000000000..46048098f99d --- /dev/null +++ b/mm/kpkeys_hardened_cred_test.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include + +static void write_cred(struct kunit *test) +{ + long zero = 0; + int ret; + + ret = copy_to_kernel_nofault((unsigned long *)current->cred, &zero, sizeof(zero)); + KUNIT_EXPECT_EQ_MSG(test, ret, -EFAULT, + "Write to current->cred wasn't prevented"); + + ret = copy_to_kernel_nofault((unsigned long *)current->real_cred, &zero, sizeof(zero)); + KUNIT_EXPECT_EQ_MSG(test, ret, -EFAULT, + "Write to current->real_cred wasn't prevented"); +} + +static int kpkeys_hardened_cred_suite_init(struct kunit_suite *suite) +{ + if (!arch_kpkeys_enabled()) { + pr_err("Cannot run kpkeys_hardened_cred tests: kpkeys are not supported\n"); + return 1; + } + + return 0; +} + +static struct kunit_case kpkeys_hardened_cred_test_cases[] = { + KUNIT_CASE(write_cred), + {} +}; + +static struct kunit_suite kpkeys_hardened_cred_test_suite = { + .name = "Hardened credentials using kpkeys", + .test_cases = kpkeys_hardened_cred_test_cases, + .suite_init = kpkeys_hardened_cred_suite_init, +}; +kunit_test_suite(kpkeys_hardened_cred_test_suite); + +MODULE_DESCRIPTION("Tests for the kpkeys_hardened_cred feature"); +MODULE_LICENSE("GPL"); diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index 1af3a9dae645..9b0563a03ab4 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -338,6 +338,17 @@ config KPKEYS_HARDENED_CRED This option has no effect if the system does not support kernel pkeys. +config KPKEYS_HARDENED_CRED_TEST + tristate "KUnit tests for kpkeys_hardened_cred" if !KUNIT_ALL_TESTS + depends on KPKEYS_HARDENED_CRED + depends on KUNIT + default KUNIT_ALL_TESTS + help + Enable this option to check that the kpkeys_hardened_cred feature + functions as intended, i.e. prevents arbitrary writes to live credentials. + + If unsure, say N. + endmenu config CC_HAS_RANDSTRUCT