From patchwork Mon May 15 13:05:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13241402 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 DCA77C7EE22 for ; Mon, 15 May 2023 13:08:03 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 5BDE5900009; Mon, 15 May 2023 09:08:03 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 56D5990000A; Mon, 15 May 2023 09:08:03 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 40E70900009; Mon, 15 May 2023 09:08:03 -0400 (EDT) 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 259FE900002 for ; Mon, 15 May 2023 09:08:03 -0400 (EDT) Received: from smtpin05.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id B583A80F15 for ; Mon, 15 May 2023 13:08:02 +0000 (UTC) X-FDA: 80792517204.05.7BE2D94 Received: from mail-pg1-f174.google.com (mail-pg1-f174.google.com [209.85.215.174]) by imf28.hostedemail.com (Postfix) with ESMTP id 1E623C01AB for ; Mon, 15 May 2023 13:06:02 +0000 (UTC) Authentication-Results: imf28.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b="N/+vAM46"; spf=pass (imf28.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.215.174 as permitted sender) smtp.mailfrom=jeffxu@chromium.org; dmarc=pass (policy=none) header.from=chromium.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1684155963; 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:dkim-signature; bh=amUmjeQdjogZim3KCvDHtpibL1Mlx7r/unbXJ7VLzz4=; b=yUTzj1JOrhwLTd3BtH1JsPKUbOXyTzjxiTBffR/TgddfOIisF4FlqwX4OLunfXb4jyqlgo 7V00rvCpWxvJcRiRNpfbTZLqvpZhtl4P5OSj1BzHlTUDZcsXMvP6PXsUVHBy9Y+X3Lx1Np +cN+JpCEKTsueimhLmcjPalRwT7rQOk= ARC-Authentication-Results: i=1; imf28.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b="N/+vAM46"; spf=pass (imf28.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.215.174 as permitted sender) smtp.mailfrom=jeffxu@chromium.org; dmarc=pass (policy=none) header.from=chromium.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1684155963; a=rsa-sha256; cv=none; b=ymaQT+jHVLk5GvStL5xqiMXkAxRJnsGwhfAnksyPPT/kHji+0FdF86clinur8Q43LULwP4 IcQY9GkbBcDCc3UaUjOqqaeiUmaV0UMxc7tj90JCqTh1d/Zn8KmkpSNJIUyrYmazUbnWeB F/blJIpN070VRNFuu0VL5bK4WAGMq98= Received: by mail-pg1-f174.google.com with SMTP id 41be03b00d2f7-52c30fbccd4so11751142a12.0 for ; Mon, 15 May 2023 06:06:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1684155961; x=1686747961; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=amUmjeQdjogZim3KCvDHtpibL1Mlx7r/unbXJ7VLzz4=; b=N/+vAM467OglvcK5xTQfs4XWaq6XdqOUlnNqgaqWQ23QJto1u5hnHaDbMk15m9A1Dr YOq7k5ElDFHK8lgmhn3iChrsAtjQgcB4vHR77/JH3M/x2tgCBJK502XSHwtBKBaZYzbk rA7ZQqU99ZIhg7TK53UiwR7aFgmnN3dZNqKsA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684155961; x=1686747961; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=amUmjeQdjogZim3KCvDHtpibL1Mlx7r/unbXJ7VLzz4=; b=H7w+alu4XP/Q3H3aFnVndPinCwT2LOTnFyrnWPTvf+g121QKjQH1D1gKuC4JO1OKyD JH4P0mc2jfELJyFbzMHM2eDyisPVazzEipCXYeE4Q8prpB5aDKRF6svAJKGKiJFg0D1H iO9bZU21JCv2sQ5167hZzA20fNkK7leE1Z+PvOEwiRZ/TWeRbM0ZlhlGRcq87Gq+Ta+r FeABRK1iQRRKEGG4+uDgcm4kLE0eBin2nREtGEniDZF38DmXx3nKorOAy0k9/OeMuC+c fHHEzT+GrOJhqTGy0UBkAlinMj7xaqeabF1oo+bOUMzJC8g9tKZ+Qvh6bUNUvvzAhav3 LQfQ== X-Gm-Message-State: AC+VfDzvwCiyTzZNgdzaUzFnbSkNjT04keuX3HksNqFgNDpN3/ikruFN RzzHy9pVW/hFBakN/I7Y2EAOrQ== X-Google-Smtp-Source: ACHHUZ54OoJ9C5mGmXEjFBPZ+0O08cKmkUJ5oO7isFCKnT6ICVIBMxV1xzNCBVY30Rgzi3YVlV184g== X-Received: by 2002:a05:6a20:72aa:b0:100:d061:52ce with SMTP id o42-20020a056a2072aa00b00100d06152cemr30768717pzk.55.1684155961118; Mon, 15 May 2023 06:06:01 -0700 (PDT) Received: from localhost (183.43.230.35.bc.googleusercontent.com. [35.230.43.183]) by smtp.gmail.com with UTF8SMTPSA id g17-20020aa78751000000b005aa60d8545esm11745710pfo.61.2023.05.15.06.06.00 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 15 May 2023 06:06:00 -0700 (PDT) From: jeffxu@chromium.org To: dave.hansen@intel.com, luto@kernel.org, jorgelo@chromium.org, keescook@chromium.org, groeck@chromium.org, jannh@google.com, sroettger@google.com Cc: akpm@linux-foundation.org, jeffxu@google.com, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, linux-hardening@vger.kernel.org Subject: [PATCH 1/6] PKEY: Introduce PKEY_ENFORCE_API flag Date: Mon, 15 May 2023 13:05:47 +0000 Message-ID: <20230515130553.2311248-2-jeffxu@chromium.org> X-Mailer: git-send-email 2.40.1.606.ga4b1b128d6-goog In-Reply-To: <20230515130553.2311248-1-jeffxu@chromium.org> References: <20230515130553.2311248-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam01 X-Rspamd-Queue-Id: 1E623C01AB X-Stat-Signature: tfzy4dq4rnm5nrkwox5rkyq7efkc8ayf X-HE-Tag: 1684155962-851798 X-HE-Meta: U2FsdGVkX1+xWf7oQVev4dYDYWLS/Ax1ifhtQQaOW22NNGxez8CoEOX5RiDf5PfH0GPComrpiC0VtEjivYD/RKzo8SEfG1ZLBzpqW0l3l2iOaxYrw1jqvKOGkclWTyI8Od4TgaDvWnwNWQAXDTGOdzTayCtHSIiWvqg9amugENKxNSmVBush6xcnXJGpDX1c9sq6pUy5vI78x6rCDwJmh7Zy4jt1rUBRc60NMgSFpcseEvt+C/xXG+jAXlPBa+DeIP652x9ipWwvOU6sQdXKWnm665lVNnjJfmUQ0MUPT33VUwvEkM5XsASqcSR6oreb4mqm8wYM1n15ESSXwXNxd+VdliJ4+gfXpF3Hu6nEOvGfBPXHT4FqZ63VmE7qjNMeNJzGnhRK+6Mkty1HRnHKm6hiK/vfzxeoW4M2tah1cxrHlfWYne92Vg/42Zx9hwOE/KOsie4/mGhQvvS31K/jSMngcoXn1THhaHEuWijVW63Jzrzga1ypsMXWUEc153tqGVUAXJDzL4/YE/OfTljJFs0b/Ca4+MOKkgSMT4rERaxQsDdOM04q7oZD4IlyypSH95g0vffNvn+TRp+DzJ143rC3dp/zHukzOxFzOzq4khNUpJM352H62/ZquOUpvxjSKq9zHdOCkmpH09y2j+GNdY3K+CQ+SHTFWKyNwhX1rrB7uS3D3WErAwHmD42zV/iY4N4X6x38h6RczL3tRvAIT8g3TB1R2vWiJBCqpNCA6RsmyDJbMV+6MEteq+iZtWK1GEgCdnx5WhvuqRcqME1eDpoYnAHkagMZCibrH57udaD1BxMffH9/6zGQowweUvF8dlz6olmIoJHozYcmCsCkBTr0o0R4vJrtfRiVq1OUPRNFQa14zuTnA1yjeFsdVLDl6jFssEDZalLw8R9/tZSIrjJ9F4YXoHYtVxfBTlRgchwu7z16SX7okcYhlrjW/H0t6lrMzrKz3U4bolug/2Z nonL4c9X SaK96rypRJ77wYkcyQofsoykjUwhkGm6d59Zqg4xKaaJeSqzF4xzRECdAqNKtdyLcZUQwGWIGOMcomEYmTYmvlT6NM9Wc9HCyPqPuW0m1znIlN4+rldPBTRDl4CxP6lOkmqW7ds1C61Dc5YjdcS8Uul/00fiApHfSiTG84mVUgloXNADysgnnJYrFGt2LR0niH7J9D9PB2VVfvPSb1r6hBSxTC7zl7+GFUWyrMu9dg+E3Udf5J6tK6/raiZcNYHrPpge6508exdp2UA+a228Fnmia+9a6X2SBHAMdwYY/4RgAWud/eCRx3r37vZQva5xFjgYXONoRFrd5qwHAplGRPDvQdmKcfkwYuxvyVqJ7SM0+KNtathFeVMgX8w== 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: From: Jeff Xu This patch introduces a new flag, PKEY_ENFORCE_API, to the pkey_alloc() function. When a PKEY is created with this flag, it is enforced that any thread that wants to make changes to the memory mapping (such as mprotect/munmap) of the memory must have write access to the PKEY. This is to prevent unauthorized access to protected memory. PKEYs created without this flag will continue to work as they do now, for backwards compatibility. Signed-off-by: Jeff Xu --- arch/powerpc/include/asm/pkeys.h | 11 ++++++++- arch/x86/include/asm/mmu.h | 7 ++++++ arch/x86/include/asm/pkeys.h | 42 ++++++++++++++++++++++++++++++-- arch/x86/mm/pkeys.c | 2 +- include/linux/pkeys.h | 9 ++++++- include/uapi/linux/mman.h | 5 ++++ mm/mprotect.c | 6 ++--- 7 files changed, 74 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h index 59a2c7dbc78f..943333ac0fee 100644 --- a/arch/powerpc/include/asm/pkeys.h +++ b/arch/powerpc/include/asm/pkeys.h @@ -82,7 +82,7 @@ static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) * Relies on the mmap_lock to protect against concurrency in mm_pkey_alloc() and * mm_pkey_free(). */ -static inline int mm_pkey_alloc(struct mm_struct *mm) +static inline int mm_pkey_alloc(struct mm_struct *mm, unsigned long flags) { /* * Note: this is the one and only place we make sure that the pkey is @@ -168,5 +168,14 @@ static inline bool arch_pkeys_enabled(void) return mmu_has_feature(MMU_FTR_PKEY); } +static inline bool arch_check_pkey_alloc_flags(unsigned long flags) +{ + /* No flags supported yet. */ + if (flags) + return false; + + return true; +} + extern void pkey_mm_init(struct mm_struct *mm); #endif /*_ASM_POWERPC_KEYS_H */ diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h index 0da5c227f490..d97594b44d9a 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -66,6 +66,13 @@ typedef struct { */ u16 pkey_allocation_map; s16 execute_only_pkey; + /* + * One bit per protection key. + * When set, thread must have write permission on corresponding + * PKRU in order to call memory mapping API, such as mprotect, + * munmap, etc. + */ + u16 pkey_enforce_api_map; #endif } mm_context_t; diff --git a/arch/x86/include/asm/pkeys.h b/arch/x86/include/asm/pkeys.h index 2e6c04d8a45b..ecadf04a8251 100644 --- a/arch/x86/include/asm/pkeys.h +++ b/arch/x86/include/asm/pkeys.h @@ -51,6 +51,17 @@ static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma, mm_pkey_allocation_map(mm) &= ~(1U << pkey); \ } while (0) +#define mm_pkey_enforce_api_map(mm) (mm->context.pkey_enforce_api_map) +#define mm_set_pkey_enforce_api(mm, pkey) \ + { \ + mm_pkey_enforce_api_map(mm) |= (1U << pkey); \ + } + +#define mm_clear_pkey_enforce_api(mm, pkey) \ + { \ + mm_pkey_enforce_api_map(mm) &= ~(1U << pkey); \ + } + static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) { @@ -74,11 +85,25 @@ bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) return mm_pkey_allocation_map(mm) & (1U << pkey); } +/* + * Return true if the pkey has ENFORCE_API flag during allocation. + */ +static inline bool mm_pkey_enforce_api(struct mm_struct *mm, int pkey) +{ + /* + * Only pkey created by user space has the flag. + * execute_only_pkey check is in mm_pkey_is_allocated(). + */ + if (pkey != ARCH_DEFAULT_PKEY && mm_pkey_is_allocated(mm, pkey)) + return mm_pkey_enforce_api_map(mm) & (1U << pkey); + + return false; +} + /* * Returns a positive, 4-bit key on success, or -1 on failure. */ -static inline -int mm_pkey_alloc(struct mm_struct *mm) +static inline int mm_pkey_alloc(struct mm_struct *mm, unsigned long flags) { /* * Note: this is the one and only place we make sure @@ -101,6 +126,9 @@ int mm_pkey_alloc(struct mm_struct *mm) mm_set_pkey_allocated(mm, ret); + if (flags & PKEY_ENFORCE_API) + mm_set_pkey_enforce_api(mm, ret); + return ret; } @@ -110,6 +138,7 @@ int mm_pkey_free(struct mm_struct *mm, int pkey) if (!mm_pkey_is_allocated(mm, pkey)) return -EINVAL; + mm_clear_pkey_enforce_api(mm, pkey); mm_set_pkey_free(mm, pkey); return 0; @@ -123,4 +152,13 @@ static inline int vma_pkey(struct vm_area_struct *vma) return (vma->vm_flags & vma_pkey_mask) >> VM_PKEY_SHIFT; } +static inline bool arch_check_pkey_alloc_flags(unsigned long flags) +{ + unsigned long valid_flags = PKEY_ENFORCE_API; + + if (flags & ~valid_flags) + return false; + + return true; +} #endif /*_ASM_X86_PKEYS_H */ diff --git a/arch/x86/mm/pkeys.c b/arch/x86/mm/pkeys.c index 7418c367e328..a76981f44acf 100644 --- a/arch/x86/mm/pkeys.c +++ b/arch/x86/mm/pkeys.c @@ -20,7 +20,7 @@ int __execute_only_pkey(struct mm_struct *mm) /* Do we need to assign a pkey for mm's execute-only maps? */ if (execute_only_pkey == -1) { /* Go allocate one to use, which might fail */ - execute_only_pkey = mm_pkey_alloc(mm); + execute_only_pkey = mm_pkey_alloc(mm, 0); if (execute_only_pkey < 0) return -1; need_to_set_mm_pkey = true; diff --git a/include/linux/pkeys.h b/include/linux/pkeys.h index 86be8bf27b41..81a482c3e051 100644 --- a/include/linux/pkeys.h +++ b/include/linux/pkeys.h @@ -3,6 +3,7 @@ #define _LINUX_PKEYS_H #include +#include #define ARCH_DEFAULT_PKEY 0 @@ -25,7 +26,7 @@ static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) return (pkey == 0); } -static inline int mm_pkey_alloc(struct mm_struct *mm) +static inline int mm_pkey_alloc(struct mm_struct *mm, unsigned long flags) { return -1; } @@ -46,6 +47,12 @@ static inline bool arch_pkeys_enabled(void) return false; } +static inline bool arch_check_pkey_alloc_flags(unsigned long flags) +{ + if (flags) + return false; + return true; +} #endif /* ! CONFIG_ARCH_HAS_PKEYS */ #endif /* _LINUX_PKEYS_H */ diff --git a/include/uapi/linux/mman.h b/include/uapi/linux/mman.h index f55bc680b5b0..8c69b9a7ff5b 100644 --- a/include/uapi/linux/mman.h +++ b/include/uapi/linux/mman.h @@ -41,4 +41,9 @@ #define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB #define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB +/* + * Flags for pkey_alloc + */ +#define PKEY_ENFORCE_API (1 << 0) + #endif /* _UAPI_LINUX_MMAN_H */ diff --git a/mm/mprotect.c b/mm/mprotect.c index 92d3d3ca390a..8a68fdca8487 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -894,15 +894,15 @@ SYSCALL_DEFINE2(pkey_alloc, unsigned long, flags, unsigned long, init_val) int pkey; int ret; - /* No flags supported yet. */ - if (flags) + if (!arch_check_pkey_alloc_flags(flags)) return -EINVAL; + /* check for unsupported init values */ if (init_val & ~PKEY_ACCESS_MASK) return -EINVAL; mmap_write_lock(current->mm); - pkey = mm_pkey_alloc(current->mm); + pkey = mm_pkey_alloc(current->mm, flags); ret = -ENOSPC; if (pkey == -1)