From: David Hildenbrand <david@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org, David Hildenbrand <david@redhat.com>,
Andrew Morton <akpm@linux-foundation.org>,
Mike Rapoport <rppt@kernel.org>,
Miklos Szeredi <mszeredi@redhat.com>,
Lorenzo Stoakes <lstoakes@gmail.com>,
xingwei lee <xrivendell7@gmail.com>,
yue sun <samsun1006219@gmail.com>
Subject: [PATCH v1 3/3] mm: merge folio_is_secretmem() into folio_fast_pin_allowed()
Date: Mon, 25 Mar 2024 14:41:14 +0100 [thread overview]
Message-ID: <20240325134114.257544-4-david@redhat.com> (raw)
In-Reply-To: <20240325134114.257544-1-david@redhat.com>
folio_is_secretmem() is currently only used during GUP-fast, and using
it in wrong context where concurrent truncation might happen, could be
problematic.
Nowadays, folio_fast_pin_allowed() performs similar checks during
GUP-fast and contains a lot of careful handling -- READ_ONCE( -- ), sanity
checks -- lockdep_assert_irqs_disabled() -- and helpful comments on how
this handling is safe and correct.
So let's merge folio_is_secretmem() into folio_fast_pin_allowed(), still
avoiding checking the actual mapping only if really required.
Signed-off-by: David Hildenbrand <david@redhat.com>
---
include/linux/secretmem.h | 21 ++-------------------
mm/gup.c | 33 +++++++++++++++++++++------------
2 files changed, 23 insertions(+), 31 deletions(-)
diff --git a/include/linux/secretmem.h b/include/linux/secretmem.h
index 6996f1f53f14..e918f96881f5 100644
--- a/include/linux/secretmem.h
+++ b/include/linux/secretmem.h
@@ -6,25 +6,8 @@
extern const struct address_space_operations secretmem_aops;
-static inline bool folio_is_secretmem(struct folio *folio)
+static inline bool secretmem_mapping(struct address_space *mapping)
{
- struct address_space *mapping;
-
- /*
- * Using folio_mapping() is quite slow because of the actual call
- * instruction.
- * We know that secretmem pages are not compound and LRU so we can
- * save a couple of cycles here.
- */
- if (folio_test_large(folio) || folio_test_lru(folio))
- return false;
-
- mapping = (struct address_space *)
- ((unsigned long)folio->mapping & ~PAGE_MAPPING_FLAGS);
-
- if (!mapping || mapping != folio->mapping)
- return false;
-
return mapping->a_ops == &secretmem_aops;
}
@@ -38,7 +21,7 @@ static inline bool vma_is_secretmem(struct vm_area_struct *vma)
return false;
}
-static inline bool folio_is_secretmem(struct folio *folio)
+static inline bool secretmem_mapping(struct address_space *mapping)
{
return false;
}
diff --git a/mm/gup.c b/mm/gup.c
index e7510b6ce765..69d8bc8e4451 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -2472,6 +2472,8 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
* This call assumes the caller has pinned the folio, that the lowest page table
* level still points to this folio, and that interrupts have been disabled.
*
+ * GUP-fast must reject all secretmem folios.
+ *
* Writing to pinned file-backed dirty tracked folios is inherently problematic
* (see comment describing the writable_file_mapping_allowed() function). We
* therefore try to avoid the most egregious case of a long-term mapping doing
@@ -2484,22 +2486,32 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
static bool folio_fast_pin_allowed(struct folio *folio, unsigned int flags)
{
struct address_space *mapping;
+ bool check_secretmem = false;
+ bool reject_file_backed = false;
unsigned long mapping_flags;
/*
* If we aren't pinning then no problematic write can occur. A long term
* pin is the most egregious case so this is the one we disallow.
*/
- if ((flags & (FOLL_PIN | FOLL_LONGTERM | FOLL_WRITE)) !=
+ if ((flags & (FOLL_PIN | FOLL_LONGTERM | FOLL_WRITE)) ==
(FOLL_PIN | FOLL_LONGTERM | FOLL_WRITE))
- return true;
+ reject_file_backed = true;
+
+ /* We hold a folio reference, so we can safely access folio fields. */
- /* The folio is pinned, so we can safely access folio fields. */
+ /* secretmem folios are only order-0 folios and never LRU folios. */
+ if (IS_ENABLED(CONFIG_SECRETMEM) && !folio_test_large(folio) &&
+ !folio_test_lru(folio))
+ check_secretmem = true;
+
+ if (!reject_file_backed && !check_secretmem)
+ return true;
if (WARN_ON_ONCE(folio_test_slab(folio)))
return false;
- /* hugetlb mappings do not require dirty-tracking. */
+ /* hugetlb neither requires dirty-tracking nor can be secretmem. */
if (folio_test_hugetlb(folio))
return true;
@@ -2535,10 +2547,12 @@ static bool folio_fast_pin_allowed(struct folio *folio, unsigned int flags)
/*
* At this point, we know the mapping is non-null and points to an
- * address_space object. The only remaining whitelisted file system is
- * shmem.
+ * address_space object.
*/
- return shmem_mapping(mapping);
+ if (check_secretmem && secretmem_mapping(mapping))
+ return false;
+ /* The only remaining allowed file system is shmem. */
+ return !reject_file_backed || shmem_mapping(mapping);
}
static void __maybe_unused undo_dev_pagemap(int *nr, int nr_start,
@@ -2624,11 +2638,6 @@ static int gup_pte_range(pmd_t pmd, pmd_t *pmdp, unsigned long addr,
if (!folio)
goto pte_unmap;
- if (unlikely(folio_is_secretmem(folio))) {
- gup_put_folio(folio, 1, flags);
- goto pte_unmap;
- }
-
if (unlikely(pmd_val(pmd) != pmd_val(*pmdp)) ||
unlikely(pte_val(pte) != pte_val(ptep_get(ptep)))) {
gup_put_folio(folio, 1, flags);
--
2.43.2
next prev parent reply other threads:[~2024-03-25 13:41 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-25 13:41 [PATCH v1 0/3] mm/secretmem: one fix and one refactoring David Hildenbrand
2024-03-25 13:41 ` [PATCH v1 1/3] mm/secretmem: fix GUP-fast succeeding on secretmem folios David Hildenbrand
2024-03-25 18:30 ` Andrew Morton
2024-03-26 13:23 ` David Hildenbrand
2024-03-25 13:41 ` [PATCH v1 2/3] selftests/memfd_secret: add vmsplice() test David Hildenbrand
2024-03-26 6:17 ` Mike Rapoport
2024-03-26 12:32 ` David Hildenbrand
2024-03-26 13:11 ` David Hildenbrand
2024-03-25 13:41 ` David Hildenbrand [this message]
2024-03-26 6:30 ` [PATCH v1 3/3] mm: merge folio_is_secretmem() into folio_fast_pin_allowed() Mike Rapoport
2024-03-26 8:40 ` David Hildenbrand
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=20240325134114.257544-4-david@redhat.com \
--to=david@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lstoakes@gmail.com \
--cc=mszeredi@redhat.com \
--cc=rppt@kernel.org \
--cc=samsun1006219@gmail.com \
--cc=xrivendell7@gmail.com \
/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;
as well as URLs for NNTP newsgroup(s).