From patchwork Tue Oct 17 09:08:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13424810 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 B9959CDB482 for ; Tue, 17 Oct 2023 09:08:24 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 8B7F28D0103; Tue, 17 Oct 2023 05:08:23 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 867BA8D0101; Tue, 17 Oct 2023 05:08:23 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6E1A38D0103; Tue, 17 Oct 2023 05:08:23 -0400 (EDT) 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 5E20C8D0101 for ; Tue, 17 Oct 2023 05:08:23 -0400 (EDT) Received: from smtpin24.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 2D4D0A0F70 for ; Tue, 17 Oct 2023 09:08:23 +0000 (UTC) X-FDA: 81354377286.24.D94104A Received: from mail-pg1-f169.google.com (mail-pg1-f169.google.com [209.85.215.169]) by imf25.hostedemail.com (Postfix) with ESMTP id 32527A001B for ; Tue, 17 Oct 2023 09:08:21 +0000 (UTC) Authentication-Results: imf25.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=AOcV02lF; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf25.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.215.169 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1697533701; 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-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=ONFWwgK5lj2ZpjjMWHEuYRjeJZbiZQQ2L6zlDrNvyHE=; b=cDWlCwCipxmpltaFC0yLCyBvaKSiQPs5AuKg784okOyNiLts859eVFYGGxQ/hC1Vyowlqo YZABwFhnfSE0tp44zx71CBn3MXhMKZzExKignJLKLrLRJJ783YBsfdznPimDYvPdLXfusx nklwr3xeknYv//vl/UnBvfPhMuRqkDo= ARC-Authentication-Results: i=1; imf25.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=AOcV02lF; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf25.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.215.169 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1697533701; a=rsa-sha256; cv=none; b=MRo7ZZIzNDNuIx+O91oTrMaE8q0VIyOlJZo/yxHHVVlnmsf8IORVkHh61kHb9VOlqjvxYv t0tKUMo+JzC94V6Noc4KTyukFT5tkSC+fvKZJECYFkdsvkdrSdulvKA114bnpIm2B56GNa pHeqwi7NDPcsLMc2UW8Ej10b1dIenqU= Received: by mail-pg1-f169.google.com with SMTP id 41be03b00d2f7-5aaebfac4b0so2290189a12.2 for ; Tue, 17 Oct 2023 02:08:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1697533700; x=1698138500; 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=ONFWwgK5lj2ZpjjMWHEuYRjeJZbiZQQ2L6zlDrNvyHE=; b=AOcV02lFz5SulluyFoPhjOTu4UsGD0g+/9kr95pXS+egfUoVFb1YpWNDvdPZ5NCSfm 46vcN4wbZJsVU7GVRYxq4eonlHD4jQl3oj7MjPNfnc4aX1+sv8IeogOJDMV/5ZwFEKcc nvjnd1Mw9j4RYXwXK2H06HhJ7JwfdZAEB/CkE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697533700; x=1698138500; 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=ONFWwgK5lj2ZpjjMWHEuYRjeJZbiZQQ2L6zlDrNvyHE=; b=DLdFox5wmuxucYUxwf63W1mwHWp7v1GLnRhcPNnhkusXGJrLOIamvebkYozzjqCf+1 G4DChV7T4OI93nE0Y9rMcToUd16qrYpt7tMYId2jvl4DaKcsezH3pQfqLBG6YDYRHFbs hFasUnDTUtAO+xo2MfXFyvPlfoeFcqp9tTyCE+fLOKDrjyMKHFS0dcr4m10Tq4LpsNv5 7Qn53j+T7X3jlrVC32aOGTThc8RAG9OpqPudjyJtYnPcnYTJUHP8g//yFRj6VzLL8Z7u Q73HXc24ObLU4lm0sDjKEDhmCXuG7VL9ycuGEdNgYVS46/PsZ6C+7davi9BRMwmvpol/ K6ow== X-Gm-Message-State: AOJu0YxIp3ndYL8JC4zDZcGcDRzps1ajssFS3w7zXj4f2Hdb26UarigT kPtArkqiv3BQnyOAs7Lq5UhdXg== X-Google-Smtp-Source: AGHT+IFx84m8bigMOvX11yXy6GBlD52QqNEpmNFYE4AlviCUipj3jIvD/AeEXO283xhOeBSoscXP1g== X-Received: by 2002:a17:90b:1048:b0:27c:edd6:b08d with SMTP id gq8-20020a17090b104800b0027cedd6b08dmr1360755pjb.24.1697533699711; Tue, 17 Oct 2023 02:08:19 -0700 (PDT) Received: from localhost (9.184.168.34.bc.googleusercontent.com. [34.168.184.9]) by smtp.gmail.com with UTF8SMTPSA id gd22-20020a17090b0fd600b0026f90d7947csm868534pjb.34.2023.10.17.02.08.18 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 17 Oct 2023 02:08:19 -0700 (PDT) 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, surenb@google.com, alex.sierra@amd.com, apopple@nvidia.com, aneesh.kumar@linux.ibm.com, axelrasmussen@google.com, ben@decadent.org.uk, catalin.marinas@arm.com, david@redhat.com, dwmw@amazon.co.uk, ying.huang@intel.com, hughd@google.com, joey.gouly@arm.com, corbet@lwn.net, wangkefeng.wang@huawei.com, Liam.Howlett@oracle.com, lstoakes@gmail.com, mawupeng1@huawei.com, linmiaohe@huawei.com, namit@vmware.com, peterx@redhat.com, peterz@infradead.org, ryan.roberts@arm.com, shr@devkernel.io, vbabka@suse.cz, xiujianfeng@huawei.com, yu.ma@intel.com, zhangpeng362@huawei.com, dave.hansen@intel.com, luto@kernel.org, linux-hardening@vger.kernel.org Subject: [RFC PATCH v2 1/8] mseal: Add mseal(2) syscall. Date: Tue, 17 Oct 2023 09:08:08 +0000 Message-ID: <20231017090815.1067790-2-jeffxu@chromium.org> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog In-Reply-To: <20231017090815.1067790-1-jeffxu@chromium.org> References: <20231017090815.1067790-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 32527A001B X-Stat-Signature: xuxewhppngua1ar4ax3fzp8ceoou6xfq X-HE-Tag: 1697533701-115163 X-HE-Meta: U2FsdGVkX1/2hyj3AxWrn+Nds68MTjgubbTUeP6N72wKzvwXMqqu78UzxVzwguIjgcg9QR/UU8S7knIerHNDYBs/FJYOwphyDpMrLEvsmfazXGlp3TZimazZOi/rGpUQl4GPtZ9/EAifm0h0wLKp+ct8XYc3GDSjfNQIpGaJxSN4AiFJQq9KmxKST4k7pSoO+ZClw2QXwT9BIADUAgWeMpq/84JvfPV2UZkPsMJAkjhr4OHtXTdGA5ZE5Y0cSA2JGm0cw9bh7rU1Z2cJVQAQ5rxCcv2MnG/CghzdyjAB9FNrKm7lz9uzk3480sothVg8Vw943VuX8bvfyOKuoFAmEewG02+IK7gAYOje12jzJ74HL4QO59JdfEiJ6TBgMArgZWvIFn+iCJAByS0++QRRGNSPqxbWsMwta0X7ip97PxumSbHK6NWsQewp3L2XNtMJLwEGa9l0qZ8LazgAomG6p4gjs4JYS+t6aQMLV2fliyeOv56ZZ9OnMOEoNZaNw4JscWVxGFNP5WtHTR0MLmLpXuKKXjo7m0UlM+z+y89bcHZn9YSc3u8lXoJ5W2Ea7yufVHXHUGGiYVTZKeXslMhWo4ws8tfKv6tDmAV/1JwOW69QKf/F9Mlj2pRomJxxENqn5a8tRjrbIOU5+hc12knkhjQPsWe7XAguxDgcuUCzAdPIxsFvxzH3YuoP5/Rirsl4yTDx+pBgNsfIgFCOELmSO9+HeOFvyhF4N3V201iJz5gGmNl/+ggrnjBcz29C845UJ+NBdSUfp+ExLbG2z1mES7mMTv6n+Wn/voc4oSTQkVbia8Bgxq0w2DvhsV+cL8T1Skomc2CA6peek8E9odejByHR3eONMQ0VRna+tUbaSk23D6gctQK6g8kPmndvrrT7j81/C4HLC5p6N9RU80eCjnWTVXHgQAquSqQedgU66JywM0fdL2AADHyob6TkcnShkR1ryiMeVUV5dLzyrRn 33SYOaqM 3jiRrfPSYW1ZiGjEWfHPfe90sLvEK3eAYILTWxMsSSSU5NHmqvOYzqhvGaijju0GYI8UZSKGgXcGi+l+Ph/eAWJIG+9yBdnOEY582SE7oZEzi/mqqEw5jy1QcQ6QL9a+vvTRk8vyymUiJDBHRZijqHiaOmIs4rjredtV/4MV7AoHZ1t9OvxhnC2nBEpyMGx/RhT7dHPigd3T4aPRpCuAsvzT8hlQXADYrs6BCzjb9LCyZLZSrzlrhOqreDjhF4wuBOnEXvzFoHuDEul56AFZAJSAI6SHV5VkmlC7P9j30kmqHjuwGwKvMHD/ZQDsmiBTxsf4b8wYECCV3B0AIL1rbxj2kno3cgHZSNr3BGEPNczXZVGt1IsAmL+Ue1/ccS2SSjRZSn773B1jv//bGChD+adETbngXV8W9lJ3LsTWvPJLKOKWTPUh3t6OZvTNyDJddIH6Twcd8Dba1QVOU5iKojfIZ580QM/wpFLpL2KU37F6ep4vV188bO2MFreoT54i6mMfxWc30Znkzy2z/L5vtSmkQyG1XoiYYhDcgBcKraGc9vo2IGmn552tfrQ== 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 patchset proposes a new mseal() syscall for the Linux kernel. Modern CPUs support memory permissions such as RW and NX bits. Linux has supported NX since the release of kernel version 2.6.8 in August 2004 [1]. The memory permission feature improves security stance on memory corruption bugs, i.e. the attacker can’t just write to arbitrary memory and point the code to it, the memory has to be marked with X bit, or else an exception will happen. Memory sealing additionally protects the mapping itself against modifications. This is useful to mitigate memory corruption issues where a corrupted pointer is passed to a memory management syscall. For example, such an attacker primitive can break control-flow integrity guarantees since read-only memory that is supposed to be trusted can become writable or .text pages can get remapped. Memory sealing can automatically be applied by the runtime loader to seal .text and .rodata pages and applications can additionally seal security critical data at runtime. A similar feature already exists in the XNU kernel with the VM_FLAGS_PERMANENT [3] flag and on OpenBSD with the mimmutable syscall [4]. Also, Chrome wants to adopt this feature for their CFI work [2] and this patchset has been designed to be compatible with the Chrome use case. The new mseal() is an architecture independent syscall, and with following signature: mseal(void addr, size_t len, unsigned long types, unsigned long flags) addr/len: memory range. Must be continuous/allocated memory, or else mseal() will fail and no VMA is updated. For details on acceptable arguments, please refer to comments in mseal.c. Those are also fully covered by the selftest. types: bit mask to specify which syscall to seal. Five syscalls can be sealed, as specified by bitmasks: MM_SEAL_MPROTECT: Deny mprotect(2)/pkey_mprotect(2). MM_SEAL_MUNMAP: Deny munmap(2). MM_SEAL_MMAP: Deny mmap(2). MM_SEAL_MREMAP: Deny mremap(2). MM_SEAL_MSEAL: Deny adding a new seal type. Each bit represents sealing for one specific syscall type, e.g. MM_SEAL_MPROTECT will deny mprotect syscall. The consideration of bitmask is that the API is extendable, i.e. when needed, the sealing can be extended to madvise, mlock, etc. Backward compatibility is also easy. The kernel will remember which seal types are applied, and the application doesn’t need to repeat all existing seal types in the next mseal(). Once a seal type is applied, it can’t be unsealed. Call mseal() on an existing seal type is a no-action, not a failure. MM_SEAL_MSEAL will deny mseal() calls that try to add a new seal type. Internally, vm_area_struct adds a new field vm_seals, to store the bit masks. For the affected syscalls, such as mprotect, a check(can_modify_mm) for sealing is added, this usually happens at the early point of the syscall, before any update is made to VMAs. The effect of that is: if any of the VMAs in the given address range fails the sealing check, none of the VMA will be updated. The idea that inspired this patch comes from Stephen Röttger’s work in V8 CFI [5], Chrome browser in ChromeOS will be the first user of this API. In addition, Stephen is working on glibc change to add sealing support into the dynamic linker to seal all non-writable segments at startup. When that work is completed, all applications can automatically benefit from these new protections. [1] https://kernelnewbies.org/Linux_2_6_8 [2] https://v8.dev/blog/control-flow-integrity [3] https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/osfmk/mach/vm_statistics.h#L274 [4] https://man.openbsd.org/mimmutable.2 [5] https://docs.google.com/document/d/1O2jwK4dxI3nRcOJuPYkonhTkNQfbmwdvxQMyXgeaRHo/edit#heading=h.bvaojj9fu6hc Signed-off-by: Jeff Xu --- include/linux/mm.h | 11 ++ include/linux/mm_types.h | 7 ++ include/linux/syscalls.h | 2 + include/uapi/linux/mman.h | 6 + kernel/sys_ni.c | 1 + mm/Kconfig | 8 ++ mm/Makefile | 1 + mm/mmap.c | 14 +++ mm/mseal.c | 230 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 280 insertions(+) create mode 100644 mm/mseal.c diff --git a/include/linux/mm.h b/include/linux/mm.h index 53efddc4d178..b511932df033 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -30,6 +30,7 @@ #include #include #include +#include struct mempolicy; struct anon_vma; @@ -257,6 +258,16 @@ extern struct rw_semaphore nommu_region_sem; extern unsigned int kobjsize(const void *objp); #endif +/* + * MM_SEAL_ALL is all supported flags in mseal(). + */ +#define MM_SEAL_ALL ( \ + MM_SEAL_MSEAL | \ + MM_SEAL_MPROTECT | \ + MM_SEAL_MUNMAP | \ + MM_SEAL_MMAP | \ + MM_SEAL_MREMAP) + /* * vm_flags in vm_area_struct, see mm_types.h. * When changing, update also include/trace/events/mmflags.h diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 36c5b43999e6..17d80f5a73dc 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -660,6 +660,13 @@ struct vm_area_struct { struct vma_numab_state *numab_state; /* NUMA Balancing state */ #endif struct vm_userfaultfd_ctx vm_userfaultfd_ctx; +#ifdef CONFIG_MSEAL + /* + * bit masks for seal. + * need this since vm_flags is full. + */ + unsigned long vm_seals; /* seal flags, see mm.h. */ +#endif } __randomize_layout; #ifdef CONFIG_SCHED_MM_CID diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index c0cb22cd607d..dbc8d4f76646 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -802,6 +802,8 @@ asmlinkage long sys_process_mrelease(int pidfd, unsigned int flags); asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags); +asmlinkage long sys_mseal(unsigned long start, size_t len, unsigned long types, + unsigned long flags); asmlinkage long sys_mbind(unsigned long start, unsigned long len, unsigned long mode, const unsigned long __user *nmask, diff --git a/include/uapi/linux/mman.h b/include/uapi/linux/mman.h index a246e11988d5..5ed4072cf4a6 100644 --- a/include/uapi/linux/mman.h +++ b/include/uapi/linux/mman.h @@ -55,4 +55,10 @@ struct cachestat { __u64 nr_recently_evicted; }; +#define MM_SEAL_MSEAL _BITUL(0) +#define MM_SEAL_MPROTECT _BITUL(1) +#define MM_SEAL_MUNMAP _BITUL(2) +#define MM_SEAL_MMAP _BITUL(3) +#define MM_SEAL_MREMAP _BITUL(4) + #endif /* _UAPI_LINUX_MMAN_H */ diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 781de7cc6a4e..06fabf379e33 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -192,6 +192,7 @@ COND_SYSCALL(migrate_pages); COND_SYSCALL(move_pages); COND_SYSCALL(set_mempolicy_home_node); COND_SYSCALL(cachestat); +COND_SYSCALL(mseal); COND_SYSCALL(perf_event_open); COND_SYSCALL(accept4); diff --git a/mm/Kconfig b/mm/Kconfig index 264a2df5ecf5..db8a567cb4d3 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -1258,6 +1258,14 @@ config LOCK_MM_AND_FIND_VMA bool depends on !STACK_GROWSUP +config MSEAL + default n + bool "Enable mseal() system call" + depends on MMU + help + Enable the mseal() system call. Make memory areas's metadata immutable + by selected system calls, i.e. mprotect(), munmap(), mremap(), mmap(). + source "mm/damon/Kconfig" endmenu diff --git a/mm/Makefile b/mm/Makefile index ec65984e2ade..643d8518dac0 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -120,6 +120,7 @@ obj-$(CONFIG_PAGE_EXTENSION) += page_ext.o obj-$(CONFIG_PAGE_TABLE_CHECK) += page_table_check.o obj-$(CONFIG_CMA_DEBUGFS) += cma_debug.o obj-$(CONFIG_SECRETMEM) += secretmem.o +obj-$(CONFIG_MSEAL) += mseal.o obj-$(CONFIG_CMA_SYSFS) += cma_sysfs.o obj-$(CONFIG_USERFAULTFD) += userfaultfd.o obj-$(CONFIG_IDLE_PAGE_TRACKING) += page_idle.o diff --git a/mm/mmap.c b/mm/mmap.c index 514ced13c65c..414ac31aa9fa 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -730,6 +730,20 @@ static inline bool is_mergeable_vma(struct vm_area_struct *vma, return false; if (!anon_vma_name_eq(anon_vma_name(vma), anon_name)) return false; +#ifdef CONFIG_MSEAL + /* + * If a VMA is sealed, it won't be merged with another VMA. + * This might be useful for diagnosis, i.e. the boundary used + * in the mseal() call will be preserved. + * There are chances of too many mseal() calls can create + * many segmentations. Considering mseal() usually comes + * with a careful memory layout design by the application, + * this might not be an issue in real world. + * Though, we could add merging support later if needed. + */ + if (vma->vm_seals & MM_SEAL_ALL) + return 0; +#endif return true; } diff --git a/mm/mseal.c b/mm/mseal.c new file mode 100644 index 000000000000..ffe4c4c3f1bc --- /dev/null +++ b/mm/mseal.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Implement mseal() syscall. + * + * Copyright (c) 2023 Google, Inc. + * + * Author: Jeff Xu + */ + +#include +#include +#include +#include +#include "internal.h" + +static bool can_do_mseal(unsigned long types, unsigned long flags) +{ + /* check types is a valid bitmap */ + if (types & ~MM_SEAL_ALL) + return false; + + /* flags isn't used for now */ + if (flags) + return false; + + return true; +} + +/* + * Check if a seal type can be added to VMA. + */ +static bool can_add_vma_seals(struct vm_area_struct *vma, unsigned long newSeals) +{ + /* When SEAL_MSEAL is set, reject if a new type of seal is added */ + if ((vma->vm_seals & MM_SEAL_MSEAL) && + (newSeals & ~(vma->vm_seals & MM_SEAL_ALL))) + return false; + + return true; +} + +static int mseal_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma, + struct vm_area_struct **prev, unsigned long start, + unsigned long end, unsigned long addtypes) +{ + int ret = 0; + + if (addtypes & ~(vma->vm_seals & MM_SEAL_ALL)) { + /* + * Handle split at start and end. + * Note: sealed VMA doesn't merge with other VMAs. + */ + if (start != vma->vm_start) { + ret = split_vma(vmi, vma, start, 1); + if (ret) + goto out; + } + + if (end != vma->vm_end) { + ret = split_vma(vmi, vma, end, 0); + if (ret) + goto out; + } + + vma->vm_seals |= addtypes; + } + +out: + *prev = vma; + return ret; +} + +/* + * Check for do_mseal: + * 1> start is part of a valid 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. + */ +static int check_mm_seal(unsigned long start, unsigned long end, + unsigned long newtypes) +{ + struct vm_area_struct *vma; + unsigned long nstart = start; + + VMA_ITERATOR(vmi, current->mm, start); + + /* going through each vma to check */ + for_each_vma_range(vmi, vma, end) { + if (vma->vm_start > nstart) + /* unallocated memory found */ + return -ENOMEM; + + if (!can_add_vma_seals(vma, newtypes)) + return -EACCES; + + if (vma->vm_end >= end) + return 0; + + nstart = vma->vm_end; + } + + return -ENOMEM; +} + +/* + * Apply sealing. + */ +static int apply_mm_seal(unsigned long start, unsigned long end, + unsigned long newtypes) +{ + unsigned long nstart, nend; + struct vm_area_struct *vma, *prev = NULL; + struct vma_iterator vmi; + int error = 0; + + vma_iter_init(&vmi, current->mm, start); + vma = vma_find(&vmi, end); + + prev = vma_prev(&vmi); + if (start > vma->vm_start) + prev = vma; + + nstart = start; + + /* going through each vma to update */ + for_each_vma_range(vmi, vma, end) { + nend = vma->vm_end; + if (nend > end) + nend = end; + + error = mseal_fixup(&vmi, vma, &prev, nstart, nend, newtypes); + if (error) + break; + + nstart = vma->vm_end; + } + + return error; +} + +/* + * mseal(2) seals the VM's meta data from + * selected syscalls. + * + * addr/len: VM address range. + * + * The address range by addr/len must meet: + * start (addr) must be in a valid VMA. + * end (addr + len) must be in a valid VMA. + * no gap (unallocated memory) between start and end. + * start (addr) must be page aligned. + * + * len: len will be page aligned implicitly. + * + * types: bit mask for sealed syscalls. + * MM_SEAL_MPROTECT: seal mprotect(2)/pkey_mprotect(2). + * MM_SEAL_MUNMAP: seal munmap(2). + * MM_SEAL_MMAP: seal mmap(2). + * MM_SEAL_MREMAP: seal mremap(2). + * MM_SEAL_MSEAL: adding new seal type will be rejected. + * + * flags: reserved. + * + * return values: + * zero: success + * -EINVAL: + * invalid seal type. + * invalid input flags. + * addr is not page aligned. + * addr + len overflow. + * -ENOMEM: + * addr is not a valid address (not allocated). + * end (addr + len) is not a valid address. + * a gap (unallocated memory) between start and end. + * -EACCES: + * MM_SEAL_MSEAL is set, adding a new seal is rejected. + * + * Note: + * user can call mseal(2) multiple times to add new seal types. + * adding an already added seal type is a no-action (no error). + * adding a new seal type after MM_SEAL_MSEAL will be rejected. + * unseal() or removing a seal type is not supported. + */ +static int do_mseal(unsigned long start, size_t len_in, unsigned long types, + unsigned long flags) +{ + int ret = 0; + unsigned long end; + struct mm_struct *mm = current->mm; + size_t len; + + if (!can_do_mseal(types, flags)) + return -EINVAL; + + start = untagged_addr(start); + if (!PAGE_ALIGNED(start)) + return -EINVAL; + + len = PAGE_ALIGN(len_in); + /* Check to see whether len was rounded up from small -ve to zero */ + if (len_in && !len) + return -EINVAL; + + end = start + len; + if (end < start) + return -EINVAL; + + if (end == start) + return 0; + + if (mmap_write_lock_killable(mm)) + return -EINTR; + + ret = check_mm_seal(start, end, types); + if (ret) + goto out; + + ret = apply_mm_seal(start, end, types); + +out: + mmap_write_unlock(current->mm); + return ret; +} + +SYSCALL_DEFINE4(mseal, unsigned long, start, size_t, len, unsigned long, types, unsigned long, + flags) +{ + return do_mseal(start, len, types, flags); +} From patchwork Tue Oct 17 09:08:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13424831 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 2A27DCDB482 for ; Tue, 17 Oct 2023 09:13:44 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id B54F880035; Tue, 17 Oct 2023 05:13:43 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id AE6B08D0108; Tue, 17 Oct 2023 05:13:43 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 9584480035; Tue, 17 Oct 2023 05:13:43 -0400 (EDT) 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 819A08D0108 for ; Tue, 17 Oct 2023 05:13:43 -0400 (EDT) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 489D6B6387 for ; Tue, 17 Oct 2023 09:13:43 +0000 (UTC) X-FDA: 81354390726.08.6C972E5 Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) by imf22.hostedemail.com (Postfix) with ESMTP id 6635BC0018 for ; Tue, 17 Oct 2023 09:13:41 +0000 (UTC) Authentication-Results: imf22.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=SMOnGUV2; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf22.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.210.173 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1697534021; 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=f2cnGwgONMuFiKzqdro4bTWTESfW7gQ3dGqDUQlrl20=; b=4ZpFA3pplPSC3dq0i2HdGRVrhR9ayceR5cqDx6dDRBzcUitoz2yH1qyeS8cGLTh0CuHOiM 6zBNITkFPCPnSzfJCb/5lQltL/zlB+Zfa73jhra+pnwdqchchYBInhI2S7ak3NOAS/b7xr ajK/FzToM3x11U4DtQOVIutcDDv7a48= ARC-Authentication-Results: i=1; imf22.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=SMOnGUV2; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf22.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.210.173 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1697534021; a=rsa-sha256; cv=none; b=36mH2BU+qhNHdMbZfC8Ix4HlFMDc3ppsNQ7B00JnvWQcUG+VbqhAychAbidf9GmqyyN80r +/dCryRHY/7Elk/7uln+kjrPotLVDYfhHZKWkzSERp1+eaQW6D1WfX3ms9bklGg4M0xHJC gNQATkCG9DkX1Fjdx3f9YdtMo+dVjhQ= Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-692c02adeefso3904023b3a.3 for ; Tue, 17 Oct 2023 02:13:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1697534020; x=1698138820; 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=f2cnGwgONMuFiKzqdro4bTWTESfW7gQ3dGqDUQlrl20=; b=SMOnGUV2Z2u6lh6cOaqzcB8IHrG6Pn5vYvrj6fteEjr/sp0GvYUgxpp+4KqTam6s6/ L01X22mqTbSO0L8Pv/F4RGH7dyyvnKypg1r1i9fgiN69sAZV817lDGgESTZ22DQTkaZV jAwnBadshr0+slliw4G8qZVDFcKbiLQKh8Xp0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697534020; x=1698138820; 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=f2cnGwgONMuFiKzqdro4bTWTESfW7gQ3dGqDUQlrl20=; b=dM9YuUoK/DNXoGBHRF4Iw6+GeAGwrbqDjTBJnTgtMDYzCc28FKqK7bJWagBZ6wRxXD eaqPPYkCp2XRIjZz8IMQMCqak30PiV8wfEAEHiLYNM+HcQDbuKJZV/ZgtuLks97hCHIa KNqO7b71quXLW54pGmKrhQZPCO4xtJFd/YFJ17qOrahBONFyDlZ1+qS+idJsMPnKpCLP zGyRknRY6j58k4E9Xe7SuvCS/o2O+/mbXtW6B91NXLMQbCaf+xXkiFmEyRlHcS/nKIp2 8jtN1eIPBxs9PToRqEu77jyOAjmP+7obdopnDeSkhSXVpBFyMXSAyYahct4PCgHSHTwH BT8Q== X-Gm-Message-State: AOJu0YyQMOVXc13vbM+kWRptWtmAo7OWXl70B00gMatzs4furORV2iYX JXN/yUOdA2kEuWQ84G/6F7vqYyNy1o5qrk1zmU4= X-Google-Smtp-Source: AGHT+IEK7RHTFUSPPkQL/tU2WyLa+OefKeSmCxcxvRxKg8e3OQYg6zBnYCJxPZc//BnDg+09Qpik4w== X-Received: by 2002:a0d:d703:0:b0:592:9235:4bcc with SMTP id z3-20020a0dd703000000b0059292354bccmr1734255ywd.50.1697533700754; Tue, 17 Oct 2023 02:08:20 -0700 (PDT) Received: from localhost (9.184.168.34.bc.googleusercontent.com. [34.168.184.9]) by smtp.gmail.com with UTF8SMTPSA id i9-20020a63e449000000b0057c29fec795sm951964pgk.37.2023.10.17.02.08.20 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 17 Oct 2023 02:08:20 -0700 (PDT) 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, surenb@google.com, alex.sierra@amd.com, apopple@nvidia.com, aneesh.kumar@linux.ibm.com, axelrasmussen@google.com, ben@decadent.org.uk, catalin.marinas@arm.com, david@redhat.com, dwmw@amazon.co.uk, ying.huang@intel.com, hughd@google.com, joey.gouly@arm.com, corbet@lwn.net, wangkefeng.wang@huawei.com, Liam.Howlett@oracle.com, lstoakes@gmail.com, mawupeng1@huawei.com, linmiaohe@huawei.com, namit@vmware.com, peterx@redhat.com, peterz@infradead.org, ryan.roberts@arm.com, shr@devkernel.io, vbabka@suse.cz, xiujianfeng@huawei.com, yu.ma@intel.com, zhangpeng362@huawei.com, dave.hansen@intel.com, luto@kernel.org, linux-hardening@vger.kernel.org Subject: [RFC PATCH v2 2/8] mseal: Wire up mseal syscall Date: Tue, 17 Oct 2023 09:08:09 +0000 Message-ID: <20231017090815.1067790-3-jeffxu@chromium.org> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog In-Reply-To: <20231017090815.1067790-1-jeffxu@chromium.org> References: <20231017090815.1067790-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspam-User: X-Stat-Signature: gk9f8n73deaync5gd499afwsruunc37g X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: 6635BC0018 X-HE-Tag: 1697534021-553030 X-HE-Meta: U2FsdGVkX182216bGPAUeuf8N3/zvbFC8e1u89pbMrcuTpG5aaVE/jJIQjKgzILt3Qq512fiBw9ygeUZyqRjzF0/7jjAcBiAicNMFJOL0d/OVWpC4jyDOXNM74ay0Owf4XNCW0ehJ+cHSo4qpUHco/h3U1hPWO+eyVzgNNa2nddxYBmYZfpuQdfHUTlK6sEuHl7klDuW+vkSSy0q5qFJsqtt++ZCSSShGH+60WlYkInsD9W/jqM3IiKaQGK+95RmxnftOGCYi6DYOKlj23ImMlf+dMRBo7E1DJXe3rAQUXkOr7lngB9heVvHzn0zQl9M5Hahryiq2LsxAoiisBXajnA8Z8yfedbdPiLu7wv20P/NJ8K4pwKzrCTDwP9678ttDOLzi3MCyxi3P1/4AkVGdXpu1mTNa1qaWWBaFpPe61WNnhrAKceX6iPHtV7cWtIhNEw3T9fMrBQ6xO0wqHrK6FjVCFFKwvOs69m3m5OU+ugpZ1tvtr+2rVWsfExV1d2D4iQfsHWGvyUG1rZKK9QLrzxYUqazMHH5VPFENA1ats1h5mLWd1eDKrM5a+eZYt8jAaCe8pRDplY6K46q6y8zyoZI3X2PDn7QKIvVY3mdkl6Ti0Ejk+X2RQi4wz+oM78ACmahiYUxv7PbunvoL2KMxn3UlrU/sONlkleRxczzUlbvT6k3w12omozmSDtq13zYA43b0RvUo0o9L7VwOnTl/qHWa8iUWsUOONmv5T8NpsCWA6+S5fYCQRBkkCcpqmJtzd1Z8vfSitdwPL3uwAOPZj45jiHO63m8aX1sLezb8EkDd3q/WjZF7qaL5mykcZ6VjuqIMleSfV6bPo86mnTNKUZj8w4NiWYCqgNQ8qwmPupZJ16Mty6clHpVIXYzPK7uG8xc6MYLUof9lP4Yc/ny8fRfdAQQ+y0kKIAP+ZWGr/QP93iNtD0W/QI3LtQ9+07FnkXj+TGO5XchQMUK+cv fV4dDj32 eb0pJCRoGF8R1e3dKsZpEbwjGfG4sjpNsyiGwMWlTDseN8rbSI+uBNbSU6jAasFukTl4FOuax8UH4NA0P3tS0PrZs8Zfblt/eUTkGqEgowbXQUyPg6BGkp0SL+DXpWUMWBUmgmv5LwGvKl1Pg5m0iRsjxek8V5LCGtV1PxvmeBEqKi2nqlxHxILQmdLyHQc4rbudT//mD3GngNIROHXhrjhtd38IJYXUm6HgEsd+NxKQUJ1Dji/gh33AxIJdPXUw2HGYAu/HVxQ+mPsjBPsO02YqjErIxps+uxYDZZK8Bq7U1V2uw0JhK+hD6va1Iw6xYlzGDz3H0rsDWaww= 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 Wire up mseal syscall for all architectures. Signed-off-by: Jeff Xu --- arch/alpha/kernel/syscalls/syscall.tbl | 1 + arch/arm/tools/syscall.tbl | 1 + arch/arm64/include/asm/unistd.h | 2 +- arch/arm64/include/asm/unistd32.h | 2 ++ arch/ia64/kernel/syscalls/syscall.tbl | 1 + arch/m68k/kernel/syscalls/syscall.tbl | 1 + arch/microblaze/kernel/syscalls/syscall.tbl | 1 + arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + arch/mips/kernel/syscalls/syscall_n64.tbl | 1 + arch/mips/kernel/syscalls/syscall_o32.tbl | 1 + arch/parisc/kernel/syscalls/syscall.tbl | 1 + arch/powerpc/kernel/syscalls/syscall.tbl | 1 + arch/s390/kernel/syscalls/syscall.tbl | 1 + arch/sh/kernel/syscalls/syscall.tbl | 1 + arch/sparc/kernel/syscalls/syscall.tbl | 1 + arch/x86/entry/syscalls/syscall_32.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + arch/xtensa/kernel/syscalls/syscall.tbl | 1 + include/uapi/asm-generic/unistd.h | 5 ++++- 19 files changed, 23 insertions(+), 2 deletions(-) diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl index ad37569d0507..b5847d53102a 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -492,3 +492,4 @@ 560 common set_mempolicy_home_node sys_ni_syscall 561 common cachestat sys_cachestat 562 common fchmodat2 sys_fchmodat2 +563 common mseal sys_mseal diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index c572d6c3dee0..b50c5ca5047d 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -466,3 +466,4 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index bd77253b62e0..6a28fb91b85d 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -39,7 +39,7 @@ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5) #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800) -#define __NR_compat_syscalls 453 +#define __NR_compat_syscalls 454 #endif #define __ARCH_WANT_SYS_CLONE diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 78b68311ec81..1e9b3c098a8e 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -911,6 +911,8 @@ __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) __SYSCALL(__NR_cachestat, sys_cachestat) #define __NR_fchmodat2 452 __SYSCALL(__NR_fchmodat2, sys_fchmodat2) +#define __NR_mseal 453 +__SYSCALL(__NR_mseal, sys_mseal) /* * Please add new compat syscalls above this comment and update diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl index 83d8609aec03..babe34d221ee 100644 --- a/arch/ia64/kernel/syscalls/syscall.tbl +++ b/arch/ia64/kernel/syscalls/syscall.tbl @@ -373,3 +373,4 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl index 259ceb125367..27cd3f7dbd5e 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -452,3 +452,4 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl index a3798c2637fd..e49861f7c61f 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -458,3 +458,4 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index 152034b8e0a0..78d15010cd77 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -391,3 +391,4 @@ 450 n32 set_mempolicy_home_node sys_set_mempolicy_home_node 451 n32 cachestat sys_cachestat 452 n32 fchmodat2 sys_fchmodat2 +453 n32 mseal sys_mseal diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl index cb5e757f6621..813614fedb72 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -367,3 +367,4 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 n64 cachestat sys_cachestat 452 n64 fchmodat2 sys_fchmodat2 +453 n64 mseal sys_mseal diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl index 1a646813afdc..01d88d3a6f3e 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -440,3 +440,4 @@ 450 o32 set_mempolicy_home_node sys_set_mempolicy_home_node 451 o32 cachestat sys_cachestat 452 o32 fchmodat2 sys_fchmodat2 +453 o32 mseal sys_mseal diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index e97c175b56f9..d52d08f0a1ea 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -451,3 +451,4 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index 20e50586e8a2..d38deba73a7b 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -539,3 +539,4 @@ 450 nospu set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl index 0122cc156952..cf3243c2978b 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -455,3 +455,4 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal sys_mseal diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl index e90d585c4d3e..76f1cd33adaa 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -455,3 +455,4 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl index 4ed06c71c43f..d7728695d780 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -498,3 +498,4 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 2d0b1bd866ea..6d4cc386df22 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -457,3 +457,4 @@ 450 i386 set_mempolicy_home_node sys_set_mempolicy_home_node 451 i386 cachestat sys_cachestat 452 i386 fchmodat2 sys_fchmodat2 +453 i386 mseal sys_mseal diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 814768249eae..73dcfc43d921 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -374,6 +374,7 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal # # Due to a historical design error, certain syscalls are numbered differently diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl index fc1a4f3c81d9..e8fd3bf35d73 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -423,3 +423,4 @@ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 +453 common mseal sys_mseal diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index abe087c53b4b..0c945a798208 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -823,8 +823,11 @@ __SYSCALL(__NR_cachestat, sys_cachestat) #define __NR_fchmodat2 452 __SYSCALL(__NR_fchmodat2, sys_fchmodat2) +#define __NR_mseal 453 +__SYSCALL(__NR_mseal, sys_mseal) + #undef __NR_syscalls -#define __NR_syscalls 453 +#define __NR_syscalls 454 /* * 32 bit systems traditionally used different From patchwork Tue Oct 17 09:08:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13424812 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 503C3CDB486 for ; Tue, 17 Oct 2023 09:08:27 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 29EE58D0104; Tue, 17 Oct 2023 05:08:25 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 228518D0101; Tue, 17 Oct 2023 05:08:25 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 02C798D0104; Tue, 17 Oct 2023 05:08:24 -0400 (EDT) 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 D350C8D0101 for ; Tue, 17 Oct 2023 05:08:24 -0400 (EDT) Received: from smtpin13.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 879C2120F73 for ; Tue, 17 Oct 2023 09:08:24 +0000 (UTC) X-FDA: 81354377328.13.4DDBE0B Received: from mail-oa1-f41.google.com (mail-oa1-f41.google.com [209.85.160.41]) by imf08.hostedemail.com (Postfix) with ESMTP id B7D7F160021 for ; Tue, 17 Oct 2023 09:08:22 +0000 (UTC) Authentication-Results: imf08.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=K4Z8HbaH; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf08.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.160.41 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1697533702; 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=pUe9FJYX6yjMwKk8iWQD0cd7P0ayg/xoiIZR+/sHFb4=; b=fUA8I3nth/K6iONpgdO2LellJMQtpPBfNE7zPA6yUeTrahV33GDplYMFb4vjj9nmn4SvIE 4RmuU3iUVpKKLbwvitamny5kPgE5mb5ZpGHkknVNLVZC9AsRDcV2gdfgbKwhAbGrGyiBbU m03/pAkoF6ufAgQYGW5ym9gkMewupmw= ARC-Authentication-Results: i=1; imf08.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=K4Z8HbaH; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf08.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.160.41 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1697533702; a=rsa-sha256; cv=none; b=XG9LcJDW+embTeyR7/NbMc7jToITxP28TSF0VMCi1tdJs+EfTvdKlqyH1jYcSrIL4Dw1Kq rngxRlu13aKoh1wjHpTt4lVc+C92QqGdbu4IgqaFN9qlm+Kk5Da8/WKbIgtmbfAHZILr7I QzFqauLhJ16sldHw8edzEWuATpqrhlk= Received: by mail-oa1-f41.google.com with SMTP id 586e51a60fabf-1e9fbb7d88eso2474285fac.3 for ; Tue, 17 Oct 2023 02:08:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1697533702; x=1698138502; 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=pUe9FJYX6yjMwKk8iWQD0cd7P0ayg/xoiIZR+/sHFb4=; b=K4Z8HbaHGKWiOsvE+w/5C5Tx7HA7oM3tq36c5JROSAK9Vdj05p47t48K+zYuAoJmu2 atiLt8ssZLjBumiquCUovqx7IAWEg7gijMtB73CIZfsFmYma5Cb3TPvfiywEoEUyyWtH 0qZ1bkLRqnkw4P+qa0+Vjlu5xwMuDG6ZescWA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697533702; x=1698138502; 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=pUe9FJYX6yjMwKk8iWQD0cd7P0ayg/xoiIZR+/sHFb4=; b=KZB+gex2PV71TyOHqbetYVoyAkosOyhZjQxP6XtKPqSHJJ3hcrgNw88BPXh2k+0zrm OjrngYdE2xGxyG5pzc5Ss7SDQwUhC6JaZy06howDkMclL9V6WOHBbm1lR7OVTNaaHpbW 3DKjYbuN8XPvdt3mnHtClasrpl2eDfykkML80CHQ3T22dzY32OvQiEqeblcw4depwB6z BpYsb7avwpbSTfhgcAYnOvw7HAKerQU7c/pCrF137NNlsF2yMK0LB/AzPlg6b4nroZIp MjBFYI6EU/96RK9Q3xQcRw8lxExOsGbINjWvB+FGzGiFzSEVP+Y0GWnljQ3uPWgBrBFi S8AQ== X-Gm-Message-State: AOJu0YwVEO2lTFjv/pTlrYVbT9UHgSuULKaMG/8flObohC7XMVRm2o1z wljQvVgO7qU8nQmWl9PS9weD3A== X-Google-Smtp-Source: AGHT+IGfvPndwtubeysEkGBSe3P/I0KBNSmcl27k26RD2FLLQ+j3OqYWoI+9c2SEWjqylHIx2vUv/Q== X-Received: by 2002:a05:6870:1391:b0:1ea:6a81:8c8a with SMTP id 17-20020a056870139100b001ea6a818c8amr1412779oas.29.1697533701742; Tue, 17 Oct 2023 02:08:21 -0700 (PDT) Received: from localhost (9.184.168.34.bc.googleusercontent.com. [34.168.184.9]) by smtp.gmail.com with UTF8SMTPSA id s11-20020a632c0b000000b0058958ea2aaesm945519pgs.83.2023.10.17.02.08.21 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 17 Oct 2023 02:08:21 -0700 (PDT) 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, surenb@google.com, alex.sierra@amd.com, apopple@nvidia.com, aneesh.kumar@linux.ibm.com, axelrasmussen@google.com, ben@decadent.org.uk, catalin.marinas@arm.com, david@redhat.com, dwmw@amazon.co.uk, ying.huang@intel.com, hughd@google.com, joey.gouly@arm.com, corbet@lwn.net, wangkefeng.wang@huawei.com, Liam.Howlett@oracle.com, lstoakes@gmail.com, mawupeng1@huawei.com, linmiaohe@huawei.com, namit@vmware.com, peterx@redhat.com, peterz@infradead.org, ryan.roberts@arm.com, shr@devkernel.io, vbabka@suse.cz, xiujianfeng@huawei.com, yu.ma@intel.com, zhangpeng362@huawei.com, dave.hansen@intel.com, luto@kernel.org, linux-hardening@vger.kernel.org Subject: [RFC PATCH v2 3/8] mseal: add can_modify_mm and can_modify_vma Date: Tue, 17 Oct 2023 09:08:10 +0000 Message-ID: <20231017090815.1067790-4-jeffxu@chromium.org> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog In-Reply-To: <20231017090815.1067790-1-jeffxu@chromium.org> References: <20231017090815.1067790-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: B7D7F160021 X-Stat-Signature: fnj8tupaxo768bsbxztg6stwouwot6fi X-HE-Tag: 1697533702-990459 X-HE-Meta: U2FsdGVkX1+5j/mHAjNexxOK981ikMElJcRQHurAAmUHOZ93TvMMG2+C0vk5jgBfG68V9SiqMZKMCwHAYHLZVSgbQeh3aLGXtGfUln4/6Lh1YPRZX/1vgRk3JwqisNq2QTqRrw2IAF4FfDX0c6ne2MhCtRw9uqyCfX+INmtyNJ9trjdLQ/Xl1W3T1k4uWhY8dGb4a10w89bfZTVxFsHG86RS82AATYlCrGggnVmtMX4KijeKxMykxwmIgwyH9KVIAQuW/8SkvR3wqBNQNfJWX/UtIMJGeNhvOEGDl5oFGlThZz6m4HYg0HKOdBFbQPvUTcOboxsdy0QzjNG+WlWvXyDKB3bQbd1gp+S3P0c0liak8LWiisSu6KgCIve0UpZeJA60rTtbLLiRi7LAsrlnaW5+zRzRY4DuUufgOwvnFtzRzNLacjNhhbCrYXqaaRKisyUGegJZ9WhI0xYF255C0MBESo0JTy+c10H5NCEHJ+vySF46c8fYm1Z4FPYSmyhZj1HjRcPwf3O6wP4VA1iS4PRoU0faHnJxqM75rlaq4OQU8R4jC+srWdcXTDnNVFXpi3GH/XgBbspkzyurn6e8PYP2cIPU2H+pUmNBCgQevfXx8uIyP6OpoM7HzngVU6j6LJZZbjr4X0x/Y8Gq2lMHp33/ZR5aPJ1fk14fK4wP1iCNN2rojkVdoAkmKUgy5jCImxZPMZV9v7qrhdjuTSf1CW71OD9mqDidiU+bgE+MB0h1QD6K+2uXvulMucUtCBWDbdvMxwV9/WDRUI/HfyBg5vsVmLuH93zgMhlrPCG/SPTkrTXyyPslxkQoL7Df+RbQD/13+mohsMo2+ZOom351qS2FtIVWXZ0UXN+U/uMCk8uv+PrrNwYrr3KQHQyrqj1FcbsgecaDiTZU4jVdkw4zzFeckuQuOdjSJwnrlIhexO0V8izxheC1/4UWRak7LeiHYqqxkdgtnSUjv5dgcsA jMr8DtZs 3jB7KAoNiv0pNS94VR+hVZ9wBePb7DgLtASqu6pfdC7LeFMrzne+DQ1HM5niEBL8Lycj+vwikaZoa0BXx6lzLeXuvS7ChuAt3Fui7pvtmNW/wiRZ6DHtqfVPHmuEFDudCny9FAnsxjw+PJq+zOSi3NeD3HcuKL+4rGymSAkxzQop2iNuV70X6Us0NznmPSKkKsySzJFvFUHnC8GCXJIV1EjHTW23F0GK9Iz1ctOb+gi3ukfYHiWvD5pm/HGd6MyuCgJiHXQGoSJXpRw1MoBWHPjkqA9AgKPm2pjN3s0WQK5HIi6/f+tkibHJgWD8e2yX5r8znIaDqirKjRfipiDI5XI1VTSeK1RoxnOWldRVrvV8qPQazakbynkuJVA== 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 can_modify_mm: checks sealing flags for given memory range. can_modify_vma: checks sealing flags for given vma. Signed-off-by: Jeff Xu --- include/linux/mm.h | 26 ++++++++++++++++++++++++++ mm/mseal.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index b511932df033..b09df8501987 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3299,6 +3299,32 @@ static inline void mm_populate(unsigned long addr, unsigned long len) static inline void mm_populate(unsigned long addr, unsigned long len) {} #endif +#ifdef CONFIG_MSEAL +extern bool can_modify_mm(struct mm_struct *mm, unsigned long start, + unsigned long end, unsigned long checkSeals); + +extern bool can_modify_vma(struct vm_area_struct *vma, + unsigned long checkSeals); + +static inline unsigned long vma_seals(struct vm_area_struct *vma) +{ + return (vma->vm_seals & MM_SEAL_ALL); +} + +#else +static inline bool can_modify_mm(struct mm_struct *mm, unsigned long start, + unsigned long end, unsigned long checkSeals) +{ + return true; +} + +static inline bool can_modify_vma(struct vm_area_struct *vma, + unsigned long checkSeals) +{ + return true; +} +#endif + /* These take the mm semaphore themselves */ extern int __must_check vm_brk(unsigned long, unsigned long); extern int __must_check vm_brk_flags(unsigned long, unsigned long, unsigned long); diff --git a/mm/mseal.c b/mm/mseal.c index ffe4c4c3f1bc..3e9d1c732c38 100644 --- a/mm/mseal.c +++ b/mm/mseal.c @@ -26,6 +26,44 @@ static bool can_do_mseal(unsigned long types, unsigned long flags) return true; } +/* + * check if a vma is sealed for modification. + * return true, if modification is allowed. + */ +bool can_modify_vma(struct vm_area_struct *vma, + unsigned long checkSeals) +{ + if (checkSeals & vma_seals(vma)) + return false; + + return true; +} + +/* + * Check if the vmas of a memory range are allowed to be modified. + * the memory ranger can have a gap (unallocated memory). + * return true, if it is allowed. + */ +bool can_modify_mm(struct mm_struct *mm, unsigned long start, unsigned long end, + unsigned long checkSeals) +{ + struct vm_area_struct *vma; + + VMA_ITERATOR(vmi, mm, start); + + if (!checkSeals) + return true; + + /* going through each vma to check */ + for_each_vma_range(vmi, vma, end) { + if (!can_modify_vma(vma, checkSeals)) + return false; + } + + /* Allow by default. */ + return true; +} + /* * Check if a seal type can be added to VMA. */ @@ -33,7 +71,7 @@ static bool can_add_vma_seals(struct vm_area_struct *vma, unsigned long newSeals { /* When SEAL_MSEAL is set, reject if a new type of seal is added */ if ((vma->vm_seals & MM_SEAL_MSEAL) && - (newSeals & ~(vma->vm_seals & MM_SEAL_ALL))) + (newSeals & ~(vma_seals(vma)))) return false; return true; @@ -45,7 +83,7 @@ static int mseal_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma, { int ret = 0; - if (addtypes & ~(vma->vm_seals & MM_SEAL_ALL)) { + if (addtypes & ~(vma_seals(vma))) { /* * Handle split at start and end. * Note: sealed VMA doesn't merge with other VMAs. From patchwork Tue Oct 17 09:08:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13424813 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 A2347CDB482 for ; Tue, 17 Oct 2023 09:08:29 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 0CA808D0105; Tue, 17 Oct 2023 05:08:26 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 054B88D0101; Tue, 17 Oct 2023 05:08:25 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D99948D0105; Tue, 17 Oct 2023 05:08:25 -0400 (EDT) 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 C0E908D0101 for ; Tue, 17 Oct 2023 05:08:25 -0400 (EDT) Received: from smtpin01.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id A11E6B6222 for ; Tue, 17 Oct 2023 09:08:25 +0000 (UTC) X-FDA: 81354377370.01.B97E4C0 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) by imf21.hostedemail.com (Postfix) with ESMTP id D25271C0017 for ; Tue, 17 Oct 2023 09:08:23 +0000 (UTC) Authentication-Results: imf21.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=m1BjMJzS; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf21.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.216.44 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1697533703; 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=4llBoLvRHSRPhxaAVX+Xew1tpI9xPqxP9ssy5QguIl8=; b=sI8jN4MkbtLr1s6NqtXN1LepmpDO5oxVLetjJomLts5JhiQ+IPIucuxtKgrDmnIgUfZCa4 W1mpwY31yNlxmxPlGy0r+5mL3MiBWC0GVRLMVW3nA4+JH1ErBKNJ4pSGZez+3JojkbEFbD voADtiKzJIbCin8fo6G15aN5DEGwKYQ= ARC-Authentication-Results: i=1; imf21.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=m1BjMJzS; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf21.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.216.44 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1697533703; a=rsa-sha256; cv=none; b=2ySRqM3lve/fx32Zg+JiVdNpgqrhM3O3SLTx3iRILZpe8OPhQO1P7TeCmrQ6gV0ft/agNg I4r26ZESt4+KFta6gi12t/uNvQQ426Hw+Hlkqe4+Yaglc1N/JkQm2e0GdYstaXa3iXiFur 5F7Tp/40SJRJ01kq9pL5+a9pmZ3RZ/g= Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-27d1b48e20dso3051651a91.0 for ; Tue, 17 Oct 2023 02:08:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1697533702; x=1698138502; 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=4llBoLvRHSRPhxaAVX+Xew1tpI9xPqxP9ssy5QguIl8=; b=m1BjMJzS88ivL7tBhxOtFFOEeE75xogMDCs+QMwmDebgxB3stxW49uJj6vrMCAhX4o LQcQS21QzwN/28mENOjVzB9TMpTJBCQkRMCnOY15vDIW+iajuJPTUGqFw+SI7nOQFZAY 59aNSrAnY4USGLRPTCDKz4QaKqYTgKXk2WYYQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697533702; x=1698138502; 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=4llBoLvRHSRPhxaAVX+Xew1tpI9xPqxP9ssy5QguIl8=; b=lLxjazakm27AYbQ8CJ8q9Kmom9uBga0ysOlpr/Rou7xVcJbejaZmKavsypDvucdIAJ Pkt6THhzki5YLsDfA2O5kgdV/12HC+hUnnzvS56napvN4ldh46oYxw3tDntKigP3Fca0 vNWcUg6bFCiLU4oGvpTeMfpEQDz1/MMrV0sYxEmlQI/r5zF5pfXZmp+OBTn0cKJ6qgCO ambd8hR0XVWbulL9B/QKKiSy0UdFCKQYZmvqI6jp82/XEPStb9KSmO1h/Hg5a8SHd6YS hABZx0NfaL43bDXtp6erDj2heYk52TtoI1EwfnzPTf30qiZBtpGezjUNBS3/b4DM+n1x 6rNw== X-Gm-Message-State: AOJu0YwM8NXZM7crmrAsuCJsufMQNc1C0zZs6BVlztAbABrFNJCJgtjC UBY4ijU2k/Q2rjahTmhrfSs2bw== X-Google-Smtp-Source: AGHT+IGY8Ka5xTN+9aN+5JwGnYHZ3aFuu39VQWy4bG7nyYFZ0P/8XqDQIp2idGjzoHOlr8sq9RvLbg== X-Received: by 2002:a17:90b:124a:b0:27c:f21b:6342 with SMTP id gx10-20020a17090b124a00b0027cf21b6342mr1443714pjb.22.1697533702687; Tue, 17 Oct 2023 02:08:22 -0700 (PDT) Received: from localhost (9.184.168.34.bc.googleusercontent.com. [34.168.184.9]) by smtp.gmail.com with UTF8SMTPSA id t13-20020a17090ae50d00b00277326038dasm868586pjy.39.2023.10.17.02.08.22 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 17 Oct 2023 02:08:22 -0700 (PDT) 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, surenb@google.com, alex.sierra@amd.com, apopple@nvidia.com, aneesh.kumar@linux.ibm.com, axelrasmussen@google.com, ben@decadent.org.uk, catalin.marinas@arm.com, david@redhat.com, dwmw@amazon.co.uk, ying.huang@intel.com, hughd@google.com, joey.gouly@arm.com, corbet@lwn.net, wangkefeng.wang@huawei.com, Liam.Howlett@oracle.com, lstoakes@gmail.com, mawupeng1@huawei.com, linmiaohe@huawei.com, namit@vmware.com, peterx@redhat.com, peterz@infradead.org, ryan.roberts@arm.com, shr@devkernel.io, vbabka@suse.cz, xiujianfeng@huawei.com, yu.ma@intel.com, zhangpeng362@huawei.com, dave.hansen@intel.com, luto@kernel.org, linux-hardening@vger.kernel.org Subject: [RFC PATCH v2 4/8] mseal: Check seal flag for mprotect(2) Date: Tue, 17 Oct 2023 09:08:11 +0000 Message-ID: <20231017090815.1067790-5-jeffxu@chromium.org> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog In-Reply-To: <20231017090815.1067790-1-jeffxu@chromium.org> References: <20231017090815.1067790-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: D25271C0017 X-Stat-Signature: ewinumyjboibemrdb5jpj5czas87qdp3 X-HE-Tag: 1697533703-610533 X-HE-Meta: U2FsdGVkX19xbVk+EW31G1Bk2lamXl4I6/v7AMcZaRIlo82HUN9ezLoXqMMqj5Fb4zZtJQ/wAansYjPHTrDQhFXcg3eggXwxnj5bP3SYXtPwQ5o0DNbDuwBRDaN2zNVv67WFmXx3ie8A3DxtUupOuYadggzR4GO7+FSkljV2SJfVCA81oJSBWCqbhQFWCHAb8/cImRuHeVF3yC/O4eyhj1BuztVgdlSfGGHRYLY/E6mpgpRc0X1UVcrrkFsQNThYuIdiIA8UqrNXWo06+QlnVnuwXf6Ks5NQQ51VeAwydJsRTJ8PuMhuqnlu1KyX47M5qain/y3HWHYJhJoiTSA3/yCF0AjxhyjQjly8L/GvWR/tjykl7bZyI2hhD036i5XsBiaBlYh2ilz/OdUolI1HeFiQQ6oBrh01yQ22Jw4CBOpDjzx/dgl6XPbXEwbA38y2RcpsczuGZQ+9te/ydDCIj9qOyebMn57YiGOjeC0HtmaPKgHjBTizcu62IGr30bM5ItKfGKlRpVtqDDRk+w1EGQAMrpH1/XobE/OokBeWduot0FqG07q7aLQGivAzpUs0yVThLYTbEaCsNbOFXg9g2jAaXAmnyKAS8VkbS5eX6FU+/QnarY37UsPoxXQLp/9wIMtOf0myVET/LkGZLdTFoOz4mWHRZpHrKorsIJ7hhaDZ4ZRk3Jw/55qrsTXEtBZ1/c8LlY0DyaCI/yeCqzED2IzCjeiChpwJzyByXv63TrNgKhVZcak9fS4rE37lHpvTlcVB9m/B8EG6PAjJBiE9GnZZ2/ni4nE9lMyUR2eSGhsaIDCFmrhUEPxsd04z+2IbiwirJWjWwjP2lQNJU7J8eJ/ZMDsffei77OMCWNubP52Qf9t+mvU2YVptX3N1Ufvq0xUDFi22tLefQHpc84va3CuKp5cO7sz34WZdXCBd1gKIPlF0k35C9xKRsRJHl8V1Uxt3QXw9gtzIHVx84rn mHZbvoZS QDPafTrPNFQA7s63C4ArF3YHp4fTEqOk7AVrRm/AVI6qNoCOYIAeySoZV4ztGFY6R1XHmuLT7jNIWl1WcTenQn83tOtGbHS4m28MrAuqZaCWlFrO1r6+sWKmc9rMrxLcQjnWldZoZSvz4RDaAsQ1NRnl4MqaFuDL2kdcdTKGBdv2NZi/2xmSdilHuIFTl/2alODA1dLT9riNsyuSj90KdbJ3GNNAeRFVhkzfQfkboSqvs2JF378NK6Sp/JGxJqH9xQVKsSW8RZW7HivZs6++b9xP5UvEtcqXkfcCzmc85pngb6FTCacLW52AJ9K4kpkeeoM4H26dodayJoRhnUg/Ob/LHTyztHPIyDPNRYBy+zxTqvlw= 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 mprotect(2) changes protection of VMAs in the given address range. Sealing will prevent unintended mprotect call. What this patch does: When a mprotect(2) is invoked, if one of its VMAs has MM_SEAL_MPROTECT set from previous mseal(2) call, this mprotect(2) will fail, without any VMA modified. This patch is based on following: 1. do_mprotect_pkey() currently called in two places: SYSCALL_DEFINE3(mprotect,...) SYSCALL_DEFINE4(pkey_mprotect, ...) and not in any other places, therefore omit changing the signature of do_mprotect_pkey(), i.e. not passing checkSeals flag. 2. In do_mprotect_pkey(), calls can_modify_mm() before any update is made on the VMAs. Signed-off-by: Jeff Xu --- mm/mprotect.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mm/mprotect.c b/mm/mprotect.c index 130db91d3a8c..6321c4d0aa3f 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -753,6 +754,20 @@ static int do_mprotect_pkey(unsigned long start, size_t len, } } + /* + * do_mprotect_pkey() currently called from two places: + * SYSCALL_DEFINE3(mprotect,...) + * SYSCALL_DEFINE4(pkey_mprotect, ...) + * and not from other places. + * Therefore, omit changing the signature of do_mprotect_pkey(). + * Otherwise, we might need to add checkSeals and pass it + * from all callers of do_mprotect_pkey(). + */ + if (!can_modify_mm(current->mm, start, end, MM_SEAL_MPROTECT)) { + error = -EACCES; + goto out; + } + prev = vma_prev(&vmi); if (start > vma->vm_start) prev = vma; From patchwork Tue Oct 17 09:08:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13424814 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 E13FECDB483 for ; Tue, 17 Oct 2023 09:08:31 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 6E48D8D0106; Tue, 17 Oct 2023 05:08:27 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 693E58D0101; Tue, 17 Oct 2023 05:08:27 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 4E7348D0106; Tue, 17 Oct 2023 05:08:27 -0400 (EDT) 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 3A9338D0101 for ; Tue, 17 Oct 2023 05:08:27 -0400 (EDT) Received: from smtpin21.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 146E2120F98 for ; Tue, 17 Oct 2023 09:08:27 +0000 (UTC) X-FDA: 81354377454.21.9015444 Received: from mail-pl1-f169.google.com (mail-pl1-f169.google.com [209.85.214.169]) by imf27.hostedemail.com (Postfix) with ESMTP id 40F5840008 for ; Tue, 17 Oct 2023 09:08:25 +0000 (UTC) Authentication-Results: imf27.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=Z8LmKfHt; spf=pass (imf27.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.214.169 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=1697533705; 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=UgKgE+zT4qoDlXNN6kCnypBqiPQ8What3ncvSi+XOyU=; b=fuUD6RhLhTtpjL8gMD2EVond3KZxViCh7Ob/6KaWPgwWPw6Mwi9uNe051gTnXvxkTVt+62 wUXlMZtN2MeJKTZTRFWZJ8w7lHeD6V6pxVCFzBifoDvCQ4cHyr6k+Kw/V6WeuEAdu4+5pM SEqXzc2MkEqSnlsaBMs7W3FEmICAS2U= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1697533705; a=rsa-sha256; cv=none; b=QBeWeZ/YSFkeg6YaecHwD0C6SsSYXvjhr6scdZPNgRPBUyWvLUL3Yi5F3jBsr9OOEUIMJn BEUQkChJSH8eCVYHVO37kpg+TXrtqZekpedBm8nSjtXZqrWnn+7lp0H0nbAF9NTIcEA1Xh sYwI5lhEeS9U954G4huvsJanOViPbco= ARC-Authentication-Results: i=1; imf27.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=Z8LmKfHt; spf=pass (imf27.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.214.169 as permitted sender) smtp.mailfrom=jeffxu@chromium.org; dmarc=pass (policy=none) header.from=chromium.org Received: by mail-pl1-f169.google.com with SMTP id d9443c01a7336-1c0ecb9a075so35841345ad.2 for ; Tue, 17 Oct 2023 02:08:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1697533704; x=1698138504; 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=UgKgE+zT4qoDlXNN6kCnypBqiPQ8What3ncvSi+XOyU=; b=Z8LmKfHtjSvJLqyJVFpwEUs/QcvL5zm1gu7hRIFWfzcQkl3dZoME7P7i38o6UtCzUe ppZrcBSeJY+msxBBx/GOL6jGP18PvRjYg8de0vTscOxFJl3jfKl8FcogtzIje5NpoZQs ZGQUVYSida0priiQCR2nMN8n6UepuVmkPtljU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697533704; x=1698138504; 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=UgKgE+zT4qoDlXNN6kCnypBqiPQ8What3ncvSi+XOyU=; b=blS8eKUzL8dN0NGNTcPtWLb9wzHPntyuZ8azfq+1/AD23K2ZyB8t0lJJ610VyhV9Gz YRbZST+CAn6ZOhpIWnrSg2Ip574EVuiO6SVLVpYvQSBaZjDjnZEqlDhWG8r+6jwL97+l yWizxLFSger4ibwPE9Zb4rRjsHdQuJ5UuLfQUdTGUQlbnmiBDnqpU+YyMixghAKMZMAR AC/LjRR2K3aWtK+PZ4RzQPdhchU+Pv79YhAW0l1m4Dhe5V9EugN0aqJEevTXRdIr3L/Y G09RQLER4MgenEyxloi7lQ6pgxU18Z46K6qhR924ey3mV8VxCK38RJcXHY81ylP8N0Hc ja7w== X-Gm-Message-State: AOJu0YwmqMEgItoRd2LDhjjzbprUfq5pWdZ4jK7ibJCEuNij+AtIw7/W 4oqBiLm2r7vrroutH+eKlAPowg== X-Google-Smtp-Source: AGHT+IHCYocrm1n4yld0Gd8Vj3vGZcQMpjkWq5rvV/TBCHu6MN2SKOy6Ffa2J/O1CuQzRvjFk/JD+Q== X-Received: by 2002:a17:903:4295:b0:1c6:2780:3adc with SMTP id ju21-20020a170903429500b001c627803adcmr1780065plb.24.1697533704140; Tue, 17 Oct 2023 02:08:24 -0700 (PDT) Received: from localhost (9.184.168.34.bc.googleusercontent.com. [34.168.184.9]) by smtp.gmail.com with UTF8SMTPSA id t7-20020a170902e84700b001bc21222e34sm995141plg.285.2023.10.17.02.08.23 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 17 Oct 2023 02:08:23 -0700 (PDT) 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, surenb@google.com, alex.sierra@amd.com, apopple@nvidia.com, aneesh.kumar@linux.ibm.com, axelrasmussen@google.com, ben@decadent.org.uk, catalin.marinas@arm.com, david@redhat.com, dwmw@amazon.co.uk, ying.huang@intel.com, hughd@google.com, joey.gouly@arm.com, corbet@lwn.net, wangkefeng.wang@huawei.com, Liam.Howlett@oracle.com, lstoakes@gmail.com, mawupeng1@huawei.com, linmiaohe@huawei.com, namit@vmware.com, peterx@redhat.com, peterz@infradead.org, ryan.roberts@arm.com, shr@devkernel.io, vbabka@suse.cz, xiujianfeng@huawei.com, yu.ma@intel.com, zhangpeng362@huawei.com, dave.hansen@intel.com, luto@kernel.org, linux-hardening@vger.kernel.org Subject: [RFC PATCH v2 5/8] mseal: Check seal flag for munmap(2) Date: Tue, 17 Oct 2023 09:08:12 +0000 Message-ID: <20231017090815.1067790-6-jeffxu@chromium.org> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog In-Reply-To: <20231017090815.1067790-1-jeffxu@chromium.org> References: <20231017090815.1067790-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 40F5840008 X-Rspam-User: X-Rspamd-Server: rspam11 X-Stat-Signature: b8uuhbfg1g8tc8aoh7wqm45ep8zajo4x X-HE-Tag: 1697533705-91675 X-HE-Meta: U2FsdGVkX19q7Xutd9xFYT336iYPDZL8oW+WtVZhNTKeqr6WUpDZQJ0BpPuAZ2oH5QThqt12rf+Wv4agsOM9Jv0ULpZyyWd//0ksGGTBPyQjZrIn5uNO9Uj4c8yDmPQQMJBhJqMh+Y7QsLDvTEU3LY8atTa92gicF9z2M+H2kZzKk0NEg7rU7oRnJ/M3c+pNtHpYrOHeLlu43zczFoelZZXrC3DB6LjHYzp3C5PWbly+hEFdTc9WEffNXIwYAUUGF8v87ZKXxqqR7HVhdMRWyZ/XIBPUlU/JjsKDf+VP6zxdJvFWNdsyRS1BpQ4lwzT15GriSdevzse8+3m5o8nYvMBRLSJu4LdeO3ZIIdhNUWCoTqh724R6Xxwyfw0qBC2pdEqDU7rl9qPQfpqWVMhaYHTNTQAYPpV71OFIbFzzo9gbw9PnDm0bJGB7lkaLaBkxl7YMGuhnrgqXGh1vVjWX5z7sAlbFjduBS0cYVfkZ0hEhItO79Lf4ZzkokygPhx46/9HTBq4UpnBMdcW32BLggk3/rmrzkwHmwZU7bfk0nh/g9d7QEgUWGHdiC7iMIgZkFUH7y4c9XVitL96ulH3foVwY64OLaaaKTNNkwGz3lB0RB2VpdFcLX57NHGW0yQl3okpz4nPfP91oIdIohnr5lZbJoElfKC/8LplmslazFnmS2/lLpo5eDr3W7HQcK4PCzskkU/yJYa8CkeSkzwCe7i+QblDGvKBUa8pHEGSyvanhReTCdyHPQRoYtbpxoNcoDENYC/6w6V0TsO0FvmLiYWBox198N8CK8+9ixZns2J/GIx+SEzXJrsZyZ0re9dspKFjbbL/Pl7ZgXDs5RLftSjxbx3hV5vxNgB2+gSKl5KUWyU7TfcLuFVndOHdbR8HmMPlIB3PS/CK15A/akVe8uCeb9dofXGOddTAyzBJ2kgcpq0Xzzh5SAOSe9qpqSxkb5pBhaZ5GUA/QX/4znuj qr21t2T5 2eLgEBLHG72jW2E9KDikfW8Jjn+ozGezLvS59bCjBFJimCKhWVWmHhptgm9lODoPdDDDVnXklHhMmbCncn7D7yRVXG6K3XZLUUlxigiaymzAd4+ccApLLjxTedK6M8HWlwMQqovVofT4sSvqFME3tnlxyF+hkNukYXekyU/N+op5imJLszig0hMI6OBnEGhTJ3/OGmnie3BLIfM4eqpAlH6oF4TdiGFxHPIHl4WC4yTnN9iG9D7EusG7DnsZuhUqFK6YQFuakg6ZjQkFVkwpkMfFTka8qx96zHm17Mfnfe0xXB+O1pXYUhRj7p3vaok8Wy7pO4eJ/3UVfQ/k= 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 munmap(2) unmap VMAs in the given address range. Sealing will prevent unintended munmap(2) call. What this patch does: When a munmap(2) is invoked, if one of its VMAs has MM_SEAL_MUNMAP set from previous mseal(2) call, this munmap(2) will fail, without any VMA modified. This patch is based on following: 1. At syscall entry point: SYSCALL_DEFINE2(munmap, ...) Pass checkSeals = MM_SEAL_MUNMAP into __vm_munmap(), in turn, to do_vmi_munmap(). Of all the call paths that call into do_vmi_munmap(), this is the only place where checkSeals = MM_SEAL_MUNMAP. The rest has checkSeals = 0. 2. In do_vmi_munmap(), calls can_modify_mm() before any update is made to VMAs. Signed-off-by: Jeff Xu --- include/linux/mm.h | 2 +- mm/mmap.c | 21 +++++++++++++-------- mm/mremap.c | 5 +++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index b09df8501987..f2f316522f2a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3279,7 +3279,7 @@ extern unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long pgoff, unsigned long *populate, struct list_head *uf); extern int do_vmi_munmap(struct vma_iterator *vmi, struct mm_struct *mm, unsigned long start, size_t len, struct list_head *uf, - bool unlock); + bool unlock, unsigned long checkSeals); extern int do_munmap(struct mm_struct *, unsigned long, size_t, struct list_head *uf); extern int do_madvise(struct mm_struct *mm, unsigned long start, size_t len_in, int behavior); diff --git a/mm/mmap.c b/mm/mmap.c index 414ac31aa9fa..62d592f16f45 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2601,6 +2601,7 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma, * @len: The length of the range to munmap * @uf: The userfaultfd list_head * @unlock: set to true if the user wants to drop the mmap_lock on success + * @checkSeals: seal type to check. * * This function takes a @mas that is either pointing to the previous VMA or set * to MA_START and sets it up to remove the mapping(s). The @len will be @@ -2611,7 +2612,7 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma, */ int do_vmi_munmap(struct vma_iterator *vmi, struct mm_struct *mm, unsigned long start, size_t len, struct list_head *uf, - bool unlock) + bool unlock, unsigned long checkSeals) { unsigned long end; struct vm_area_struct *vma; @@ -2623,6 +2624,9 @@ int do_vmi_munmap(struct vma_iterator *vmi, struct mm_struct *mm, if (end == start) return -EINVAL; + if (!can_modify_mm(mm, start, end, checkSeals)) + return -EACCES; + /* arch_unmap() might do unmaps itself. */ arch_unmap(mm, start, end); @@ -2650,7 +2654,7 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len, { VMA_ITERATOR(vmi, mm, start); - return do_vmi_munmap(&vmi, mm, start, len, uf, false); + return do_vmi_munmap(&vmi, mm, start, len, uf, false, 0); } unsigned long mmap_region(struct file *file, unsigned long addr, @@ -2684,7 +2688,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr, } /* Unmap any existing mapping in the area */ - if (do_vmi_munmap(&vmi, mm, addr, len, uf, false)) + if (do_vmi_munmap(&vmi, mm, addr, len, uf, false, 0)) return -ENOMEM; /* @@ -2909,7 +2913,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, return error; } -static int __vm_munmap(unsigned long start, size_t len, bool unlock) +static int __vm_munmap(unsigned long start, size_t len, bool unlock, + unsigned long checkSeals) { int ret; struct mm_struct *mm = current->mm; @@ -2919,7 +2924,7 @@ static int __vm_munmap(unsigned long start, size_t len, bool unlock) if (mmap_write_lock_killable(mm)) return -EINTR; - ret = do_vmi_munmap(&vmi, mm, start, len, &uf, unlock); + ret = do_vmi_munmap(&vmi, mm, start, len, &uf, unlock, checkSeals); if (ret || !unlock) mmap_write_unlock(mm); @@ -2929,14 +2934,14 @@ static int __vm_munmap(unsigned long start, size_t len, bool unlock) int vm_munmap(unsigned long start, size_t len) { - return __vm_munmap(start, len, false); + return __vm_munmap(start, len, false, 0); } EXPORT_SYMBOL(vm_munmap); SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) { addr = untagged_addr(addr); - return __vm_munmap(addr, len, true); + return __vm_munmap(addr, len, true, MM_SEAL_MUNMAP); } @@ -3168,7 +3173,7 @@ int vm_brk_flags(unsigned long addr, unsigned long request, unsigned long flags) if (ret) goto limits_failed; - ret = do_vmi_munmap(&vmi, mm, addr, len, &uf, 0); + ret = do_vmi_munmap(&vmi, mm, addr, len, &uf, 0, 0); if (ret) goto munmap_failed; diff --git a/mm/mremap.c b/mm/mremap.c index 056478c106ee..ac363937f8c4 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -715,7 +715,8 @@ static unsigned long move_vma(struct vm_area_struct *vma, } vma_iter_init(&vmi, mm, old_addr); - if (!do_vmi_munmap(&vmi, mm, old_addr, old_len, uf_unmap, false)) { + if (!do_vmi_munmap(&vmi, mm, old_addr, old_len, uf_unmap, false, + 0)) { /* OOM: unable to split vma, just get accounts right */ if (vm_flags & VM_ACCOUNT && !(flags & MREMAP_DONTUNMAP)) vm_acct_memory(old_len >> PAGE_SHIFT); @@ -1009,7 +1010,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, } ret = do_vmi_munmap(&vmi, mm, addr + new_len, old_len - new_len, - &uf_unmap, true); + &uf_unmap, true, 0); if (ret) goto out; From patchwork Tue Oct 17 09:08:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13424815 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 40979CDB474 for ; Tue, 17 Oct 2023 09:08:35 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 7819F8D0107; Tue, 17 Oct 2023 05:08:28 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 6BA878D0101; Tue, 17 Oct 2023 05:08:28 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 535168D0107; Tue, 17 Oct 2023 05:08:28 -0400 (EDT) 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 2FD708D0101 for ; Tue, 17 Oct 2023 05:08:28 -0400 (EDT) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 00194A0F86 for ; Tue, 17 Oct 2023 09:08:27 +0000 (UTC) X-FDA: 81354377454.11.7F32974 Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) by imf19.hostedemail.com (Postfix) with ESMTP id 264DC1A0007 for ; Tue, 17 Oct 2023 09:08:25 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=IfIXCkRu; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf19.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.214.181 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1697533706; 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=ViNyz7MVEy68sAHHL0LA4TbUsB4+tEyuC2ph9hmOQwY=; b=iJ/F+R8Ywfa82za/G1egGTdYHv2PmuPdk3sEcFkj3k0V5lQhnx+qW0WXvCpJtQVfRdpcr6 OZ0SCV4Vymc9yl1702fBJwf29gS4Q4142xPXN9tSQ8m+NRmZYOfMH7IIy2SOoq39XUb+Uk 2X8qeEk2mOpnrO5+L46zcAfqXm3+OfE= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=IfIXCkRu; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf19.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.214.181 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1697533706; a=rsa-sha256; cv=none; b=Lc42KygczbIpw1anmYJ1Ba/k3xnv8Y1/gUzvPaUNjpBKhJnrE5RT1PJGIS7FGxkG0m4Jb8 ZKyhU+fkw9THhGXGbCC2MzDs1+KCAKeLFq1Dhl7nCXy0h0D5JZDgMbLcEE1QBFYL4P6CSf r2fP96DYPCAtojEdaYZ7VXGyAvv64hQ= Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-1c9b70b9656so32194565ad.1 for ; Tue, 17 Oct 2023 02:08:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1697533705; x=1698138505; 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=ViNyz7MVEy68sAHHL0LA4TbUsB4+tEyuC2ph9hmOQwY=; b=IfIXCkRucaef/p9FaKgbgMqEHlR0AWeXUzuO6BhHQPf4QionXtxYIuuQbWFrj2XBTU 8i88BA58HBep+7PwjQPUp0kpc0vE1xVBqrPL/N2uTnymfg6Q+4O9bdtjDjBRjek13CNi iYkbRSAAOD78wQN7AuKzRgNhubRqdLfiPk2as= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697533705; x=1698138505; 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=ViNyz7MVEy68sAHHL0LA4TbUsB4+tEyuC2ph9hmOQwY=; b=oGyKmYhpp0GyY8wGsK1npYF3pZnanjSKWK5SlaQKhq0AHz8rEXthJ79t0pWak1ElBM /W9/Y6NgmIXxZHiSNIGlg+RBayK3k0wQIJhyWOq9qmEyeV9fGfYjR0ll11DuHN2/W5jy uhYF4lT9x/HPzFYmTmo7ekITxbWZfoMWtG+hiYjO3vL7XX1bKFO/L2c/7NJB2t96g2en 5V+yKWxLLzzv+zlnofmcfZEDL3ZNk6CRs9/5qPbcZNgdIBuAC/bzpT/kt4FpXTZGvTs4 Kk0l5reVD4d/jicTgDGAwXJH4s7KYDUWouphZQ619+TNcGVlAbSJBRIWRVRvOXml1aPu CemA== X-Gm-Message-State: AOJu0Yws6qgHgCjQM5swDW4QX6BruIEWrK89Pi+S9IuN1Qk7KO1Cw84Q trfS0048hNKqW0qeGJjatdR1Zg== X-Google-Smtp-Source: AGHT+IHMQjs3CP1M6u0EHjQpywUiPuYTFdj8fIiwHgzFn3k/gAIRbOULG1q5OcNoW72tl/neYPQw3A== X-Received: by 2002:a17:902:e749:b0:1c9:b187:4d84 with SMTP id p9-20020a170902e74900b001c9b1874d84mr2075293plf.14.1697533704959; Tue, 17 Oct 2023 02:08:24 -0700 (PDT) Received: from localhost (9.184.168.34.bc.googleusercontent.com. [34.168.184.9]) by smtp.gmail.com with UTF8SMTPSA id ij25-20020a170902ab5900b001b890b3bbb1sm1019372plb.211.2023.10.17.02.08.24 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 17 Oct 2023 02:08:24 -0700 (PDT) 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, surenb@google.com, alex.sierra@amd.com, apopple@nvidia.com, aneesh.kumar@linux.ibm.com, axelrasmussen@google.com, ben@decadent.org.uk, catalin.marinas@arm.com, david@redhat.com, dwmw@amazon.co.uk, ying.huang@intel.com, hughd@google.com, joey.gouly@arm.com, corbet@lwn.net, wangkefeng.wang@huawei.com, Liam.Howlett@oracle.com, lstoakes@gmail.com, mawupeng1@huawei.com, linmiaohe@huawei.com, namit@vmware.com, peterx@redhat.com, peterz@infradead.org, ryan.roberts@arm.com, shr@devkernel.io, vbabka@suse.cz, xiujianfeng@huawei.com, yu.ma@intel.com, zhangpeng362@huawei.com, dave.hansen@intel.com, luto@kernel.org, linux-hardening@vger.kernel.org Subject: [RFC PATCH v2 6/8] mseal: Check seal flag for mremap(2) Date: Tue, 17 Oct 2023 09:08:13 +0000 Message-ID: <20231017090815.1067790-7-jeffxu@chromium.org> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog In-Reply-To: <20231017090815.1067790-1-jeffxu@chromium.org> References: <20231017090815.1067790-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 264DC1A0007 X-Stat-Signature: wcqmph8fmgwqkzrxbdj19z9wih3phyf9 X-HE-Tag: 1697533705-592 X-HE-Meta: U2FsdGVkX198JpF6HOD9+z/qSKuLT07htTc3n0gLBcebQFLlQGTXtvnKCw328Q6r6rxm/cQ+HT3mBurb4AbSTbXKaKuw/ePuJHHMKkEjxZ2RybjTpLw5RnU4jl07dfdEpMWKbjyBRcnLk0SgHSKytrDzlaB84nZuRfM283q+rukz4u2c7b9eVpxA8YTHn5QAlZYSO3Lv2LJF2ervl0TxSiEUw2jTGu+TiVpDlnMsCYl3x0mQTVkWd4FyVu5lTbHwGQgw528FenDfauGpZRpsjCx2sIOG0cd2DvK75uUKsGfDR5xdkNhCN5e0H8gevjrH3Ss9p7iqS+a/9lqGNyJs1A+psWpnsQlpR7M5xLji0Vr+7KRhN3NTdxaAMUgTNPLBnA4HhgEbNGzF5bKEWZQ5mikRndiWxr3GPt9Gd9AwkLZDGHZ6hURYVLMljRKQZrQjsHgi8hzpzCPu3nVcHXkYrZdhmQ5VHw9SinCEBjn4YzatbwYKtB/Lx3GX5Rm6117rkQk5KZA2iFSO8MquNrY+rcJVB4U7AAt2mmhZH/xIZxp0ZVaC+K94dC+bnSIIjl9KeqBJWtqLHW1+rI1CC5VjWunsVbZI+qPsVRKA+mxewQaZE6jE8DRGs8nUat22ws+oyVBY6cTp/cSQ03xFhVdYVJOOJnAf5WNffePcISD6bxzR+KK8W8lvMsyeLZ4bliXaVe4XvICBO5nQEbUVlmy6JjTxGNFqSYXiT4glILI/AdsozVjIIL/nXModk52WMdfmi6sQ2hYQIb2v0l3u9oGZ0SJ4cTfWdIA3KWA283iIrEeG1OB/X2W3NUo8Zf7ifmb4n76x/EzPMimEwppCEeGwhOPlBpGqXNCAYHCDR7aXMO9Qi4DFX7QxP22EfAj/+LWQxrCBVgZsVIC0jH3e4hEA6qJdSCJZr7GmQbs5tNbV/yiNI37o05VZIoY1Q+aAmvd6uWHwiefMX/YPXfd1Hw0 YIPV4EmN UfiwK8iEoc9IyOTy6vz9au4sbpaTymlFxm3/0aOfSAHVYWz6j7LTHeNxssTrMTKsHrWJYwdkuIF01aaMkNTUKggGe7eZpBJDJL2skLOTF77I5ubz1Qcg58wEQVLLeJxDzDO5qRCPnxOofy1jEVzBeK2/Oj2FnkVYjkI3GWGZbVSOtXdllTBPCzAiGfGino+q2lDDgUfRJbMhNf9gvXxSAWurGfHtaNbMv6Va9CUctfVNsRRR6cCVlNjOm5hyby4zvT+7J82DtYmMlgGl7pWII35QXwe2oN3ojSGDeLDvxxnUuGmpEkXuFTO91UjiL1JIZG+zs+vdCI+MFqo4= 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 mremap(2) can shrink/expand a VMA, or move a VMA to a fixed address and overwriting or existing VMA. Sealing will prevent unintended mremap(2) call. What this patch does: When a mremap(2) is invoked, if one of its VMAs has MM_SEAL_MREMAP set from previous mseal(2) call, this mremap(2) will fail, without any VMA modified. This patch is based on following: 1. At syscall entry point: SYSCALL_DEFINE5(mremap,...) There are two cases: a. going into mremap_to(). b. not going into mremap_to(). 2. For mremap_to() case. Since mremap_to() is called only from SYSCALL_DEFINE5(mremap,..), omit changing signature of mremap_to(), i.e. not passing checkSeals flag. In mremap_to(), it calls can_modify_mm() for src address and dst address (when MREMAP_FIXED is used), before any update is made to the VMAs. 3. For non mremap_to() case. It is still part of SYSCALL_DEFINE5(mremap,...). It calls can_modify_mm() to check sealing in the src address, before any update is made to src VMAs. Check for dest address is not needed, because dest memory is allocated in current mremap(2) call. Signed-off-by: Jeff Xu --- mm/mremap.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/mm/mremap.c b/mm/mremap.c index ac363937f8c4..691fc32d37e4 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -836,7 +836,27 @@ static unsigned long mremap_to(unsigned long addr, unsigned long old_len, if ((mm->map_count + 2) >= sysctl_max_map_count - 3) return -ENOMEM; + /* + * Check src address for sealing. + * + * Note: mremap_to() currently called from one place: + * SYSCALL_DEFINE4(pkey_mprotect, ...) + * and not in any other places. + * Therefore, omit changing the signature of mremap_to() + * Otherwise, we might need to add checkSeals and pass it + * from all callers of mremap_to(). + */ + if (!can_modify_mm(mm, addr, addr + old_len, MM_SEAL_MREMAP)) + return -EACCES; + if (flags & MREMAP_FIXED) { + /* + * Check dest address for sealing. + */ + if (!can_modify_mm(mm, new_addr, new_addr + new_len, + MM_SEAL_MREMAP)) + return -EACCES; + ret = do_munmap(mm, new_addr, new_len, uf_unmap_early); if (ret) goto out; @@ -995,6 +1015,11 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, goto out; } + if (!can_modify_mm(mm, addr, addr + old_len, MM_SEAL_MREMAP)) { + ret = -EACCES; + goto out; + } + /* * Always allow a shrinking remap: that just unmaps * the unnecessary pages.. From patchwork Tue Oct 17 09:08:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13424816 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 6661FCDB474 for ; Tue, 17 Oct 2023 09:08:38 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 3636A8D0101; Tue, 17 Oct 2023 05:08:29 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 312E58D0108; Tue, 17 Oct 2023 05:08:29 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 0FB6C8D0101; Tue, 17 Oct 2023 05:08:29 -0400 (EDT) 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 EE9E68D0101 for ; Tue, 17 Oct 2023 05:08:28 -0400 (EDT) Received: from smtpin01.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id CFF8D1A1032 for ; Tue, 17 Oct 2023 09:08:28 +0000 (UTC) X-FDA: 81354377496.01.503D390 Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) by imf07.hostedemail.com (Postfix) with ESMTP id 0A4454001C for ; Tue, 17 Oct 2023 09:08:26 +0000 (UTC) Authentication-Results: imf07.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=UvJV2IFY; spf=pass (imf07.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.214.179 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=1697533707; 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=y4l+64vDxS/g2eoGFpPCE9LGtKZAVDbLXZ7/tGX4pxw=; b=tdhM3iNrWWW9RfNg+/Mbtf1KMB0yWSGU9JH8BG4oDmKXJE8UWZvXNgoBUhaGaCbbabuHAb iyTdIWWdRaZLaMl7qLxdOX3wpEnrzBXHhNuFQZ49gyjpBMtPWn6H4OUkTy7i7LAcflSf8O zX9zco/JVvsnsK3G4amdrkXOgMSxArI= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1697533707; a=rsa-sha256; cv=none; b=b7hAtMWuz7w0K1ITiA+yia0ceIKyX0mCfNX8iGOJgk1Qa4H/kMJMIyBykf0/U8jcg+NM5W 6/D+Vpk8CMF76fl/J9Vi52Xh1wwL/xTmtOwH1FxXsbdbtyjeCfNfkl9fMlxFJqGRb0q4hP 0S6z5rjTIOVBHks7O7BeaStC5z7hNuE= ARC-Authentication-Results: i=1; imf07.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=UvJV2IFY; spf=pass (imf07.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.214.179 as permitted sender) smtp.mailfrom=jeffxu@chromium.org; dmarc=pass (policy=none) header.from=chromium.org Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-1c0ecb9a075so35841705ad.2 for ; Tue, 17 Oct 2023 02:08:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1697533706; x=1698138506; 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=y4l+64vDxS/g2eoGFpPCE9LGtKZAVDbLXZ7/tGX4pxw=; b=UvJV2IFYOojuMrhBrhtqDao9dIMGp+02pRv+Z4iwgAnPPss9X0HJa2Xkrezer69BlD 16bzbwCt9oPXf0RygcFbMBLZZ/T4wcpO7P0FC0JN6KnQixkMQKJoqGkpujzYWC4GNAkr bbKSrGxM/LjBsLyvxVECwz/AQvOiRhSjd83fI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697533706; x=1698138506; 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=y4l+64vDxS/g2eoGFpPCE9LGtKZAVDbLXZ7/tGX4pxw=; b=DI528JhAOQVyxYjEptVvszyVFXQ1XAfAD0ehZFR70DCRYOvSBfQ0Fn3hYOBajJnnqG nf3yHcgLjPJNBgKomGhVKk3RpD1Z5fvHk+mC0GNtKN2zdi0C3zspyMjtgsQMt7iZzAWc brgdf9T3tkg9hHlEk5kA4cf3TlmU2iROXFn8OIA6eamRRlP0gZw0RJrvGXyLkHwWDtZk jXo8IAUsexabaBYrUcIbAfvWmn9A0RY7JorQ2y0MCjgLvndzvIzNQ/C96q2Pveos3mzL RrYvyG6YmAW294sHEEUaWMU5D0CDnet8Kj6mb/ZuIhQytZRCkvnn6sKGJVkaoo+/nhEp TT5g== X-Gm-Message-State: AOJu0YzyMXWDfN0tN/xcVbz5JQ28Ux2uHZOEhpl+4WSY5cbaLYwkmobI LBS8FpyfVZo7m/2X767TbUQO5A== X-Google-Smtp-Source: AGHT+IH3ijh2spAMvSfaaAyElvlHfpC0/idOO3bXawN0BNxN5uSfUsaSC/pvKljbIONUXHU4GOlTmA== X-Received: by 2002:a17:902:da83:b0:1b2:4852:9a5f with SMTP id j3-20020a170902da8300b001b248529a5fmr1721130plx.54.1697533706010; Tue, 17 Oct 2023 02:08:26 -0700 (PDT) Received: from localhost (9.184.168.34.bc.googleusercontent.com. [34.168.184.9]) by smtp.gmail.com with UTF8SMTPSA id k13-20020a170902760d00b001acae9734c0sm986537pll.266.2023.10.17.02.08.25 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 17 Oct 2023 02:08:25 -0700 (PDT) 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, surenb@google.com, alex.sierra@amd.com, apopple@nvidia.com, aneesh.kumar@linux.ibm.com, axelrasmussen@google.com, ben@decadent.org.uk, catalin.marinas@arm.com, david@redhat.com, dwmw@amazon.co.uk, ying.huang@intel.com, hughd@google.com, joey.gouly@arm.com, corbet@lwn.net, wangkefeng.wang@huawei.com, Liam.Howlett@oracle.com, lstoakes@gmail.com, mawupeng1@huawei.com, linmiaohe@huawei.com, namit@vmware.com, peterx@redhat.com, peterz@infradead.org, ryan.roberts@arm.com, shr@devkernel.io, vbabka@suse.cz, xiujianfeng@huawei.com, yu.ma@intel.com, zhangpeng362@huawei.com, dave.hansen@intel.com, luto@kernel.org, linux-hardening@vger.kernel.org Subject: [RFC PATCH v2 7/8] mseal:Check seal flag for mmap(2) Date: Tue, 17 Oct 2023 09:08:14 +0000 Message-ID: <20231017090815.1067790-8-jeffxu@chromium.org> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog In-Reply-To: <20231017090815.1067790-1-jeffxu@chromium.org> References: <20231017090815.1067790-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 0A4454001C X-Rspam-User: X-Rspamd-Server: rspam11 X-Stat-Signature: r7torw19f3tf9wepq5o65yk63ftcr3wh X-HE-Tag: 1697533706-478768 X-HE-Meta: U2FsdGVkX1+iJkspgFEFbm56xBlilShQf12plf6IOO+JFn+kaYCt35kbME+cLKHh65j70e+j4Mow95dV5zEPsCnWA3wI6Emtnz/MP7RYA2KxGEga6aexCtPzVC1nNK6tAKg0LjHhtCjnyeAnPAdAYMdB2wb7ohdA+LVn2Apaz42r3PrviluHgq9EfV41CoV9TJCuFnBvV25I86QLfBggFnwZFsg2LiSaBvyIrU0xIFpoAbu7QxgQ1kNy61q1ZGPNuHvrzML3uCNrbXpiJbmnWZefyuqABlRU9dnTMaRIIRgnXu079kKqbfz9nAPhC0myPg8et1ZB1SRpM6EFb+ncGGfLraAyiMxlKd/Cth4eYHpGMSVrMfvcyaiVBP11QHJ5ZtI8LHgb0NLwIur+3LPK86mrOJizKlN5hGe71QQ7SIdQqFZ+pt5dTzWOadIuhY84Ntcm0JgioW9/8qwKZuUBlwhHerBZufD7Yc8nd6sMyTZrdFIMgDZCD3pzXJBqEOp+BXaN0d2/6W9NmUP41rJkirXo8xDrfWJRZ0FTNm1t+z1e3OwtkPAbWpFRcjCIl+wuVkBVOX9SkhkD3X0/WMP1HBDUvv3NTFJKp3XXhyeXMWyM1E2cdQbpUXiAQyn+M/tnwH8ej+byBDcQqWE5HfBh5kmyh23ZMsHkm5A5OynqveDF4X5Qu8N2PnljHWoWMqn32HE6ys6C/cFM8SN16xszjN+Q43mciHmv7OQ4MlTFDuIK5arNlOxXYZIgUu1KBZ4BLTGIlqZvhVarEPrEevN57xWEgpU5QhyR3YtpNyQk+YqjoDv8YhZhAoWpcwaKeyUScJvVmu6FOaX98OCkRKq4pWmnjlI2BMDpNTkdgz/pQd3OgFQrQzeSZrRccrkup3atdzRcLFnhYWWWVapcPZKMlAbdgNKReDT0pogy3QBdZotKbjcouyrmysqbhoOHtdon8zcoVEai+8AdLE8mxOA 0Fds9PiJ uinxiXfOLHeppRrls+2RyGBbN/b6U87bUydmg9FVVENLCeHp9s225X9U04LHB+sD74vDkgFYSCV/Is2pM03/Bfx5J2mlgtN5z/5bldJcROornFCTmxZ/9gfrdGAhpdwZi9nPfkS6rPrsEf3u9je9Q7uOLBgkN7qvcx+M9AXr6wIbgENpSCPtIrl8m+XT9CRMi5foVXrsVhqdPDrC988un6ax6hf6XcN0CfcO5WL2F/azwagsQ+85CxqVwjdF3ED7Iel3PFbgtpak6uwLkK0wicVVEDuBu+YYRPGhyrN6qtugpx/6uFUZDQqSmhQ4CjmgnSRtfeB8KpUn8qNk= 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 mmap(2) can change a protection of existing VMAs. Sealing will prevent unintended mmap(2) call. What this patch does: When a mmap(2) is invoked, if one of its VMAs has MM_SEAL_MMAP set from previous mseal(2) call, the mmap(2) will fail, without any VMAs modified. The patch is based on following: There are two cases: with MMU, NO MMU. For MMU case: 1. ksys_mmap_pgoff() currently are called in 2 places: SYSCALL_DEFINE1(old_mmap, ...) SYSCALL_DEFINE6(mmap_pgoff,...) Since both are syscall entry point, omit adding checkSeals in the signature of ksys_mmap_pgoff(). 2. ksys_mmap_pgoff() calls vm_mmap_pgoff() with checkSeals = MM_SEAL_MMAP, in turn, checkSeals flag is passed into do_mmap(), Note: Of all the call paths that goes into do_mmap(), ksys_mmap_pgoff() is the only place where checkSeals = MM_SEAL_MMAP. The rest has checkSeals = 0. 3. In do_mmap(), call can_modify_mm() before any update is maded to the VMAs. For NON-MMU case: Set checkSeals = 0 for all cases. Signed-off-by: Jeff Xu --- fs/aio.c | 5 +++-- include/linux/mm.h | 5 ++++- ipc/shm.c | 3 ++- mm/internal.h | 4 ++-- mm/mmap.c | 22 ++++++++++++++++++---- mm/nommu.c | 6 ++++-- mm/util.c | 8 +++++--- 7 files changed, 38 insertions(+), 15 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index b3174da80ff6..7f4863d0082d 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -557,8 +557,9 @@ static int aio_setup_ring(struct kioctx *ctx, unsigned int nr_events) } ctx->mmap_base = do_mmap(ctx->aio_ring_file, 0, ctx->mmap_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, 0, &unused, NULL); + PROT_READ | PROT_WRITE, MAP_SHARED, 0, &unused, + NULL, 0); + mmap_write_unlock(mm); if (IS_ERR((void *)ctx->mmap_base)) { ctx->mmap_size = 0; diff --git a/include/linux/mm.h b/include/linux/mm.h index f2f316522f2a..9f496c9f2970 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3274,9 +3274,12 @@ extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned lo extern unsigned long mmap_region(struct file *file, unsigned long addr, unsigned long len, vm_flags_t vm_flags, unsigned long pgoff, struct list_head *uf); + extern unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, - unsigned long pgoff, unsigned long *populate, struct list_head *uf); + unsigned long pgoff, unsigned long *populate, struct list_head *uf, + unsigned long checkSeals); + extern int do_vmi_munmap(struct vma_iterator *vmi, struct mm_struct *mm, unsigned long start, size_t len, struct list_head *uf, bool unlock, unsigned long checkSeals); diff --git a/ipc/shm.c b/ipc/shm.c index 60e45e7045d4..3660f522ecba 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -1662,7 +1662,8 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, goto invalid; } - addr = do_mmap(file, addr, size, prot, flags, 0, &populate, NULL); + addr = do_mmap(file, addr, size, prot, flags, 0, &populate, NULL, + 0); *raddr = addr; err = 0; if (IS_ERR_VALUE(addr)) diff --git a/mm/internal.h b/mm/internal.h index d1d4bf4e63c0..2c074d8c6abd 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -800,8 +800,8 @@ extern u64 hwpoison_filter_memcg; extern u32 hwpoison_filter_enable; extern unsigned long __must_check vm_mmap_pgoff(struct file *, unsigned long, - unsigned long, unsigned long, - unsigned long, unsigned long); + unsigned long, unsigned long, unsigned long, unsigned long, + unsigned long checkSeals); extern void set_pageblock_order(void); unsigned long reclaim_pages(struct list_head *folio_list); diff --git a/mm/mmap.c b/mm/mmap.c index 62d592f16f45..edcadd2bb394 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1197,7 +1197,8 @@ static inline bool file_mmap_ok(struct file *file, struct inode *inode, unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long pgoff, - unsigned long *populate, struct list_head *uf) + unsigned long *populate, struct list_head *uf, + unsigned long checkSeals) { struct mm_struct *mm = current->mm; vm_flags_t vm_flags; @@ -1365,6 +1366,9 @@ unsigned long do_mmap(struct file *file, unsigned long addr, vm_flags |= VM_NORESERVE; } + if (!can_modify_mm(mm, addr, addr + len, MM_SEAL_MMAP)) + return -EACCES; + addr = mmap_region(file, addr, len, vm_flags, pgoff, uf); if (!IS_ERR_VALUE(addr) && ((vm_flags & VM_LOCKED) || @@ -1411,7 +1415,17 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, return PTR_ERR(file); } - retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff); + /* + * vm_mmap_pgoff() currently called from two places: + * SYSCALL_DEFINE1(old_mmap, ...) + * SYSCALL_DEFINE6(mmap_pgoff,...) + * and not in any other places. + * Therefore, omit changing the signature of vm_mmap_pgoff() + * Otherwise, we might need to add checkSeals and pass it + * from all callers of vm_mmap_pgoff(). + */ + retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff, + MM_SEAL_MMAP); out_fput: if (file) fput(file); @@ -3016,8 +3030,8 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, flags |= MAP_LOCKED; file = get_file(vma->vm_file); - ret = do_mmap(vma->vm_file, start, size, - prot, flags, pgoff, &populate, NULL); + ret = do_mmap(vma->vm_file, start, size, prot, flags, pgoff, + &populate, NULL, 0); fput(file); out: mmap_write_unlock(mm); diff --git a/mm/nommu.c b/mm/nommu.c index 8dba41cfc44d..dc83651ee777 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1018,7 +1018,8 @@ unsigned long do_mmap(struct file *file, unsigned long flags, unsigned long pgoff, unsigned long *populate, - struct list_head *uf) + struct list_head *uf, + unsigned long checkSeals) { struct vm_area_struct *vma; struct vm_region *region; @@ -1262,7 +1263,8 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, goto out; } - retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff); + retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff, + 0); if (file) fput(file); diff --git a/mm/util.c b/mm/util.c index 4ed8b9b5273c..ca9d8c69267c 100644 --- a/mm/util.c +++ b/mm/util.c @@ -532,7 +532,8 @@ EXPORT_SYMBOL_GPL(account_locked_vm); unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flag, unsigned long pgoff) + unsigned long flag, unsigned long pgoff, + unsigned long checkseals) { unsigned long ret; struct mm_struct *mm = current->mm; @@ -544,7 +545,7 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, if (mmap_write_lock_killable(mm)) return -EINTR; ret = do_mmap(file, addr, len, prot, flag, pgoff, &populate, - &uf); + &uf, checkseals); mmap_write_unlock(mm); userfaultfd_unmap_complete(mm, &uf); if (populate) @@ -562,7 +563,8 @@ unsigned long vm_mmap(struct file *file, unsigned long addr, if (unlikely(offset_in_page(offset))) return -EINVAL; - return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); + return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT, + 0); } EXPORT_SYMBOL(vm_mmap); From patchwork Tue Oct 17 09:08:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13424817 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 A0BE3CDB474 for ; Tue, 17 Oct 2023 09:08:41 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id BA1CB8D010B; Tue, 17 Oct 2023 05:08:30 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id B4F1C8D0108; Tue, 17 Oct 2023 05:08:30 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 97AD98D010A; Tue, 17 Oct 2023 05:08:30 -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 826A08D0108 for ; Tue, 17 Oct 2023 05:08:30 -0400 (EDT) Received: from smtpin18.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 49CC71CBB7C for ; Tue, 17 Oct 2023 09:08:30 +0000 (UTC) X-FDA: 81354377580.18.C70A140 Received: from mail-oa1-f48.google.com (mail-oa1-f48.google.com [209.85.160.48]) by imf10.hostedemail.com (Postfix) with ESMTP id 3CB1EC0012 for ; Tue, 17 Oct 2023 09:08:28 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=hrO9i9Of; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf10.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.160.48 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1697533708; a=rsa-sha256; cv=none; b=kekRFJfLTP3plQ1hqx7HklGcViImdhDz4LPym3mDRr6EFaqQAbMIM/03atIT1TfB/gB0aq 7tIJ5OZUIHNHApzVGtw9pDR56Ni3lp0ekra7NWbnK3+lpmVU6aF0R5j5RKAvRng0XebJ8v 3U8RDPFe0GIrGtPze6BQ+DKKYs5WW/U= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=hrO9i9Of; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf10.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.160.48 as permitted sender) smtp.mailfrom=jeffxu@chromium.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1697533708; 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=Hw+0mxkbjnBoJCM8uU/OaiCIRT4UXTb1F5SYS+HPWzk=; b=oHS70sOhY/MLv62/l58pnfpAFm7JXnEST5qLaXFoLhBkLQzJk1Q3z3y7nYUn/qNDiKCXsW ehbtlLQZUyxpLw0+S1ponl6Xrk21zK/wzD1hUz5mUQvPu0TjK3+2KTXrU0YkkafIVzDBhq qzmOlYtI9xR4Lz7vRtl8HIBz2IV78oc= Received: by mail-oa1-f48.google.com with SMTP id 586e51a60fabf-1e59894d105so3190444fac.1 for ; Tue, 17 Oct 2023 02:08:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1697533707; x=1698138507; 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=Hw+0mxkbjnBoJCM8uU/OaiCIRT4UXTb1F5SYS+HPWzk=; b=hrO9i9OfB9FHe9sx/Je9MXb/drwtqJI6FSHS7HtJI7rXk8v8x59grcUTFEuwCu5CLe /LN2R9tERZxqw1UdrJ4GSPNoZFO9Zo12l0UgJVZz2srHCGTMYVzjGIo0fliw/HZ/i8tC KchoL8uLmO1EecIh8hqKpDXEmijIyBUvDl/ls= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697533707; x=1698138507; 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=Hw+0mxkbjnBoJCM8uU/OaiCIRT4UXTb1F5SYS+HPWzk=; b=q0F+qu6mx57hsoaqAVLESn/QO6VpidDWyY490n+VQB6PK6VO02vIAhXNdWIDqpml8T S74KS2ZDZG6eQePQZ/eZ9T+mkic6AOXTCAzHVWM/3KB5hNgscQCp1UOp8KArgGMtAxx2 JjCX6zaiFSemNZ2G6H8kECxJ9VsnM8T2OHIJO8z416aZwwliGfGIhaQXceu3Sep5+4fs pu58aCmnfAdLPAHZERH3GObwYIKMMPo1hXwGsnh1Pi7G7MPCLS6CFbg4sWs3dpat7Fo2 U/DtlqqezDAgapBd609i4FOUjpWxd3hwV0HsBC4DQfpOylO2BLeWog1CnUgH6WAknnNy hWGw== X-Gm-Message-State: AOJu0Yynq51pNVR4NtBnf8h8I3Pwgv1hQEZzMaIfGDKentkq3Sf429iU /0oqMI5fUeEaJ/QzcjwpKn3XvQ== X-Google-Smtp-Source: AGHT+IFXhSMVGLhauO9iE6Cgr5PhQTBiD3CUppRAftHWUoSBh6pyOmcT1t+6ZwTY+m3LG5c4FLirfw== X-Received: by 2002:a05:6870:1708:b0:1e9:8ab9:11cd with SMTP id h8-20020a056870170800b001e98ab911cdmr1939010oae.45.1697533707066; Tue, 17 Oct 2023 02:08:27 -0700 (PDT) Received: from localhost (9.184.168.34.bc.googleusercontent.com. [34.168.184.9]) by smtp.gmail.com with UTF8SMTPSA id z19-20020a63e113000000b005b7e3eddb87sm946431pgh.61.2023.10.17.02.08.26 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 17 Oct 2023 02:08:26 -0700 (PDT) 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, surenb@google.com, alex.sierra@amd.com, apopple@nvidia.com, aneesh.kumar@linux.ibm.com, axelrasmussen@google.com, ben@decadent.org.uk, catalin.marinas@arm.com, david@redhat.com, dwmw@amazon.co.uk, ying.huang@intel.com, hughd@google.com, joey.gouly@arm.com, corbet@lwn.net, wangkefeng.wang@huawei.com, Liam.Howlett@oracle.com, lstoakes@gmail.com, mawupeng1@huawei.com, linmiaohe@huawei.com, namit@vmware.com, peterx@redhat.com, peterz@infradead.org, ryan.roberts@arm.com, shr@devkernel.io, vbabka@suse.cz, xiujianfeng@huawei.com, yu.ma@intel.com, zhangpeng362@huawei.com, dave.hansen@intel.com, luto@kernel.org, linux-hardening@vger.kernel.org Subject: [RFC PATCH v2 8/8] selftest mm/mseal mprotect/munmap/mremap/mmap Date: Tue, 17 Oct 2023 09:08:15 +0000 Message-ID: <20231017090815.1067790-9-jeffxu@chromium.org> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog In-Reply-To: <20231017090815.1067790-1-jeffxu@chromium.org> References: <20231017090815.1067790-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: 3CB1EC0012 X-Stat-Signature: r3sooz9478xf83czrgtb9oo71toz9jik X-HE-Tag: 1697533708-847474 X-HE-Meta: U2FsdGVkX1/2YguHf8zSsHbrcz2u3p6kWJlUmKKHFIdgFVtIK/+k3BSHmM7V8rEtmuseCPfReoxPSIFllzF9j+VbUre030akFIAzRvbzanlKmhOJXyLGdzxsOBwAD1wp5CubTVXFC5LCysIOla92MQvam952ja/zEIPKRdbut6XFkzeGg332AgzvXR6uigdaO6V8pHXw+JsM7AjIERb5iqGczOxgN0H+iPLw+Zj72kM6jdauTVcIYZbUovQLdBxz8euNrFzVFVsiWYNw1KWGpRMnfQiwI6NozV8UXAJRcbIb0zBSAyhxTV8oyPDgc8FqSKs+hvz1RMFHpKHq5Fib30zP6fr5MrRVPVdbUdka748oDHW53S9OGIVa+fyd3c3MEcEKSZagVBcE7W3iFgQ8ie9Jxu9659l+GBR79OfGl+/MePvmRsFpXIffzyfuQy/r/xkeg+oVjORBxxaalrIiLhdrmAcymhfcW//nuMC/1lxt5AfIthUqjh4dMb+ey4kIQjy/yJbCSEWhLI2AZRDVUsJkE8dqxaYnucsuGFxdFrHPThhqFChZ5qn0vKxS13G63O9qj7b6+NvLqPiRjf9WRZ3cerwfTklT8YAJMV14HzY8MBflR4FvljmvnUJ+Xc53cTWOqBzul/prCard7EeJBX8i2Zh4wucegyeL1lI/Psm0WV0uMRM0RMWsknKu0XWfCI71o676suLnVogPk4n61eOt793njHwynba8KnrCPbCPoCqDskcYZD7alcUedQQJy1EaA7I4RAS+UdjS+YP8ntG5stWe5QL9QQjI25j4jMgMPdMFjdgOgArANHYGelOXJnBu22BWDJXrs1YOVbvN04z7igk2NO6IUm7MWNrTBRfBAUNRK+QiaHH/HJRZgzg3MjC17y/FViaRlwCbMa4Zw2t8Xcb/RRibT4IqiuyyUqiP01E4U0nzFWc6jM/gesq4yvLY2OkPGtnKPn7j+W8 IYDerjeW U0W0GfU+iAgKk+PC9/S/vNKZVhGSbBOQQ1a7gzVUt8Pozyv/BjFlI1c9CF+GUG6MQwsXRp9gMZRDBzgfdgE0zPdYXAyZyxW9IL/l5ZUqo0lO98ktZqWpj1DVFGhpA3yGsQyZB1YCbzflX9L2qxlag0afHwkY/LQNDdPgNFlb73/0h8UOWMETmDTTq6/VM04avBb4NnJ3u7iBaOuK3tt1Y8NDhXwN9/eSsQHb/+Oib2+hdNe174e6KqbgT/9Q9Hh/GfOvLbApB3d0AP78BdlZmiy07uoHtLFDFzbrSStiX2+NJBEWzpz23GJYg+E07rPpjcxPr 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 selftest for sealing mprotect/munmap/mremap/mmap Signed-off-by: Jeff Xu --- tools/testing/selftests/mm/Makefile | 1 + tools/testing/selftests/mm/mseal_test.c | 1428 +++++++++++++++++++++++ 2 files changed, 1429 insertions(+) create mode 100644 tools/testing/selftests/mm/mseal_test.c diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile index 6a9fc5693145..0c086cecc093 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -59,6 +59,7 @@ TEST_GEN_FILES += mlock2-tests TEST_GEN_FILES += mrelease_test TEST_GEN_FILES += mremap_dontunmap TEST_GEN_FILES += mremap_test +TEST_GEN_FILES += mseal_test TEST_GEN_FILES += on-fault-limit TEST_GEN_FILES += thuge-gen TEST_GEN_FILES += transhuge-stress diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c new file mode 100644 index 000000000000..d6ae09729394 --- /dev/null +++ b/tools/testing/selftests/mm/mseal_test.c @@ -0,0 +1,1428 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include "../kselftest.h" +#include +#include +#include +#include +#include + +#ifndef MM_SEAL_MSEAL +#define MM_SEAL_MSEAL 0x1 +#endif + +#ifndef MM_SEAL_MPROTECT +#define MM_SEAL_MPROTECT 0x2 +#endif + +#ifndef MM_SEAL_MUNMAP +#define MM_SEAL_MUNMAP 0x4 +#endif + +#ifndef MM_SEAL_MMAP +#define MM_SEAL_MMAP 0x8 +#endif + +#ifndef MM_SEAL_MREMAP +#define MM_SEAL_MREMAP 0x10 +#endif + +#ifndef DEBUG +#define LOG_TEST_ENTER() {} +#else +#define LOG_TEST_ENTER() { printf("%s\n", __func__); } +#endif + +static int sys_mseal(void *start, size_t len, int types) +{ + int sret; + + errno = 0; + sret = syscall(__NR_mseal, start, len, types, 0); + return sret; +} + +int sys_mprotect(void *ptr, size_t size, unsigned long prot) +{ + int sret; + + errno = 0; + sret = syscall(SYS_mprotect, ptr, size, prot); + return sret; +} + +int sys_munmap(void *ptr, size_t size) +{ + int sret; + + errno = 0; + sret = syscall(SYS_munmap, ptr, size); + return sret; +} + +static int sys_madvise(void *start, size_t len, int types) +{ + int sret; + + errno = 0; + sret = syscall(__NR_madvise, start, len, types); + return sret; +} + +void *addr1 = (void *)0x50000000; +void *addr2 = (void *)0x50004000; +void *addr3 = (void *)0x50008000; +void setup_single_address(int size, void **ptrOut) +{ + void *ptr; + + ptr = mmap(NULL, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + assert(ptr != (void *)-1); + *ptrOut = ptr; +} + +void setup_single_fixed_address(int size, void **ptrOut) +{ + void *ptr; + + ptr = mmap(addr1, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + assert(ptr == (void *)addr1); + + *ptrOut = ptr; +} + +void clean_single_address(void *ptr, int size) +{ + int ret; + + ret = munmap(ptr, size); + assert(!ret); +} + +void seal_mprotect_single_address(void *ptr, int size) +{ + int ret; + + ret = sys_mseal(ptr, size, MM_SEAL_MPROTECT); + assert(!ret); +} + +static void test_seal_addseals(void) +{ + LOG_TEST_ENTER(); + int ret; + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + + setup_single_address(size, &ptr); + + /* adding seal one by one */ + ret = sys_mseal(ptr, size, MM_SEAL_MPROTECT); + assert(!ret); + + ret = sys_mseal(ptr, size, MM_SEAL_MMAP); + assert(!ret); + + ret = sys_mseal(ptr, size, MM_SEAL_MREMAP); + assert(!ret); + + ret = sys_mseal(ptr, size, MM_SEAL_MSEAL); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_addseals_combined(void) +{ + LOG_TEST_ENTER(); + int ret; + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + + setup_single_address(size, &ptr); + + ret = sys_mseal(ptr, size, MM_SEAL_MPROTECT); + assert(!ret); + + /* adding multiple seals */ + ret = sys_mseal(ptr, size, + MM_SEAL_MPROTECT | MM_SEAL_MMAP | MM_SEAL_MREMAP | + MM_SEAL_MSEAL); + assert(!ret); + + /* not adding more seal type, so ok. */ + ret = sys_mseal(ptr, size, + MM_SEAL_MMAP | MM_SEAL_MREMAP | MM_SEAL_MSEAL); + assert(!ret); + + /* not adding more seal type, so ok. */ + ret = sys_mseal(ptr, size, MM_SEAL_MSEAL); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_addseals_reject(void) +{ + LOG_TEST_ENTER(); + int ret; + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + + setup_single_address(size, &ptr); + + ret = sys_mseal(ptr, size, MM_SEAL_MPROTECT | MM_SEAL_MSEAL); + assert(!ret); + + ret = sys_mseal(ptr, size, MM_SEAL_MPROTECT); + assert(!ret); + + /* MM_SEAL_MSEAL is set, so not allow new seal type . */ + ret = sys_mseal(ptr, size, + MM_SEAL_MPROTECT | MM_SEAL_MMAP | MM_SEAL_MSEAL); + assert(ret < 0); + + ret = sys_mseal(ptr, size, MM_SEAL_MMAP); + assert(ret < 0); + + ret = sys_mseal(ptr, size, MM_SEAL_MMAP | MM_SEAL_MSEAL); + assert(ret < 0); + + clean_single_address(ptr, size); +} + +static void test_seal_unmapped_start(void) +{ + LOG_TEST_ENTER(); + int ret; + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + + setup_single_address(size, &ptr); + + // munmap 2 pages from ptr. + ret = sys_munmap(ptr, 2 * page_size); + assert(!ret); + + // mprotect will fail because 2 pages from ptr are unmapped. + ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); + assert(ret < 0); + + // mseal will fail because 2 pages from ptr are unmapped. + ret = sys_mseal(ptr, size, MM_SEAL_MSEAL); + assert(ret < 0); + + ret = sys_mseal(ptr + 2 * page_size, 2 * page_size, MM_SEAL_MSEAL); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_unmapped_middle(void) +{ + LOG_TEST_ENTER(); + int ret; + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + + setup_single_address(size, &ptr); + + // munmap 2 pages from ptr + page. + ret = sys_munmap(ptr + page_size, 2 * page_size); + assert(!ret); + + // mprotect will fail, since size is 4 pages. + ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); + assert(ret < 0); + + // mseal will fail as well. + ret = sys_mseal(ptr, size, MM_SEAL_MSEAL); + assert(ret < 0); + + /* we still can add seal to the first page and last page*/ + ret = sys_mseal(ptr, page_size, MM_SEAL_MSEAL | MM_SEAL_MPROTECT); + assert(!ret); + + ret = sys_mseal(ptr + 3 * page_size, page_size, + MM_SEAL_MSEAL | MM_SEAL_MPROTECT); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_unmapped_end(void) +{ + LOG_TEST_ENTER(); + int ret; + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + + setup_single_address(size, &ptr); + + // unmap last 2 pages. + ret = sys_munmap(ptr + 2 * page_size, 2 * page_size); + assert(!ret); + + //mprotect will fail since last 2 pages are unmapped. + ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); + assert(ret < 0); + + //mseal will fail as well. + ret = sys_mseal(ptr, size, MM_SEAL_MSEAL); + assert(ret < 0); + + /* The first 2 pages is not sealed, and can add seals */ + ret = sys_mseal(ptr, 2 * page_size, MM_SEAL_MSEAL | MM_SEAL_MPROTECT); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_multiple_vmas(void) +{ + LOG_TEST_ENTER(); + int ret; + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + + setup_single_address(size, &ptr); + + // use mprotect to split the vma into 3. + ret = sys_mprotect(ptr + page_size, 2 * page_size, + PROT_READ | PROT_WRITE); + assert(!ret); + + // mprotect will get applied to all 4 pages - 3 VMAs. + ret = sys_mprotect(ptr, size, PROT_READ); + assert(!ret); + + // use mprotect to split the vma into 3. + ret = sys_mprotect(ptr + page_size, 2 * page_size, + PROT_READ | PROT_WRITE); + assert(!ret); + + // mseal get applied to all 4 pages - 3 VMAs. + ret = sys_mseal(ptr, size, MM_SEAL_MSEAL); + assert(!ret); + + // verify additional seal type will fail after MM_SEAL_MSEAL set. + ret = sys_mseal(ptr, page_size, MM_SEAL_MSEAL | MM_SEAL_MPROTECT); + assert(ret < 0); + + ret = sys_mseal(ptr + page_size, 2 * page_size, + MM_SEAL_MSEAL | MM_SEAL_MPROTECT); + assert(ret < 0); + + ret = sys_mseal(ptr + 3 * page_size, page_size, + MM_SEAL_MSEAL | MM_SEAL_MPROTECT); + assert(ret < 0); + + clean_single_address(ptr, size); +} + +static void test_seal_split_start(void) +{ + LOG_TEST_ENTER(); + int ret; + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + + setup_single_address(size, &ptr); + + /* use mprotect to split at middle */ + ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE); + assert(!ret); + + /* seal the first page, this will split the VMA */ + ret = sys_mseal(ptr, page_size, MM_SEAL_MSEAL); + assert(!ret); + + /* can't add seal to the first page */ + ret = sys_mseal(ptr, page_size, MM_SEAL_MSEAL | MM_SEAL_MPROTECT); + assert(ret < 0); + + /* add seal to the remain 3 pages */ + ret = sys_mseal(ptr + page_size, 3 * page_size, + MM_SEAL_MSEAL | MM_SEAL_MPROTECT); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_split_end(void) +{ + LOG_TEST_ENTER(); + int ret; + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + + setup_single_fixed_address(size, &ptr); + + /* use mprotect to split at middle */ + ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE); + assert(!ret); + + /* seal the last page */ + ret = sys_mseal(ptr + 3 * page_size, page_size, MM_SEAL_MSEAL); + assert(!ret); + + /* adding seal to the last page is rejected. */ + ret = sys_mseal(ptr + 3 * page_size, page_size, + MM_SEAL_MSEAL | MM_SEAL_MPROTECT); + assert(ret < 0); + + /* Adding seals to the first 3 pages */ + ret = sys_mseal(ptr, 3 * page_size, MM_SEAL_MSEAL | MM_SEAL_MPROTECT); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_invalid_input(void) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_fixed_address(size, &ptr); + + /* invalid flag */ + ret = sys_mseal(ptr, size, 0x20); + assert(ret < 0); + + ret = sys_mseal(ptr, size, 0x31); + assert(ret < 0); + + ret = sys_mseal(ptr, size, 0x3F); + assert(ret < 0); + + /* unaligned address */ + ret = sys_mseal(ptr + 1, 2 * page_size, MM_SEAL_MSEAL); + assert(ret < 0); + + /* length too big */ + ret = sys_mseal(ptr, 5 * page_size, MM_SEAL_MSEAL); + assert(ret < 0); + + /* start is not in a valid VMA */ + ret = sys_mseal(ptr - page_size, 5 * page_size, MM_SEAL_MSEAL); + assert(ret < 0); + + clean_single_address(ptr, size); +} + +static void test_seal_zero_length(void) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + ret = sys_mprotect(ptr, 0, PROT_READ | PROT_WRITE); + assert(!ret); + + /* seal 0 length will be OK, same as mprotect */ + ret = sys_mseal(ptr, 0, MM_SEAL_MPROTECT); + assert(!ret); + + // verify the 4 pages are not sealed by previous call. + ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_twice(void) +{ + LOG_TEST_ENTER(); + int ret; + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + + setup_single_address(size, &ptr); + + ret = sys_mseal(ptr, size, MM_SEAL_MPROTECT); + assert(!ret); + + // apply the same seal will be OK. idempotent. + ret = sys_mseal(ptr, size, MM_SEAL_MPROTECT); + assert(!ret); + + ret = sys_mseal(ptr, size, + MM_SEAL_MPROTECT | MM_SEAL_MMAP | MM_SEAL_MREMAP | + MM_SEAL_MSEAL); + assert(!ret); + + ret = sys_mseal(ptr, size, + MM_SEAL_MPROTECT | MM_SEAL_MMAP | MM_SEAL_MREMAP | + MM_SEAL_MSEAL); + assert(!ret); + + ret = sys_mseal(ptr, size, MM_SEAL_MSEAL); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_mprotect(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + if (seal) + seal_mprotect_single_address(ptr, size); + + ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); + if (seal) + assert(ret < 0); + else + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_start_mprotect(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + if (seal) + seal_mprotect_single_address(ptr, page_size); + + // the first page is sealed. + ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); + if (seal) + assert(ret < 0); + else + assert(!ret); + + // pages after the first page is not sealed. + ret = sys_mprotect(ptr + page_size, page_size * 3, + PROT_READ | PROT_WRITE); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_end_mprotect(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + if (seal) + seal_mprotect_single_address(ptr + page_size, 3 * page_size); + + /* first page is not sealed */ + ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); + assert(!ret); + + /* last 3 page are sealed */ + ret = sys_mprotect(ptr + page_size, page_size * 3, + PROT_READ | PROT_WRITE); + if (seal) + assert(ret < 0); + else + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_mprotect_unalign_len(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + if (seal) + seal_mprotect_single_address(ptr, page_size * 2 - 1); + + // 2 pages are sealed. + ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); + if (seal) + assert(ret < 0); + else + assert(!ret); + + ret = sys_mprotect(ptr + page_size * 2, page_size, + PROT_READ | PROT_WRITE); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_mprotect_unalign_len_variant_2(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + if (seal) + seal_mprotect_single_address(ptr, page_size * 2 + 1); + + // 3 pages are sealed. + ret = sys_mprotect(ptr, page_size * 3, PROT_READ | PROT_WRITE); + if (seal) + assert(ret < 0); + else + assert(!ret); + + ret = sys_mprotect(ptr + page_size * 3, page_size, + PROT_READ | PROT_WRITE); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_mprotect_two_vma(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + /* use mprotect to split */ + ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); + assert(!ret); + + if (seal) + seal_mprotect_single_address(ptr, page_size * 4); + + ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); + if (seal) + assert(ret < 0); + else + assert(!ret); + + ret = sys_mprotect(ptr + page_size * 2, page_size * 2, + PROT_READ | PROT_WRITE); + if (seal) + assert(ret < 0); + else + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_mprotect_two_vma_with_split(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + // use mprotect to split as two vma. + ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); + assert(!ret); + + // mseal can apply across 2 vma, also split them. + if (seal) + seal_mprotect_single_address(ptr + page_size, page_size * 2); + + // the first page is not sealed. + ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); + assert(!ret); + + // the second page is sealed. + ret = sys_mprotect(ptr + page_size, page_size, PROT_READ | PROT_WRITE); + if (seal) + assert(ret < 0); + else + assert(!ret); + + // the third page is sealed. + ret = sys_mprotect(ptr + 2 * page_size, page_size, + PROT_READ | PROT_WRITE); + if (seal) + assert(ret < 0); + else + assert(!ret); + + // the fouth page is not sealed. + ret = sys_mprotect(ptr + 3 * page_size, page_size, + PROT_READ | PROT_WRITE); + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_mprotect_partial_mprotect(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + // seal one page. + if (seal) + seal_mprotect_single_address(ptr, page_size); + + // mprotect first 2 page will fail, since the first page are sealed. + ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE); + if (seal) + assert(ret < 0); + else + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_mprotect_two_vma_with_gap(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + // use mprotect to split. + ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); + assert(!ret); + + // use mprotect to split. + ret = sys_mprotect(ptr + 3 * page_size, page_size, + PROT_READ | PROT_WRITE); + assert(!ret); + + // use munmap to free two pages in the middle + ret = sys_munmap(ptr + page_size, 2 * page_size); + assert(!ret); + + // mprotect will fail, because there is a gap in the address. + // notes, internally mprotect still updated the first page. + ret = sys_mprotect(ptr, 4 * page_size, PROT_READ); + assert(ret < 0); + + // mseal will fail as well. + ret = sys_mseal(ptr, 4 * page_size, MM_SEAL_MPROTECT); + assert(ret < 0); + + // unlike mprotect, the first page is not sealed. + ret = sys_mprotect(ptr, page_size, PROT_READ); + assert(ret == 0); + + // the last page is not sealed. + ret = sys_mprotect(ptr + 3 * page_size, page_size, PROT_READ); + assert(ret == 0); + + clean_single_address(ptr, size); +} + +static void test_seal_mprotect_split(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + //use mprotect to split. + ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); + assert(!ret); + + //seal all 4 pages. + if (seal) { + ret = sys_mseal(ptr, 4 * page_size, MM_SEAL_MPROTECT); + assert(!ret); + } + + //madvice is OK. + ret = sys_madvise(ptr, page_size * 2, MADV_WILLNEED); + assert(!ret); + + //mprotect is sealed. + ret = sys_mprotect(ptr, 2 * page_size, PROT_READ); + if (seal) + assert(ret < 0); + else + assert(!ret); + + + ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ); + if (seal) + assert(ret < 0); + else + assert(!ret); + + clean_single_address(ptr, size); +} + +static void test_seal_mprotect_merge(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + // use mprotect to split one page. + ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); + assert(!ret); + + // seal first two pages. + if (seal) { + ret = sys_mseal(ptr, 2 * page_size, MM_SEAL_MPROTECT); + assert(!ret); + } + + ret = sys_madvise(ptr, page_size, MADV_WILLNEED); + assert(!ret); + + // 2 pages are sealed. + ret = sys_mprotect(ptr, 2 * page_size, PROT_READ); + if (seal) + assert(ret < 0); + else + assert(!ret); + + // last 2 pages are not sealed. + ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ); + assert(ret == 0); + + clean_single_address(ptr, size); +} + +static void test_seal_munmap(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + if (seal) { + ret = sys_mseal(ptr, size, MM_SEAL_MUNMAP); + assert(!ret); + } + + // 4 pages are sealed. + ret = sys_munmap(ptr, size); + if (seal) + assert(ret < 0); + else + assert(!ret); +} + +/* + * allocate 4 pages, + * use mprotect to split it as two VMAs + * seal the whole range + * munmap will fail on both + */ +static void test_seal_munmap_two_vma(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + /* use mprotect to split */ + ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); + assert(!ret); + + if (seal) { + ret = sys_mseal(ptr, size, MM_SEAL_MUNMAP); + assert(!ret); + } + + ret = sys_munmap(ptr, page_size * 2); + if (seal) + assert(ret < 0); + else + assert(!ret); + + ret = sys_munmap(ptr + page_size, page_size * 2); + if (seal) + assert(ret < 0); + else + assert(!ret); +} + +/* + * allocate a VMA with 4 pages. + * munmap the middle 2 pages. + * seal the whole 4 pages, will fail. + * note: one of the pages are sealed + * munmap the first page will be OK. + * munmap the last page will be OK. + */ +static void test_seal_munmap_vma_with_gap(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + ret = sys_munmap(ptr + page_size, page_size * 2); + assert(!ret); + + if (seal) { + // can't have gap in the middle. + ret = sys_mseal(ptr, size, MM_SEAL_MUNMAP); + assert(ret < 0); + } + + ret = sys_munmap(ptr, page_size); + assert(!ret); + + ret = sys_munmap(ptr + page_size * 2, page_size); + assert(!ret); + + ret = sys_munmap(ptr, size); + assert(!ret); +} + +static void test_munmap_start_freed(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + + // unmap the first page. + ret = sys_munmap(ptr, page_size); + assert(!ret); + + // seal the last 3 pages. + if (seal) { + ret = sys_mseal(ptr + page_size, 3 * page_size, MM_SEAL_MUNMAP); + assert(!ret); + } + + // unmap from the first page. + ret = sys_munmap(ptr, size); + if (seal) { + assert(ret < 0); + + // use mprotect to verify page is not unmapped. + ret = sys_mprotect(ptr + page_size, 3 * page_size, PROT_READ); + assert(!ret); + } else + // note: this will be OK, even the first page is + // already unmapped. + assert(!ret); +} + +static void test_munmap_end_freed(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + // unmap last page. + ret = sys_munmap(ptr + page_size * 3, page_size); + assert(!ret); + + // seal the first 3 pages. + if (seal) { + ret = sys_mseal(ptr, 3 * page_size, MM_SEAL_MUNMAP); + assert(!ret); + } + + // unmap all pages. + ret = sys_munmap(ptr, size); + if (seal) { + assert(ret < 0); + + // use mprotect to verify page is not unmapped. + ret = sys_mprotect(ptr, 3 * page_size, PROT_READ); + assert(!ret); + } else + assert(!ret); +} + +static void test_munmap_middle_freed(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + + setup_single_address(size, &ptr); + // unmap 2 pages in the middle. + ret = sys_munmap(ptr + page_size, page_size * 2); + assert(!ret); + + // seal the first page. + if (seal) { + ret = sys_mseal(ptr, page_size, MM_SEAL_MUNMAP); + assert(!ret); + } + + // munmap all 4 pages. + ret = sys_munmap(ptr, size); + if (seal) { + assert(ret < 0); + + // use mprotect to verify page is not unmapped. + ret = sys_mprotect(ptr, page_size, PROT_READ); + assert(!ret); + } else + assert(!ret); +} + +void test_seal_mremap_shrink(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + void *ret2; + + setup_single_address(size, &ptr); + + if (seal) { + ret = sys_mseal(ptr, size, MM_SEAL_MREMAP); + assert(!ret); + } + + // shrink from 4 pages to 2 pages. + ret2 = mremap(ptr, size, 2 * page_size, 0, 0); + if (seal) { + assert(ret2 == MAP_FAILED); + assert(errno == EACCES); + } else { + assert(ret2 != MAP_FAILED); + clean_single_address(ret2, 2 * page_size); + } + clean_single_address(ptr, size); +} + +void test_seal_mremap_expand(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + void *ret2; + + setup_single_address(size, &ptr); + // ummap last 2 pages. + ret = sys_munmap(ptr + 2 * page_size, 2 * page_size); + assert(!ret); + + if (seal) { + ret = sys_mseal(ptr, 2 * page_size, MM_SEAL_MREMAP); + assert(!ret); + } + + // expand from 2 page to 4 pages. + ret2 = mremap(ptr, 2 * page_size, 4 * page_size, 0, 0); + if (seal) { + assert(ret2 == MAP_FAILED); + assert(errno == EACCES); + } else { + assert(ret2 == ptr); + clean_single_address(ret2, 4 * page_size); + } + clean_single_address(ptr, size); +} + +void test_seal_mremap_move(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = page_size; + int ret; + void *ret2; + + setup_single_address(size, &ptr); + if (seal) { + ret = sys_mseal(ptr, size, MM_SEAL_MREMAP); + assert(!ret); + } + + // move from ptr to fixed address. + ret2 = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, addr1); + if (seal) { + assert(ret2 == MAP_FAILED); + assert(errno == EACCES); + } else { + assert(ret2 != MAP_FAILED); + clean_single_address(ret2, size); + } + clean_single_address(ptr, size); +} + +void test_seal_mmap_overwrite_prot(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = page_size; + int ret; + void *ret2; + + setup_single_address(size, &ptr); + + if (seal) { + ret = sys_mseal(ptr, size, MM_SEAL_MMAP); + assert(!ret); + } + + // use mmap to change protection. + ret2 = mmap(ptr, size, PROT_NONE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + if (seal) { + assert(ret2 == MAP_FAILED); + assert(errno == EACCES); + } else + assert(ret2 == ptr); + + clean_single_address(ptr, size); +} + +void test_seal_mremap_shrink_fixed(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + void *newAddr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + void *ret2; + + setup_single_address(size, &ptr); + setup_single_fixed_address(size, &newAddr); + + if (seal) { + ret = sys_mseal(ptr, size, MM_SEAL_MREMAP); + assert(!ret); + } + + // mremap to move and shrink to fixed address + ret2 = mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED, + newAddr); + if (seal) { + assert(ret2 == MAP_FAILED); + assert(errno == EACCES); + } else + assert(ret2 == newAddr); + + clean_single_address(ptr, size); + clean_single_address(newAddr, size); +} + +void test_seal_mremap_expand_fixed(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + void *newAddr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + void *ret2; + + setup_single_address(page_size, &ptr); + setup_single_fixed_address(size, &newAddr); + + if (seal) { + ret = sys_mseal(newAddr, size, MM_SEAL_MREMAP); + assert(!ret); + } + + // mremap to move and expand to fixed address + ret2 = mremap(ptr, page_size, size, MREMAP_MAYMOVE | MREMAP_FIXED, + newAddr); + if (seal) { + assert(ret2 == MAP_FAILED); + assert(errno == EACCES); + } else + assert(ret2 == newAddr); + + clean_single_address(ptr, page_size); + clean_single_address(newAddr, size); +} + +void test_seal_mremap_move_fixed(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + void *newAddr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + void *ret2; + + setup_single_address(size, &ptr); + setup_single_fixed_address(size, &newAddr); + + if (seal) { + ret = sys_mseal(newAddr, size, MM_SEAL_MREMAP); + assert(!ret); + } + + // mremap to move to fixed address + ret2 = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newAddr); + if (seal) { + assert(ret2 == MAP_FAILED); + assert(errno == EACCES); + } else + assert(ret2 == newAddr); + + clean_single_address(ptr, page_size); + clean_single_address(newAddr, size); +} + +void test_seal_mremap_move_fixed_zero(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + void *newAddr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + void *ret2; + + setup_single_address(size, &ptr); + + if (seal) { + ret = sys_mseal(ptr, size, MM_SEAL_MREMAP); + assert(!ret); + } + + /* + * MREMAP_FIXED can move the mapping to zero address + */ + ret2 = mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED, + 0); + if (seal) { + assert(ret2 == MAP_FAILED); + assert(errno == EACCES); + } else { + assert(ret2 == 0); + clean_single_address(ret2, 2 * page_size); + } + clean_single_address(ptr, size); +} + +void test_seal_mremap_move_dontunmap(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + void *newAddr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + void *ret2; + + setup_single_address(size, &ptr); + + if (seal) { + ret = sys_mseal(ptr, size, MM_SEAL_MREMAP); + assert(!ret); + } + + // mremap to move, and don't unmap src addr. + ret2 = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, 0); + if (seal) { + assert(ret2 == MAP_FAILED); + assert(errno == EACCES); + } else { + assert(ret2 != MAP_FAILED); + clean_single_address(ret2, size); + } + + clean_single_address(ptr, page_size); +} + +void test_seal_mremap_move_dontunmap_anyaddr(bool seal) +{ + LOG_TEST_ENTER(); + void *ptr; + void *newAddr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + void *ret2; + + setup_single_address(size, &ptr); + + if (seal) { + ret = sys_mseal(ptr, size, MM_SEAL_MREMAP); + assert(!ret); + } + + /* + * The 0xdeaddead should not have effect on dest addr + * when MREMAP_DONTUNMAP is set. + */ + ret2 = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, + 0xdeaddead); + if (seal) { + assert(ret2 == MAP_FAILED); + assert(errno == EACCES); + } else { + assert(ret2 != MAP_FAILED); + assert((long)ret2 != 0xdeaddead); + clean_single_address(ret2, size); + } + + clean_single_address(ptr, page_size); +} + +int main(int argc, char **argv) +{ + test_seal_invalid_input(); + test_seal_addseals(); + test_seal_addseals_combined(); + test_seal_addseals_reject(); + test_seal_unmapped_start(); + test_seal_unmapped_middle(); + test_seal_unmapped_end(); + test_seal_multiple_vmas(); + test_seal_split_start(); + test_seal_split_end(); + + test_seal_zero_length(); + test_seal_twice(); + + test_seal_mprotect(false); + test_seal_mprotect(true); + + test_seal_start_mprotect(false); + test_seal_start_mprotect(true); + + test_seal_end_mprotect(false); + test_seal_end_mprotect(true); + + test_seal_mprotect_unalign_len(false); + test_seal_mprotect_unalign_len(true); + + test_seal_mprotect_unalign_len_variant_2(false); + test_seal_mprotect_unalign_len_variant_2(true); + + test_seal_mprotect_two_vma(false); + test_seal_mprotect_two_vma(true); + + test_seal_mprotect_two_vma_with_split(false); + test_seal_mprotect_two_vma_with_split(true); + + test_seal_mprotect_partial_mprotect(false); + test_seal_mprotect_partial_mprotect(true); + + test_seal_mprotect_two_vma_with_gap(false); + test_seal_mprotect_two_vma_with_gap(true); + + test_seal_mprotect_merge(false); + test_seal_mprotect_merge(true); + + test_seal_mprotect_split(false); + test_seal_mprotect_split(true); + + test_seal_munmap(false); + test_seal_munmap(true); + test_seal_munmap_two_vma(false); + test_seal_munmap_two_vma(true); + test_seal_munmap_vma_with_gap(false); + test_seal_munmap_vma_with_gap(true); + + test_munmap_start_freed(false); + test_munmap_start_freed(true); + test_munmap_middle_freed(false); + test_munmap_middle_freed(true); + test_munmap_end_freed(false); + test_munmap_end_freed(true); + + test_seal_mremap_shrink(false); + test_seal_mremap_shrink(true); + test_seal_mremap_expand(false); + test_seal_mremap_expand(true); + test_seal_mremap_move(false); + test_seal_mremap_move(true); + + test_seal_mremap_shrink_fixed(false); + test_seal_mremap_shrink_fixed(true); + test_seal_mremap_expand_fixed(false); + test_seal_mremap_expand_fixed(true); + test_seal_mremap_move_fixed(false); + test_seal_mremap_move_fixed(true); + test_seal_mremap_move_dontunmap(false); + test_seal_mremap_move_dontunmap(true); + test_seal_mremap_move_fixed_zero(false); + test_seal_mremap_move_fixed_zero(true); + test_seal_mremap_move_dontunmap_anyaddr(false); + test_seal_mremap_move_dontunmap_anyaddr(true); + + test_seal_mmap_overwrite_prot(false); + test_seal_mmap_overwrite_prot(true); + + printf("OK\n"); + return 0; +}