linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Qi Zheng <zhengqi.arch@bytedance.com>
To: akpm@linux-foundation.org, david@redhat.com, jannh@google.com,
	hughd@google.com, muchun.song@linux.dev
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	Qi Zheng <zhengqi.arch@bytedance.com>,
	syzbot+1c58afed1cfd2f57efee@syzkaller.appspotmail.com
Subject: [PATCH v4 12/11] mm: pgtable: make ptlock be freed by RCU
Date: Tue, 10 Dec 2024 16:44:31 +0800	[thread overview]
Message-ID: <20241210084431.91414-1-zhengqi.arch@bytedance.com> (raw)
In-Reply-To: <841c1f35478d5354872d307888979c9e20de9c09.1733305182.git.zhengqi.arch@bytedance.com>

If ALLOC_SPLIT_PTLOCKS is enabled, the ptdesc->ptl will be a pointer and
a ptlock will be allocated for it, and it will be freed immediately before
the PTE page is freed. Once we support empty PTE page reclaimation, it may
result in the following use-after-free problem:

	CPU 0				CPU 1

					pte_offset_map_rw_nolock(&ptlock)
					--> rcu_read_lock()
	madvise(MADV_DONTNEED)
	--> ptlock_free (free ptlock immediately!)
	    free PTE page via RCU
					/* UAF!! */
					spin_lock(ptlock)

To avoid this problem, make ptlock also be freed by RCU.

Reported-by: syzbot+1c58afed1cfd2f57efee@syzkaller.appspotmail.com
Tested-by: syzbot+1c58afed1cfd2f57efee@syzkaller.appspotmail.com
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
---
 include/linux/mm.h       |  2 +-
 include/linux/mm_types.h |  9 ++++++++-
 mm/memory.c              | 22 ++++++++++++++++------
 3 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index e2d38c5867b32..e836ef6291265 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2988,7 +2988,7 @@ void ptlock_free(struct ptdesc *ptdesc);
 
 static inline spinlock_t *ptlock_ptr(struct ptdesc *ptdesc)
 {
-	return ptdesc->ptl;
+	return &(ptdesc->ptl->ptl);
 }
 #else /* ALLOC_SPLIT_PTLOCKS */
 static inline void ptlock_cache_init(void)
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 5d8779997266e..df8f5152644ec 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -434,6 +434,13 @@ FOLIO_MATCH(flags, _flags_2a);
 FOLIO_MATCH(compound_head, _head_2a);
 #undef FOLIO_MATCH
 
+#if ALLOC_SPLIT_PTLOCKS
+struct pt_lock {
+	spinlock_t ptl;
+	struct rcu_head rcu;
+};
+#endif
+
 /**
  * struct ptdesc -    Memory descriptor for page tables.
  * @__page_flags:     Same as page flags. Powerpc only.
@@ -478,7 +485,7 @@ struct ptdesc {
 	union {
 		unsigned long _pt_pad_2;
 #if ALLOC_SPLIT_PTLOCKS
-		spinlock_t *ptl;
+		struct pt_lock *ptl;
 #else
 		spinlock_t ptl;
 #endif
diff --git a/mm/memory.c b/mm/memory.c
index 91900a1479322..b5babc4bc36bc 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -7044,24 +7044,34 @@ static struct kmem_cache *page_ptl_cachep;
 
 void __init ptlock_cache_init(void)
 {
-	page_ptl_cachep = kmem_cache_create("page->ptl", sizeof(spinlock_t), 0,
+	page_ptl_cachep = kmem_cache_create("page->ptl", sizeof(struct pt_lock), 0,
 			SLAB_PANIC, NULL);
 }
 
 bool ptlock_alloc(struct ptdesc *ptdesc)
 {
-	spinlock_t *ptl;
+	struct pt_lock *pt_lock;
 
-	ptl = kmem_cache_alloc(page_ptl_cachep, GFP_KERNEL);
-	if (!ptl)
+	pt_lock = kmem_cache_alloc(page_ptl_cachep, GFP_KERNEL);
+	if (!pt_lock)
 		return false;
-	ptdesc->ptl = ptl;
+	ptdesc->ptl = pt_lock;
 	return true;
 }
 
+static void ptlock_free_rcu(struct rcu_head *head)
+{
+	struct pt_lock *pt_lock;
+
+	pt_lock = container_of(head, struct pt_lock, rcu);
+	kmem_cache_free(page_ptl_cachep, pt_lock);
+}
+
 void ptlock_free(struct ptdesc *ptdesc)
 {
-	kmem_cache_free(page_ptl_cachep, ptdesc->ptl);
+	struct pt_lock *pt_lock = ptdesc->ptl;
+
+	call_rcu(&pt_lock->rcu, ptlock_free_rcu);
 }
 #endif
 
-- 
2.20.1



  reply	other threads:[~2024-12-10  8:45 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-04 11:09 [PATCH v4 00/11] synchronously scan and reclaim empty user PTE pages Qi Zheng
2024-12-04 11:09 ` [PATCH v4 01/11] mm: khugepaged: recheck pmd state in retract_page_tables() Qi Zheng
2024-12-04 11:09 ` [PATCH v4 02/11] mm: userfaultfd: recheck dst_pmd entry in move_pages_pte() Qi Zheng
2024-12-10  8:41   ` [PATCH v4 02/11 fix] fix: " Qi Zheng
2024-12-04 11:09 ` [PATCH v4 03/11] mm: introduce zap_nonpresent_ptes() Qi Zheng
2024-12-04 11:09 ` [PATCH v4 04/11] mm: introduce do_zap_pte_range() Qi Zheng
2024-12-04 11:09 ` [PATCH v4 05/11] mm: skip over all consecutive none ptes in do_zap_pte_range() Qi Zheng
2024-12-04 11:09 ` [PATCH v4 06/11] mm: zap_install_uffd_wp_if_needed: return whether uffd-wp pte has been re-installed Qi Zheng
2024-12-04 11:09 ` [PATCH v4 07/11] mm: do_zap_pte_range: return any_skipped information to the caller Qi Zheng
2024-12-04 11:09 ` [PATCH v4 08/11] mm: make zap_pte_range() handle full within-PMD range Qi Zheng
2024-12-04 11:09 ` [PATCH v4 09/11] mm: pgtable: reclaim empty PTE page in madvise(MADV_DONTNEED) Qi Zheng
2024-12-04 22:36   ` Andrew Morton
2024-12-04 22:47     ` Jann Horn
2024-12-05  3:23       ` Qi Zheng
2024-12-05  3:35     ` Qi Zheng
2024-12-06 11:23   ` [PATCH v4 09/11 fix] fix: " Qi Zheng
2024-12-04 11:09 ` [PATCH v4 10/11] x86: mm: free page table pages by RCU instead of semi RCU Qi Zheng
2024-12-04 11:09 ` [PATCH v4 11/11] x86: select ARCH_SUPPORTS_PT_RECLAIM if X86_64 Qi Zheng
2024-12-10  8:44   ` Qi Zheng [this message]
2024-12-04 22:49 ` [PATCH v4 00/11] synchronously scan and reclaim empty user PTE pages Andrew Morton
2024-12-04 22:56   ` Jann Horn
2024-12-05  3:59     ` Qi Zheng
2024-12-05  3:56   ` Qi Zheng
2024-12-10  8:57 ` Qi Zheng

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=20241210084431.91414-1-zhengqi.arch@bytedance.com \
    --to=zhengqi.arch@bytedance.com \
    --cc=akpm@linux-foundation.org \
    --cc=david@redhat.com \
    --cc=hughd@google.com \
    --cc=jannh@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=muchun.song@linux.dev \
    --cc=syzbot+1c58afed1cfd2f57efee@syzkaller.appspotmail.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