[PATCH AUTOSEL 5.7 303/388] powerpc/64s/kuap: Add missing isync to KUAP restore paths

Sasha Levin
2020-06-18T02:33:55Z

From: Nicholas Piggin <npiggin@gmail.com>

[ Upstream commit cb2b53cbffe3c388cd676b63f34e54ceb2643ae2 ]

Writing the AMR register is documented to require context
synchronizing operations before and after, for it to take effect as
expected. The KUAP restore at interrupt exit time deliberately avoids
the isync after the AMR update because it only needs to take effect
after the context synchronizing RFID that soon follows. Add a comment
for this.

The missing isync before the update doesn't have an obvious
justification, and seems it could theoretically allow a rogue user
access to leak past the AMR update. Add isyncs for these.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200429065654.1677541-3-npiggin@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/powerpc/include/asm/book3s/64/kup-radix.h | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/book3s/64/kup-radix.h b/arch/powerpc/include/asm/book3s/64/kup-radix.h
index 3bcef989a35d..101d60f16d46 100644
--- a/arch/powerpc/include/asm/book3s/64/kup-radix.h
+++ b/arch/powerpc/include/asm/book3s/64/kup-radix.h
@@ -16,7 +16,9 @@
#ifdef CONFIG_PPC_KUAP
BEGIN_MMU_FTR_SECTION_NESTED(67)
ld \gpr, STACK_REGS_KUAP(r1)
+ isync
mtspr SPRN_AMR, \gpr
+ /* No isync required, see kuap_restore_amr() */
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67)
#endif
.endm
@@ -62,8 +64,15 @@

static inline void kuap_restore_amr(struct pt_regs *regs)
{
- if (mmu_has_feature(MMU_FTR_RADIX_KUAP))
+ if (mmu_has_feature(MMU_FTR_RADIX_KUAP)) {
+ isync();
mtspr(SPRN_AMR, regs->kuap);
+ /*
+ * No isync required here because we are about to RFI back to
+ * previous context before any user accesses would be made,
+ * which is a CSI.
+ */
+ }
}

static inline void kuap_check_amr(void)
--
2.25.1