From patchwork Tue Dec 12 23:17:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13490092 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 7B961C4167D for ; Tue, 12 Dec 2023 23:17:38 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 590D66B03E5; Tue, 12 Dec 2023 18:17:23 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 4020C6B03E7; Tue, 12 Dec 2023 18:17:23 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 1E23A6B03E8; Tue, 12 Dec 2023 18:17:23 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 063186B03E5 for ; Tue, 12 Dec 2023 18:17:23 -0500 (EST) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id D794D1409D1 for ; Tue, 12 Dec 2023 23:17:22 +0000 (UTC) X-FDA: 81559729524.08.442907D Received: from mail-oo1-f53.google.com (mail-oo1-f53.google.com [209.85.161.53]) by imf10.hostedemail.com (Postfix) with ESMTP id EDD3AC0002 for ; Tue, 12 Dec 2023 23:17:20 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=bfPcKQ82; spf=pass (imf10.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.161.53 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=1702423041; 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=cZjoMoZfbLgYK7cJaZ0EBpgFOBwo/12832X2C7MVeuk=; b=1dS5Rx+hGMit/9ZKduddLNgKpt6kwrNCsY2kLOkk7nlO8oJR3VmVnzLgbqC7OlHpXVKIK1 Okhr2Aw6KArsVj1rkEIC2yQbhNhMqIqbxvonpMtyKHIA0HmVHNcsIKz+tlZyTHx8n3/5vs p5lym30TTnI33nzJZok1cPOoRKocQi4= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1702423041; a=rsa-sha256; cv=none; b=WfpGSKpfz3y6tXvmKTNCpdbtpuGhDrlX1/EB52iaFGDcOoAQmDfH22d2RcJeEPgbBVlDdL HoY8NW6eNpZEXJM40xXf8hWYLKlwogZzugbrjvUIKn2ykWvSQ2lzSXvADaeP/pEcY0Lkl3 e+aF0uccPE3W2mbkkjXs/0jBM/+IrgE= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=bfPcKQ82; spf=pass (imf10.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.161.53 as permitted sender) smtp.mailfrom=jeffxu@chromium.org; dmarc=pass (policy=none) header.from=chromium.org Received: by mail-oo1-f53.google.com with SMTP id 006d021491bc7-58df5988172so3954850eaf.0 for ; Tue, 12 Dec 2023 15:17:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1702423040; x=1703027840; darn=kvack.org; 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=cZjoMoZfbLgYK7cJaZ0EBpgFOBwo/12832X2C7MVeuk=; b=bfPcKQ82RwAhtH90xAfdMsccXs+H34GiB04VyvY+OC7oFPAR5jNly0e95RuzxlRGIs zI/2cesK4A6mUyu8GYMSCBvs7mI13cw5M1rzUH4f2tbzO1rmj8zBMIpU+nOvpBLNQ8F1 +sdgwhd5PvU88zoPRnnmAVc98qhbikSJfQfvI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702423040; x=1703027840; 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=cZjoMoZfbLgYK7cJaZ0EBpgFOBwo/12832X2C7MVeuk=; b=B8CgD5CNZxln6okpZLcZuouAPT2wpDCEaT5uMi/C/MH5BBU7Ns3k3VcHG0ltafOzcR ZVJEPU/SharGoPbtz08DiNIH6WXfdVHMvDWYcnj6CSpc3nIoRIKQyh0YjGwYNwYtr27m fk2jzRdZzk9/fGN6dh7XGC6HuiCVp8elLeUiyi7K0WaTovCWShcf/fqoDuUmgKknz3on SvVK1OvIjpNHVo35rG9MEhfir6XM4RAevQmlLfcJDfX5TORbk8HEC7row879Xq9CRnoL VwYUpvqDMOT9eiCTquLW6i0y7QmjN1T1kgt7uDnmwFAhDHddShOSekHJSUjKQIB2itGO ieSQ== X-Gm-Message-State: AOJu0Yyo3LGlflKRSqIXGGHW3/lV5h+GXqjtNMcC2QGje4ZFOZd+xWyn tbW9QA6bBJrXvQhrq6CAvD/nIw== X-Google-Smtp-Source: AGHT+IGRI96+S8G+Wu1lZ2r1WtnFErIwHP6EFRT0QHSV6FRdjptIOjAkrTcn5HdK1GH4IA0qfPmw5g== X-Received: by 2002:a05:6358:7296:b0:170:17eb:2039 with SMTP id w22-20020a056358729600b0017017eb2039mr9338350rwf.34.1702423039955; Tue, 12 Dec 2023 15:17:19 -0800 (PST) Received: from localhost (34.133.83.34.bc.googleusercontent.com. [34.83.133.34]) by smtp.gmail.com with UTF8SMTPSA id z17-20020aa785d1000000b006ce5bb61a5fsm8749920pfn.3.2023.12.12.15.17.19 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 12 Dec 2023 15:17:19 -0800 (PST) From: jeffxu@chromium.org To: akpm@linux-foundation.org, keescook@chromium.org, jannh@google.com, sroettger@google.com, willy@infradead.org, gregkh@linuxfoundation.org, torvalds@linux-foundation.org Cc: jeffxu@google.com, jorgelo@chromium.org, groeck@chromium.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, pedro.falcato@gmail.com, dave.hansen@intel.com, linux-hardening@vger.kernel.org, deraadt@openbsd.org, Jeff Xu Subject: [RFC PATCH v3 09/11] mseal: add MAP_SEALABLE to mmap() Date: Tue, 12 Dec 2023 23:17:03 +0000 Message-ID: <20231212231706.2680890-10-jeffxu@chromium.org> X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog In-Reply-To: <20231212231706.2680890-1-jeffxu@chromium.org> References: <20231212231706.2680890-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: EDD3AC0002 X-Rspam-User: X-Rspamd-Server: rspam11 X-Stat-Signature: ig1bjmibfhuundwcsoa5apxtfmas5ehs X-HE-Tag: 1702423040-752073 X-HE-Meta: U2FsdGVkX18qhuIIvtpOM6qJntwCsKGhosVl5wP4Mc153q3pr6rwOLFIDP0t13oT8xysTkHU1pLhQ3e7Va2A87fygyspO1hy+JvMSh44eSA/nfRm1a/ppyssB6s6HokLRzGD1MySvFXu+8hBacgDneb8gKHiPbMLr2vv0PNFeXmqo8Q3V6BzI1WSNT0ddEMpFZWOkPrXqOggIzLc0GiP6TJocHDimI8he9L8n3UmzfGop1aADBIrCom6Z43Tq5/5kG39j0vTdoZf/R7Fkas9tiTs5oHZl9czPYm25TeN4LuKNMS1xkgot2udzSq97YGW6zBPqE18laRCACOTfzxK8Vzy9wxW2q1RiphLccxoKmvfF9RVbvvNhPQ4X61102gFLPzI3s+6ueBCbVnCCu9dl5YGR34zyh8TpUqfqiPqBJ/UoeZPK+4TcKSYAMbL+Ymfl3YLiSZ07fLWGoxkJluFKisT6wACkTgQ3npq83S3pN0CkZX/w/t8RE+K3TpNFBKMDdrxFtIC1TsA2AXJXsetxh0MiX0+H2QK7kYbmZDNw4RNhMUF+SE6NK8rnVvQOcbcMpDKfQydKfLPnGESqRvgYMQfrmVZu+xXeYtUX6zAsfa+TLnbWU3Ujub0UreErZp5mnYtRePjQhp2kAzPZ9LP+fcojFzlhi4ukjISxWNQjp1pZhMOHGz1AyLgyV3x5PMaiU+VXCjFD7lloMGBvihjtjlJTnXkI2VULynYC4quik+Cmo8vSSbiZK3Z0jVZONr9qzQmkZscHmfyM+edEYtQew1t0MD37KGlyTv7/YLJ0UAGUYNgAKEaS/UNlQJczH6uSJJ+xO0vg9kTzD5EZTcMB/HNK1aLNAiE0FnOr+ZHNJCaK2RGPgVanHofoPuwWcRTHyhZb1RlOKUF+H7dW2opZdsoCSEybeHBWGDoXLBjhixzd6xDhTamfcpDAmnrNLMyH6vCnhff0onrRMCIJvK BbLwCmR6 /PnOJfOjPQFvix9gYjPrj5Mz8Hl/BbYTf+qZn0rtU4+GZjGBW31Mqwv77YlJ84aZLSmo4z46brEs4M9S/9/UmSNHQ1EaxBV2qtLfQfhkuHm3o92GGz9eTNq2SdaIAFjnR5679t4ClUoExUHTE+ooKidwgwx621ceqt1Mul8FqCnLn5m7kedgU6psAUK/Y0epOyUthSWXMDDGVEeZ70lxGZPoPoFkBi7g6SS9cUCBNINhbb5rxpqXk0sGbi5c6BiYSqvqJPEigVMY5SzB/FdbONF533+X3v8LfBD1HMrDzA+t1+GbHYS1tHfnaz2ozpq/YnkEZSi87P+GmRpiwT87TVVbuLGkGg/M4OQv1A8VboIe8aP9f60amQwQ1EvbpaOiA2oIjplKOvUpqZEnByoPTTTWur755e9rU5WRkDK+f9G+yl7P4KV+PvtRBhvIPlSMTe9Eyv0SAbhpR/zj79hvOxXPZhDxUcAPD/ZQY 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: From: Jeff Xu The MAP_SEALABLE flag is added to the flags field of mmap(). When present, it marks the map as sealable. A map created without MAP_SEALABLE will not support sealing; In other words, mseal() will fail for such a map. Applications that don't care about sealing will expect their behavior unchanged. For those that need sealing support, opt-in by adding MAP_SEALABLE when creating the map. Signed-off-by: Jeff Xu --- include/linux/mm.h | 52 ++++++++++++++++++++++++-- include/linux/mm_types.h | 1 + include/uapi/asm-generic/mman-common.h | 1 + mm/mmap.c | 2 +- mm/mseal.c | 7 +++- 5 files changed, 57 insertions(+), 6 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 50dda474acc2..6f5dba9fbe21 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -267,6 +267,17 @@ extern unsigned int kobjsize(const void *objp); MM_SEAL_PROT_PKEY | \ MM_SEAL_DISCARD_RO_ANON) +/* define VM_SEALABLE in vm_seals of vm_area_struct. */ +#define VM_SEALABLE _BITUL(31) + +/* + * VM_SEALS_BITS_ALL marks the bits used for + * sealing in vm_seals of vm_area_structure. + */ +#define VM_SEALS_BITS_ALL ( \ + MM_SEAL_ALL | \ + VM_SEALABLE) + /* * PROT_SEAL_ALL is all supported flags in mmap(). * See include/uapi/asm-generic/mman-common.h. @@ -3330,9 +3341,17 @@ static inline void mm_populate(unsigned long addr, unsigned long len) {} #ifdef CONFIG_MSEAL /* - * return the valid sealing (after mask). + * return the valid sealing (after mask), this includes sealable bit. */ static inline unsigned long vma_seals(struct vm_area_struct *vma) +{ + return (vma->vm_seals & VM_SEALS_BITS_ALL); +} + +/* + * return the enabled sealing type (after mask), without sealable bit. + */ +static inline unsigned long vma_enabled_seals(struct vm_area_struct *vma) { return (vma->vm_seals & MM_SEAL_ALL); } @@ -3342,9 +3361,14 @@ static inline void update_vma_seals(struct vm_area_struct *vma, unsigned long vm vma->vm_seals |= vm_seals; } +static inline bool is_vma_sealable(struct vm_area_struct *vma) +{ + return vma->vm_seals & VM_SEALABLE; +} + static inline bool check_vma_seals_mergeable(unsigned long vm_seals1, unsigned long vm_seals2) { - if ((vm_seals1 & MM_SEAL_ALL) != (vm_seals2 & MM_SEAL_ALL)) + if ((vm_seals1 & VM_SEALS_BITS_ALL) != (vm_seals2 & VM_SEALS_BITS_ALL)) return false; return true; @@ -3384,9 +3408,15 @@ static inline unsigned long convert_mmap_seals(unsigned long prot) * check input sealing type from the "prot" field of mmap(). * for CONFIG_MSEAL case, this always return 0 (successful). */ -static inline int check_mmap_seals(unsigned long prot, unsigned long *vm_seals) +static inline int check_mmap_seals(unsigned long prot, unsigned long *vm_seals, + unsigned long flags) { *vm_seals = convert_mmap_seals(prot); + if (*vm_seals) + /* setting one of MM_SEAL_XX means the map is sealable. */ + *vm_seals |= VM_SEALABLE; + else + *vm_seals |= (flags & MAP_SEALABLE) ? VM_SEALABLE:0; return 0; } #else @@ -3395,6 +3425,16 @@ static inline unsigned long vma_seals(struct vm_area_struct *vma) return 0; } +static inline unsigned long vma_enabled_seals(struct vm_area_struct *vma) +{ + return 0; +} + +static inline bool is_vma_sealable(struct vm_area_struct *vma) +{ + return false; +} + static inline bool check_vma_seals_mergeable(unsigned long vm_seals1, unsigned long vm_seals2) { return true; @@ -3426,11 +3466,15 @@ static inline void update_vma_seals(struct vm_area_struct *vma, unsigned long vm * check input sealing type from the "prot" field of mmap(). * For not CONFIG_MSEAL, if SEAL flag is set, it will return failure. */ -static inline int check_mmap_seals(unsigned long prot, unsigned long *vm_seals) +static inline int check_mmap_seals(unsigned long prot, unsigned long *vm_seals, + unsigned long flags) { if (prot & PROT_SEAL_ALL) return -EINVAL; + if (flags & MAP_SEALABLE) + return -EINVAL; + return 0; } diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 052799173c86..c9b04c545f39 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -691,6 +691,7 @@ struct vm_area_struct { /* * bit masks for seal. * need this since vm_flags is full. + * We could merge this into vm_flags if vm_flags ever get expanded. */ unsigned long vm_seals; /* seal flags, see mm.h. */ #endif diff --git a/include/uapi/asm-generic/mman-common.h b/include/uapi/asm-generic/mman-common.h index bf503962409a..57ef4507c00b 100644 --- a/include/uapi/asm-generic/mman-common.h +++ b/include/uapi/asm-generic/mman-common.h @@ -47,6 +47,7 @@ #define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be * uninitialized */ +#define MAP_SEALABLE 0x8000000 /* map is sealable. */ /* * Flags for mlock diff --git a/mm/mmap.c b/mm/mmap.c index 6da8d83f2e66..6e35e2070060 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1235,7 +1235,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr, if (flags & MAP_FIXED_NOREPLACE) flags |= MAP_FIXED; - if (check_mmap_seals(prot, &vm_seals) < 0) + if (check_mmap_seals(prot, &vm_seals, flags) < 0) return -EINVAL; if (!(flags & MAP_FIXED)) diff --git a/mm/mseal.c b/mm/mseal.c index 294f48d33db6..5d4cf71b497e 100644 --- a/mm/mseal.c +++ b/mm/mseal.c @@ -121,9 +121,13 @@ bool can_modify_mm_madv(struct mm_struct *mm, unsigned long start, unsigned long */ static bool can_add_vma_seals(struct vm_area_struct *vma, unsigned long newSeals) { + /* if map is not sealable, reject. */ + if (!is_vma_sealable(vma)) + return false; + /* When SEAL_MSEAL is set, reject if a new type of seal is added. */ if ((vma->vm_seals & MM_SEAL_SEAL) && - (newSeals & ~(vma_seals(vma)))) + (newSeals & ~(vma_enabled_seals(vma)))) return false; /* @@ -185,6 +189,7 @@ static int mseal_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma, * 2> end is part of a valid vma. * 3> No gap (unallocated address) between start and end. * 4> requested seal type can be added in given address range. + * 5> map is sealable. */ static int check_mm_seal(unsigned long start, unsigned long end, unsigned long newtypes)