Patch "parisc: Flush kernel data mapping in set_pte_at() when installing pte for user page" has been added to the 5.10-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

    parisc: Flush kernel data mapping in set_pte_at() when installing pte for user page

to the 5.10-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:
     parisc-flush-kernel-data-mapping-in-set_pte_at-when-.patch
and it can be found in the queue-5.10 subdirectory.

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



commit 780ff6d9eb5b8c8a3cfe9f5bf7d9b789f3ad0418
Author: John David Anglin <dave.anglin@xxxxxxxx>
Date:   Mon Nov 8 16:48:16 2021 -0500

    parisc: Flush kernel data mapping in set_pte_at() when installing pte for user page
    
    [ Upstream commit 38860b2c8bb1b92f61396eb06a63adff916fc31d ]
    
    For years, there have been random segmentation faults in userspace on
    SMP PA-RISC machines.  It occurred to me that this might be a problem in
    set_pte_at().  MIPS and some other architectures do cache flushes when
    installing PTEs with the present bit set.
    
    Here I have adapted the code in update_mmu_cache() to flush the kernel
    mapping when the kernel flush is deferred, or when the kernel mapping
    may alias with the user mapping.  This simplifies calls to
    update_mmu_cache().
    
    I also changed the barrier in set_pte() from a compiler barrier to a
    full memory barrier.  I know this change is not sufficient to fix the
    problem.  It might not be needed.
    
    I have had a few days of operation with 5.14.16 to 5.15.1 and haven't
    seen any random segmentation faults on rp3440 or c8000 so far.
    
    Signed-off-by: John David Anglin <dave.anglin@xxxxxxxx>
    Signed-off-by: Helge Deller <deller@xxxxxx>
    Cc: stable@xxxxxxxxxx # 5.12+
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index 39017210dbf0..8964798b8274 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -76,6 +76,8 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 	purge_tlb_end(flags);
 }
 
+extern void __update_cache(pte_t pte);
+
 /* Certain architectures need to do special things when PTEs
  * within a page table are directly modified.  Thus, the following
  * hook is made available.
@@ -83,11 +85,14 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 #define set_pte(pteptr, pteval)			\
 	do {					\
 		*(pteptr) = (pteval);		\
-		barrier();			\
+		mb();				\
 	} while(0)
 
 #define set_pte_at(mm, addr, pteptr, pteval)	\
 	do {					\
+		if (pte_present(pteval) &&	\
+		    pte_user(pteval))		\
+			__update_cache(pteval);	\
 		*(pteptr) = (pteval);		\
 		purge_tlb_entries(mm, addr);	\
 	} while (0)
@@ -305,6 +310,7 @@ extern unsigned long *empty_zero_page;
 
 #define pte_none(x)     (pte_val(x) == 0)
 #define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
+#define pte_user(x)	(pte_val(x) & _PAGE_USER)
 #define pte_clear(mm, addr, xp)  set_pte_at(mm, addr, xp, __pte(0))
 
 #define pmd_flag(x)	(pmd_val(x) & PxD_FLAG_MASK)
@@ -412,7 +418,7 @@ extern void paging_init (void);
 
 #define PG_dcache_dirty         PG_arch_1
 
-extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);
+#define update_mmu_cache(vms,addr,ptep) __update_cache(*ptep)
 
 /* Encode and de-code a swap entry */
 
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 86a1a63563fd..c81ab0cb8925 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -83,9 +83,9 @@ EXPORT_SYMBOL(flush_cache_all_local);
 #define pfn_va(pfn)	__va(PFN_PHYS(pfn))
 
 void
-update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
+__update_cache(pte_t pte)
 {
-	unsigned long pfn = pte_pfn(*ptep);
+	unsigned long pfn = pte_pfn(pte);
 	struct page *page;
 
 	/* We don't have pte special.  As a result, we can be called with



[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