From patchwork Mon Oct 16 14:38:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 13423493 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 CA36CCDB465 for ; Mon, 16 Oct 2023 14:39:01 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 171138D00A6; Mon, 16 Oct 2023 10:39:01 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 0F81B8D0001; Mon, 16 Oct 2023 10:39:00 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id DA2098D00A6; Mon, 16 Oct 2023 10:39:00 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id C14558D0001 for ; Mon, 16 Oct 2023 10:39:00 -0400 (EDT) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id 80F1C407C7 for ; Mon, 16 Oct 2023 14:39:00 +0000 (UTC) X-FDA: 81351581640.15.6C31484 Received: from mail-oo1-f41.google.com (mail-oo1-f41.google.com [209.85.161.41]) by imf25.hostedemail.com (Postfix) with ESMTP id 6E9B5A0020 for ; Mon, 16 Oct 2023 14:38:58 +0000 (UTC) Authentication-Results: imf25.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=elro8LSF; spf=pass (imf25.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.161.41 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=1697467138; 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=i0WNNc5z5Rp4qcc+bUjy2EO5P5kIEIYGxWQPd2Onn9M=; b=hOKT0ap0xEAy+ujarZaUYji96SMhSf+W0QCrhlRmTl+eZZLHx0KE9Qzet8U6WAGFaxBzv7 rXTixJaMsVAsplP6ilS5ws0Bv/4maVxL4FjAuHlj9yLOa8RVKhWg74Ab+oS7hJvI0ljg+r bpKOU7cLa6hC/b+bvu3jedU7C3gaWVk= ARC-Authentication-Results: i=1; imf25.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=elro8LSF; spf=pass (imf25.hostedemail.com: domain of jeffxu@chromium.org designates 209.85.161.41 as permitted sender) smtp.mailfrom=jeffxu@chromium.org; dmarc=pass (policy=none) header.from=chromium.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1697467138; a=rsa-sha256; cv=none; b=r3FtBdouIEkP7kUW+jcyP21AEPky4nObYprRLSiZimfg1w9KZJY6vo6SqyXQRAfuXctUIi egTp6x8cRGJcH9X1SEfVP3XRJsM9OiI3iEJbTnK0wCh0nTrTzxbguuyDwPb+0CqHws656r CDwosAwdooOasKqNVS3J/vEEhAGlBnU= Received: by mail-oo1-f41.google.com with SMTP id 006d021491bc7-57babef76deso2587437eaf.0 for ; Mon, 16 Oct 2023 07:38:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1697467137; x=1698071937; 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=i0WNNc5z5Rp4qcc+bUjy2EO5P5kIEIYGxWQPd2Onn9M=; b=elro8LSFn5NBI6XGtX1nz/sUqcgVY34O4PT3GaMUYGtbgJXe7FPcBXNow7rmin+4d8 bT8uX23hOU9J/jMAZLuWYzYLX1YbHwulYVsjumUfOB3rKraUatu242K24uyfOmT0m0MX 7eCPuLZAfuX9Ep9C1mBl01uAxD4KV7nLyrHSU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697467137; x=1698071937; 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=i0WNNc5z5Rp4qcc+bUjy2EO5P5kIEIYGxWQPd2Onn9M=; b=O/bugjNmU3rgPOXPz5Wp+CGm8Wda09T/cdmZcC6lX0XQhX83bH1pwUTY/kvP6FP7uy u9k5XV2zysr/axDKt5+Ei7rKO8YoSWGBDdNFIGvS39br2B7O9QNWpbp76ClFFyxug23Z ONauO4nqvjyAuOgI96rum2tqiPO0wvEno8fnaIVQkFR1koKY7PjcFL/ykrS44PV9Xbvf E3mDY8WERmcs/R6fJ8r3R0t1LO700jPJJ6LhL745n0SuX92w0mQMmtbFw+fGI3stVoIi nQlvD4O98rFN1P/mScc7s12qPFVB7tr7JcSvtGt4gnUbR+OyNCkroZhoIQDDj/LmLyMb Lb2A== X-Gm-Message-State: AOJu0YwoXl0nMQ0iZ8fkYiamt1muSnM6n/jggUUvqoHT0ZGjs7hiQ8Be MjGcJ46DRltJXcWLipOR57HA7Q== X-Google-Smtp-Source: AGHT+IHl+pMgyvtur/JNbIrQM0sYpoTu0Sl4CBWNwTFYDB3ETNHzopbO9fK1CG39Fnz3dURR6iY0pg== X-Received: by 2002:a05:6358:4311:b0:13c:fd78:bb43 with SMTP id r17-20020a056358431100b0013cfd78bb43mr36098417rwc.27.1697467137176; Mon, 16 Oct 2023 07:38:57 -0700 (PDT) Received: from localhost (9.184.168.34.bc.googleusercontent.com. [34.168.184.9]) by smtp.gmail.com with UTF8SMTPSA id s5-20020aa78bc5000000b006be0fb89ac3sm2298667pfd.30.2023.10.16.07.38.56 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 16 Oct 2023 07:38:56 -0700 (PDT) From: jeffxu@chromium.org To: akpm@linux-foundation.org, keescook@chromium.org, sroettger@google.com Cc: jeffxu@google.com, jorgelo@chromium.org, groeck@chromium.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, jannh@google.com, 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, torvalds@linux-foundation.org, lstoakes@gmail.com, willy@infradead.org, 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 v1 1/8] Add mseal syscall Date: Mon, 16 Oct 2023 14:38:20 +0000 Message-ID: <20231016143828.647848-2-jeffxu@chromium.org> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog In-Reply-To: <20231016143828.647848-1-jeffxu@chromium.org> References: <20231016143828.647848-1-jeffxu@chromium.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 6E9B5A0020 X-Rspam-User: X-Stat-Signature: sayqjwgdrxx3rj46jicc7f7f4zmqr7jw X-Rspamd-Server: rspam01 X-HE-Tag: 1697467138-985116 X-HE-Meta: U2FsdGVkX1/LA4EYHbltHNlsz+ajMYXwz4rCLs7z3bI5xWiDPDZ8cPWlCLTyPBmJEdZrHOCOqDO+ffAbwVwte3xitdC14MILMl2zA2//3PII4/vYRJbFIuBxxrvl5drScwh5SLfYfIWU5x/S1uya8v1gMO4RIzF/Xiu8fKYoDI/douShGUr92AENgs11Hf9i15BDStvm8Xe7mpmhjHguNTRTU1XoG99tK78EaB17TFmhwKYTi/85nkPONnfm5BoWH+0qBuGmQE3wZQdfTG+53GgCSnI79lcd41quxqDOYIE0ZlrO05qQFtKRSj+tKUA2Pp+4nwzm4FA5+KWmTT0dTgn6KJuO2kSdCK6iPlQxAvXZw3W08Amb/NHIVAzjIlJyCp+A9RU+TjW1C46U2DKkF5DDLO4yPr9mK4YUpMIXuZmDU+63IF2z8DVkGtDebsHeJPlIvfxNc/wFkYhljVANeyAR/HmRYLzao9VFCx4zUZfuJy30/aT6YjyERSojinOPRnHheEAa/xYRMEKrqRuPhcezetT1dJaGQdIKMHqUIZkC48G0Z2UpV/hB25qQ+cKoHjzqL40IHp/NmGwxZ4j0K6P9btMnLujN4DFz9PvKBt2ocFMU30/AsC1x/gvyYfOwduvWrgbFIjqVo+cRz3IqDldK42t4ImLUCovSAs4x1EAcyEPQ34j46QLBUTmBCZezmBMXx84Vd5L7f5nfEBhBOSCc5vVMdz4hT+ATV5utAlR3ZdvKkhAv/YeeLXTuW1RV5g+AJMA0Obu0WPCIxxKhZulXHHUq7AIEvg5WEwh9tygMcBOF6KNSdXSNTDti1XpTn0O/Qy7Vsb7E0iNlNAXFWMbwDES97F9IUmprAHBEdD5x560RpQkL9IXUZmBXZCCol40yX+1178/z0Ck/wR7D+p7nJoXvaGgSQGwkVgaP+BvabRYwZWzV6efPOs6q/fQs7bXX1UGESNwEAebmKhK C3xMHF4G L9aXWWkJs/87TxX8WLjh5rTIcgG3MxQTwpa0QQbrmTxUMGmnJ7MMBaN7TYeEVGeHebY8140mQIbuice52TwdrtAfaE+pimV6tnrdaFZU6xkC/RVEtnBPwTRt3JHzyeX/vZ3jq93qyUgH1Wcj1OY3Yh4F8QXNt/MGO2o6S2EhS3zJU4unI5CwQi9uiv59kRpiossXDwJ9OGMbIzkT34XZBjt50EwG6FepYcy3Nsx7KD1hIUvSnpsabyOjrKt8SZVm2bcGHi18DjPnStlXz7TuU+ZkFvtwuNAuuj4E5pnjvXgLFBQQs0FK618JVk7sidEL8TmXc 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 mseal() prevents system calls from modifying the metadata of virtual addresses. 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. Signed-off-by: Jeff Xu --- include/linux/mm.h | 14 ++ 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 | 268 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 321 insertions(+) create mode 100644 mm/mseal.c diff --git a/include/linux/mm.h b/include/linux/mm.h index 53efddc4d178..e790b91a0cd4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -257,6 +257,20 @@ extern struct rw_semaphore nommu_region_sem; extern unsigned int kobjsize(const void *objp); #endif +/* + * vm_seals in vm_area_struct, see mm_types.h. + */ +#define VM_SEAL_NONE 0x00000000 +#define VM_SEAL_MSEAL 0x00000001 +#define VM_SEAL_MPROTECT 0x00000002 +#define VM_SEAL_MUNMAP 0x00000004 +#define VM_SEAL_MREMAP 0x00000008 +#define VM_SEAL_MMAP 0x00000010 + +#define VM_SEAL_ALL \ + (VM_SEAL_MSEAL | VM_SEAL_MPROTECT | VM_SEAL_MUNMAP | VM_SEAL_MMAP | \ + VM_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..f574c7dbee76 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 int types, + unsigned int 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..d7882b5984ce 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 0x1 +#define MM_SEAL_MPROTECT 0x2 +#define MM_SEAL_MUNMAP 0x4 +#define MM_SEAL_MMAP 0x8 +#define MM_SEAL_MREMAP 0x10 + #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..9b6c477e713e 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 & VM_SEAL_ALL) + return 0; +#endif return true; } diff --git a/mm/mseal.c b/mm/mseal.c new file mode 100644 index 000000000000..615b6e06ab44 --- /dev/null +++ b/mm/mseal.c @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Implement mseal() syscall. + * + * Copyright (c) 2023 Google, Inc. + * + * Author: Jeff Xu + */ + +#include +#include +#include +#include +#include "internal.h" + +/* + * 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) + +static bool can_do_mseal(unsigned int types, unsigned int 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 int newSeals) +{ + /* When SEAL_MSEAL is set, reject if a new type of seal is added */ + if ((vma->vm_seals & VM_SEAL_MSEAL) && + (newSeals & ~(vma->vm_seals & VM_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 int addtypes) +{ + int ret = 0; + + if (addtypes & ~(vma->vm_seals & VM_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; +} + +/* + * convert user input to internal type for seal type. + */ +static unsigned int convert_user_seal_type(unsigned int types) +{ + unsigned int newtypes = VM_SEAL_NONE; + + if (types & MM_SEAL_MSEAL) + newtypes |= VM_SEAL_MSEAL; + + if (types & MM_SEAL_MPROTECT) + newtypes |= VM_SEAL_MPROTECT; + + if (types & MM_SEAL_MUNMAP) + newtypes |= VM_SEAL_MUNMAP; + + if (types & MM_SEAL_MMAP) + newtypes |= VM_SEAL_MMAP; + + if (types & MM_SEAL_MREMAP) + newtypes |= VM_SEAL_MREMAP; + + return newtypes; +} + +/* + * 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 int 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 int 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 int types, + unsigned int flags) +{ + int ret = 0; + unsigned long end; + struct mm_struct *mm = current->mm; + unsigned int newtypes; + size_t len; + + if (!can_do_mseal(types, flags)) + return -EINVAL; + + newtypes = convert_user_seal_type(types); + + 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, newtypes); + if (ret) + goto out; + + ret = apply_mm_seal(start, end, newtypes); + +out: + mmap_write_unlock(current->mm); + return ret; +} + +SYSCALL_DEFINE4(mseal, unsigned long, start, size_t, len, unsigned int, types, unsigned int, + flags) +{ + return do_mseal(start, len, types, flags); +}