From: jeffxu@chromium.org
To: akpm@linux-foundation.org, keescook@chromium.org,
jannh@google.com, sroettger@google.com, willy@infradead.org,
gregkh@linuxfoundation.org, torvalds@linux-foundation.org
Cc: jeffxu@google.com, jorgelo@chromium.org, groeck@chromium.org,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-mm@kvack.org, pedro.falcato@gmail.com,
dave.hansen@intel.com, linux-hardening@vger.kernel.org,
deraadt@openbsd.org, Jeff Xu <jeffxu@chromium.org>
Subject: [RFC PATCH v3 09/11] mseal: add MAP_SEALABLE to mmap()
Date: Tue, 12 Dec 2023 23:17:03 +0000 [thread overview]
Message-ID: <20231212231706.2680890-10-jeffxu@chromium.org> (raw)
In-Reply-To: <20231212231706.2680890-1-jeffxu@chromium.org>
From: Jeff Xu <jeffxu@chromium.org>
The MAP_SEALABLE flag is added to the flags field of mmap().
When present, it marks the map as sealable. A map created
without MAP_SEALABLE will not support sealing; In other words,
mseal() will fail for such a map.
Applications that don't care about sealing will expect their
behavior unchanged. For those that need sealing support, opt-in
by adding MAP_SEALABLE when creating the map.
Signed-off-by: Jeff Xu <jeffxu@chromium.org>
---
include/linux/mm.h | 52 ++++++++++++++++++++++++--
include/linux/mm_types.h | 1 +
include/uapi/asm-generic/mman-common.h | 1 +
mm/mmap.c | 2 +-
mm/mseal.c | 7 +++-
5 files changed, 57 insertions(+), 6 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 50dda474acc2..6f5dba9fbe21 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -267,6 +267,17 @@ extern unsigned int kobjsize(const void *objp);
MM_SEAL_PROT_PKEY | \
MM_SEAL_DISCARD_RO_ANON)
+/* define VM_SEALABLE in vm_seals of vm_area_struct. */
+#define VM_SEALABLE _BITUL(31)
+
+/*
+ * VM_SEALS_BITS_ALL marks the bits used for
+ * sealing in vm_seals of vm_area_structure.
+ */
+#define VM_SEALS_BITS_ALL ( \
+ MM_SEAL_ALL | \
+ VM_SEALABLE)
+
/*
* PROT_SEAL_ALL is all supported flags in mmap().
* See include/uapi/asm-generic/mman-common.h.
@@ -3330,9 +3341,17 @@ static inline void mm_populate(unsigned long addr, unsigned long len) {}
#ifdef CONFIG_MSEAL
/*
- * return the valid sealing (after mask).
+ * return the valid sealing (after mask), this includes sealable bit.
*/
static inline unsigned long vma_seals(struct vm_area_struct *vma)
+{
+ return (vma->vm_seals & VM_SEALS_BITS_ALL);
+}
+
+/*
+ * return the enabled sealing type (after mask), without sealable bit.
+ */
+static inline unsigned long vma_enabled_seals(struct vm_area_struct *vma)
{
return (vma->vm_seals & MM_SEAL_ALL);
}
@@ -3342,9 +3361,14 @@ static inline void update_vma_seals(struct vm_area_struct *vma, unsigned long vm
vma->vm_seals |= vm_seals;
}
+static inline bool is_vma_sealable(struct vm_area_struct *vma)
+{
+ return vma->vm_seals & VM_SEALABLE;
+}
+
static inline bool check_vma_seals_mergeable(unsigned long vm_seals1, unsigned long vm_seals2)
{
- if ((vm_seals1 & MM_SEAL_ALL) != (vm_seals2 & MM_SEAL_ALL))
+ if ((vm_seals1 & VM_SEALS_BITS_ALL) != (vm_seals2 & VM_SEALS_BITS_ALL))
return false;
return true;
@@ -3384,9 +3408,15 @@ static inline unsigned long convert_mmap_seals(unsigned long prot)
* check input sealing type from the "prot" field of mmap().
* for CONFIG_MSEAL case, this always return 0 (successful).
*/
-static inline int check_mmap_seals(unsigned long prot, unsigned long *vm_seals)
+static inline int check_mmap_seals(unsigned long prot, unsigned long *vm_seals,
+ unsigned long flags)
{
*vm_seals = convert_mmap_seals(prot);
+ if (*vm_seals)
+ /* setting one of MM_SEAL_XX means the map is sealable. */
+ *vm_seals |= VM_SEALABLE;
+ else
+ *vm_seals |= (flags & MAP_SEALABLE) ? VM_SEALABLE:0;
return 0;
}
#else
@@ -3395,6 +3425,16 @@ static inline unsigned long vma_seals(struct vm_area_struct *vma)
return 0;
}
+static inline unsigned long vma_enabled_seals(struct vm_area_struct *vma)
+{
+ return 0;
+}
+
+static inline bool is_vma_sealable(struct vm_area_struct *vma)
+{
+ return false;
+}
+
static inline bool check_vma_seals_mergeable(unsigned long vm_seals1, unsigned long vm_seals2)
{
return true;
@@ -3426,11 +3466,15 @@ static inline void update_vma_seals(struct vm_area_struct *vma, unsigned long vm
* check input sealing type from the "prot" field of mmap().
* For not CONFIG_MSEAL, if SEAL flag is set, it will return failure.
*/
-static inline int check_mmap_seals(unsigned long prot, unsigned long *vm_seals)
+static inline int check_mmap_seals(unsigned long prot, unsigned long *vm_seals,
+ unsigned long flags)
{
if (prot & PROT_SEAL_ALL)
return -EINVAL;
+ if (flags & MAP_SEALABLE)
+ return -EINVAL;
+
return 0;
}
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 052799173c86..c9b04c545f39 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -691,6 +691,7 @@ struct vm_area_struct {
/*
* bit masks for seal.
* need this since vm_flags is full.
+ * We could merge this into vm_flags if vm_flags ever get expanded.
*/
unsigned long vm_seals; /* seal flags, see mm.h. */
#endif
diff --git a/include/uapi/asm-generic/mman-common.h b/include/uapi/asm-generic/mman-common.h
index bf503962409a..57ef4507c00b 100644
--- a/include/uapi/asm-generic/mman-common.h
+++ b/include/uapi/asm-generic/mman-common.h
@@ -47,6 +47,7 @@
#define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be
* uninitialized */
+#define MAP_SEALABLE 0x8000000 /* map is sealable. */
/*
* Flags for mlock
diff --git a/mm/mmap.c b/mm/mmap.c
index 6da8d83f2e66..6e35e2070060 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1235,7 +1235,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
if (flags & MAP_FIXED_NOREPLACE)
flags |= MAP_FIXED;
- if (check_mmap_seals(prot, &vm_seals) < 0)
+ if (check_mmap_seals(prot, &vm_seals, flags) < 0)
return -EINVAL;
if (!(flags & MAP_FIXED))
diff --git a/mm/mseal.c b/mm/mseal.c
index 294f48d33db6..5d4cf71b497e 100644
--- a/mm/mseal.c
+++ b/mm/mseal.c
@@ -121,9 +121,13 @@ bool can_modify_mm_madv(struct mm_struct *mm, unsigned long start, unsigned long
*/
static bool can_add_vma_seals(struct vm_area_struct *vma, unsigned long newSeals)
{
+ /* if map is not sealable, reject. */
+ if (!is_vma_sealable(vma))
+ return false;
+
/* When SEAL_MSEAL is set, reject if a new type of seal is added. */
if ((vma->vm_seals & MM_SEAL_SEAL) &&
- (newSeals & ~(vma_seals(vma))))
+ (newSeals & ~(vma_enabled_seals(vma))))
return false;
/*
@@ -185,6 +189,7 @@ static int mseal_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma,
* 2> end is part of a valid vma.
* 3> No gap (unallocated address) between start and end.
* 4> requested seal type can be added in given address range.
+ * 5> map is sealable.
*/
static int check_mm_seal(unsigned long start, unsigned long end,
unsigned long newtypes)
--
2.43.0.472.g3155946c3a-goog
next prev parent reply other threads:[~2023-12-12 23:17 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-12 23:16 [RFC PATCH v3 00/11] Introduce mseal() jeffxu
2023-12-12 23:16 ` [RFC PATCH v3 01/11] mseal: Add mseal syscall jeffxu
2023-12-13 7:24 ` Greg KH
2023-12-12 23:16 ` [RFC PATCH v3 02/11] mseal: Wire up " jeffxu
2023-12-12 23:16 ` [RFC PATCH v3 03/11] mseal: add can_modify_mm and can_modify_vma jeffxu
2023-12-12 23:16 ` [RFC PATCH v3 04/11] mseal: add MM_SEAL_BASE jeffxu
2023-12-12 23:16 ` [RFC PATCH v3 05/11] mseal: add MM_SEAL_PROT_PKEY jeffxu
2023-12-12 23:17 ` [RFC PATCH v3 06/11] mseal: add sealing support for mmap jeffxu
2023-12-12 23:17 ` [RFC PATCH v3 07/11] mseal: make sealed VMA mergeable jeffxu
2023-12-12 23:17 ` [RFC PATCH v3 08/11] mseal: add MM_SEAL_DISCARD_RO_ANON jeffxu
2023-12-12 23:17 ` jeffxu [this message]
2023-12-12 23:17 ` [RFC PATCH v3 10/11] selftest mm/mseal memory sealing jeffxu
2023-12-31 6:39 ` Muhammad Usama Anjum
2023-12-12 23:17 ` [RFC PATCH v3 11/11] mseal:add documentation jeffxu
2023-12-13 0:39 ` Linus Torvalds
2023-12-14 0:35 ` Jeff Xu
2023-12-14 1:09 ` Theo de Raadt
2023-12-14 1:31 ` Linus Torvalds
2023-12-14 18:06 ` Stephen Röttger
2023-12-14 20:11 ` Pedro Falcato
2023-12-14 20:14 ` Linus Torvalds
2023-12-14 22:52 ` Jeff Xu
2024-01-20 15:23 ` Theo de Raadt
2024-01-20 16:40 ` Linus Torvalds
2024-01-20 16:59 ` Theo de Raadt
2024-01-21 0:16 ` Jeff Xu
2024-01-21 0:43 ` Theo de Raadt
2023-12-14 15:04 ` Theo de Raadt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231212231706.2680890-10-jeffxu@chromium.org \
--to=jeffxu@chromium.org \
--cc=akpm@linux-foundation.org \
--cc=dave.hansen@intel.com \
--cc=deraadt@openbsd.org \
--cc=gregkh@linuxfoundation.org \
--cc=groeck@chromium.org \
--cc=jannh@google.com \
--cc=jeffxu@google.com \
--cc=jorgelo@chromium.org \
--cc=keescook@chromium.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=pedro.falcato@gmail.com \
--cc=sroettger@google.com \
--cc=torvalds@linux-foundation.org \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox