Patch "arm64: mte: Avoid setting PG_mte_tagged if no tags cleared or restored" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    arm64: mte: Avoid setting PG_mte_tagged if no tags cleared or restored

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     arm64-mte-avoid-setting-pg_mte_tagged-if-no-tags-cle.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit ab98e40cadfba39e6c6cbdd3c94717de0e111b75
Author: Catalin Marinas <catalin.marinas@xxxxxxx>
Date:   Thu Oct 6 17:33:54 2022 +0100

    arm64: mte: Avoid setting PG_mte_tagged if no tags cleared or restored
    
    [ Upstream commit a8e5e5146ad08d794c58252bab00b261045ef16d ]
    
    Prior to commit 69e3b846d8a7 ("arm64: mte: Sync tags for pages where PTE
    is untagged"), mte_sync_tags() was only called for pte_tagged() entries
    (those mapped with PROT_MTE). Therefore mte_sync_tags() could safely use
    test_and_set_bit(PG_mte_tagged, &page->flags) without inadvertently
    setting PG_mte_tagged on an untagged page.
    
    The above commit was required as guests may enable MTE without any
    control at the stage 2 mapping, nor a PROT_MTE mapping in the VMM.
    However, the side-effect was that any page with a PTE that looked like
    swap (or migration) was getting PG_mte_tagged set automatically. A
    subsequent page copy (e.g. migration) copied the tags to the destination
    page even if the tags were owned by KASAN.
    
    This issue was masked by the page_kasan_tag_reset() call introduced in
    commit e5b8d9218951 ("arm64: mte: reset the page tag in page->flags").
    When this commit was reverted (20794545c146), KASAN started reporting
    access faults because the overriding tags in a page did not match the
    original page->flags (with CONFIG_KASAN_HW_TAGS=y):
    
      BUG: KASAN: invalid-access in copy_page+0x10/0xd0 arch/arm64/lib/copy_page.S:26
      Read at addr f5ff000017f2e000 by task syz-executor.1/2218
      Pointer tag: [f5], memory tag: [f2]
    
    Move the PG_mte_tagged bit setting from mte_sync_tags() to the actual
    place where tags are cleared (mte_sync_page_tags()) or restored
    (mte_restore_tags()).
    
    Signed-off-by: Catalin Marinas <catalin.marinas@xxxxxxx>
    Reported-by: syzbot+c2c79c6d6eddc5262b77@xxxxxxxxxxxxxxxxxxxxxxxxx
    Fixes: 69e3b846d8a7 ("arm64: mte: Sync tags for pages where PTE is untagged")
    Cc: <stable@xxxxxxxxxxxxxxx> # 5.14.x
    Cc: Steven Price <steven.price@xxxxxxx>
    Cc: Andrey Konovalov <andreyknvl@xxxxxxxxx>
    Cc: Vincenzo Frascino <vincenzo.frascino@xxxxxxx>
    Cc: Will Deacon <will@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/0000000000004387dc05e5888ae5@xxxxxxxxxx/
    Reviewed-by: Steven Price <steven.price@xxxxxxx>
    Link: https://lore.kernel.org/r/20221006163354.3194102-1-catalin.marinas@xxxxxxx
    Signed-off-by: Catalin Marinas <catalin.marinas@xxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index dacca0684ea3..a3898bac5ae6 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -53,7 +53,12 @@ static void mte_sync_page_tags(struct page *page, pte_t old_pte,
 	 * the new page->flags are visible before the tags were updated.
 	 */
 	smp_wmb();
-	mte_clear_page_tags(page_address(page));
+	/*
+	 * Test PG_mte_tagged again in case it was racing with another
+	 * set_pte_at().
+	 */
+	if (!test_and_set_bit(PG_mte_tagged, &page->flags))
+		mte_clear_page_tags(page_address(page));
 }
 
 void mte_sync_tags(pte_t old_pte, pte_t pte)
@@ -69,7 +74,7 @@ void mte_sync_tags(pte_t old_pte, pte_t pte)
 
 	/* if PG_mte_tagged is set, tags have already been initialised */
 	for (i = 0; i < nr_pages; i++, page++) {
-		if (!test_and_set_bit(PG_mte_tagged, &page->flags))
+		if (!test_bit(PG_mte_tagged, &page->flags))
 			mte_sync_page_tags(page, old_pte, check_swap,
 					   pte_is_tagged);
 	}
diff --git a/arch/arm64/mm/mteswap.c b/arch/arm64/mm/mteswap.c
index 7c4ef56265ee..fd6cabc6d033 100644
--- a/arch/arm64/mm/mteswap.c
+++ b/arch/arm64/mm/mteswap.c
@@ -62,7 +62,12 @@ bool mte_restore_tags(swp_entry_t entry, struct page *page)
 	 * the new page->flags are visible before the tags were updated.
 	 */
 	smp_wmb();
-	mte_restore_page_tags(page_address(page), tags);
+	/*
+	 * Test PG_mte_tagged again in case it was racing with another
+	 * set_pte_at().
+	 */
+	if (!test_and_set_bit(PG_mte_tagged, &page->flags))
+		mte_restore_page_tags(page_address(page), tags);
 
 	return true;
 }



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux