Commit befc42e5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull powerpc fixes from Michael Ellerman:

 - A fix for unrecoverable SLB faults in the interrupt exit path,
   introduced by the recent rewrite of interrupt exit in C.

 - Four fixes for our KUAP (Kernel Userspace Access Prevention) support
   on 64-bit. These are all fairly minor with the exception of the
   change to evaluate the get/put_user() arguments before we enable user
   access, which reduces the amount of code we run with user access
   enabled.

 - A fix for our secure boot IMA rules, if enforcement of module
   signatures is enabled at runtime rather than build time.

 - A fix to our 32-bit VDSO clock_getres() which wasn't falling back to
   the syscall for unknown clocks.

 - A build fix for CONFIG_PPC_KUAP_DEBUG on 32-bit BookS, and another
   for 40x.

Thanks to: Christophe Leroy, Hugh Dickins, Nicholas Piggin, Aurelien
Jarno, Mimi Zohar, Nayna Jain.

* tag 'powerpc-5.7-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/40x: Make more space for system call exception
  powerpc/vdso32: Fallback on getres syscall when clock is unknown
  powerpc/32s: Fix build failure with CONFIG_PPC_KUAP_DEBUG
  powerpc/ima: Fix secure boot rules in ima arch policy
  powerpc/64s/kuap: Restore AMR in fast_interrupt_return
  powerpc/64s/kuap: Restore AMR in system reset exception
  powerpc/64/kuap: Move kuap checks out of MSR[RI]=0 regions of exit code
  powerpc/64s: Fix unrecoverable SLB crashes due to preemption check
  powerpc/uaccess: Evaluate macro arguments once, before user access is allowed
parents 26b089a7 249c9b0c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@

.macro kuap_check	current, gpr
#ifdef CONFIG_PPC_KUAP_DEBUG
	lwz	\gpr2, KUAP(thread)
	lwz	\gpr, KUAP(thread)
999:	twnei	\gpr, 0
	EMIT_BUG_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE)
#endif
+19 −1
Original line number Diff line number Diff line
@@ -250,9 +250,27 @@ static inline bool arch_irqs_disabled(void)
	}								\
} while(0)

static inline bool __lazy_irq_pending(u8 irq_happened)
{
	return !!(irq_happened & ~PACA_IRQ_HARD_DIS);
}

/*
 * Check if a lazy IRQ is pending. Should be called with IRQs hard disabled.
 */
static inline bool lazy_irq_pending(void)
{
	return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS);
	return __lazy_irq_pending(get_paca()->irq_happened);
}

/*
 * Check if a lazy IRQ is pending, with no debugging checks.
 * Should be called with IRQs hard disabled.
 * For use in RI disabled code or other constrained situations.
 */
static inline bool lazy_irq_pending_nocheck(void)
{
	return __lazy_irq_pending(local_paca->irq_happened);
}

/*
+35 −14
Original line number Diff line number Diff line
@@ -166,13 +166,17 @@ do { \
({								\
	long __pu_err;						\
	__typeof__(*(ptr)) __user *__pu_addr = (ptr);		\
	__typeof__(*(ptr)) __pu_val = (x);			\
	__typeof__(size) __pu_size = (size);			\
								\
	if (!is_kernel_addr((unsigned long)__pu_addr))		\
		might_fault();					\
	__chk_user_ptr(ptr);					\
	__chk_user_ptr(__pu_addr);				\
	if (do_allow)								\
		__put_user_size((x), __pu_addr, (size), __pu_err);		\
		__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err);	\
	else									\
		__put_user_size_allowed((x), __pu_addr, (size), __pu_err);	\
		__put_user_size_allowed(__pu_val, __pu_addr, __pu_size, __pu_err); \
								\
	__pu_err;						\
})

@@ -180,9 +184,13 @@ do { \
({									\
	long __pu_err = -EFAULT;					\
	__typeof__(*(ptr)) __user *__pu_addr = (ptr);			\
	__typeof__(*(ptr)) __pu_val = (x);				\
	__typeof__(size) __pu_size = (size);				\
									\
	might_fault();							\
	if (access_ok(__pu_addr, size))			\
		__put_user_size((x), __pu_addr, (size), __pu_err);	\
	if (access_ok(__pu_addr, __pu_size))				\
		__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
									\
	__pu_err;							\
})

@@ -190,8 +198,12 @@ do { \
({								\
	long __pu_err;						\
	__typeof__(*(ptr)) __user *__pu_addr = (ptr);		\
	__chk_user_ptr(ptr);					\
	__put_user_size((x), __pu_addr, (size), __pu_err);	\
	__typeof__(*(ptr)) __pu_val = (x);			\
	__typeof__(size) __pu_size = (size);			\
								\
	__chk_user_ptr(__pu_addr);				\
	__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
								\
	__pu_err;						\
})

@@ -283,15 +295,18 @@ do { \
	long __gu_err;						\
	__long_type(*(ptr)) __gu_val;				\
	__typeof__(*(ptr)) __user *__gu_addr = (ptr);	\
	__chk_user_ptr(ptr);					\
	__typeof__(size) __gu_size = (size);			\
								\
	__chk_user_ptr(__gu_addr);				\
	if (!is_kernel_addr((unsigned long)__gu_addr))		\
		might_fault();					\
	barrier_nospec();					\
	if (do_allow)								\
		__get_user_size(__gu_val, __gu_addr, (size), __gu_err);		\
		__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err);	\
	else									\
		__get_user_size_allowed(__gu_val, __gu_addr, (size), __gu_err);	\
		__get_user_size_allowed(__gu_val, __gu_addr, __gu_size, __gu_err); \
	(x) = (__typeof__(*(ptr)))__gu_val;			\
								\
	__gu_err;						\
})

@@ -300,12 +315,15 @@ do { \
	long __gu_err = -EFAULT;					\
	__long_type(*(ptr)) __gu_val = 0;				\
	__typeof__(*(ptr)) __user *__gu_addr = (ptr);		\
	__typeof__(size) __gu_size = (size);				\
									\
	might_fault();							\
	if (access_ok(__gu_addr, (size))) {		\
	if (access_ok(__gu_addr, __gu_size)) {				\
		barrier_nospec();					\
		__get_user_size(__gu_val, __gu_addr, (size), __gu_err);	\
		__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
	}								\
	(x) = (__force __typeof__(*(ptr)))__gu_val;				\
									\
	__gu_err;							\
})

@@ -314,10 +332,13 @@ do { \
	long __gu_err;						\
	__long_type(*(ptr)) __gu_val;				\
	__typeof__(*(ptr)) __user *__gu_addr = (ptr);	\
	__chk_user_ptr(ptr);					\
	__typeof__(size) __gu_size = (size);			\
								\
	__chk_user_ptr(__gu_addr);				\
	barrier_nospec();					\
	__get_user_size(__gu_val, __gu_addr, (size), __gu_err);	\
	__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
								\
	__gu_err;						\
})

+3 −1
Original line number Diff line number Diff line
@@ -472,15 +472,17 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
#ifdef CONFIG_PPC_BOOK3S
	/*
	 * If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not
	 * touched, AMR not set, no exit work created, then this can be used.
	 * touched, no exit work created, then this can be used.
	 */
	.balign IFETCH_ALIGN_BYTES
	.globl fast_interrupt_return
fast_interrupt_return:
_ASM_NOKPROBE_SYMBOL(fast_interrupt_return)
	kuap_check_amr r3, r4
	ld	r4,_MSR(r1)
	andi.	r0,r4,MSR_PR
	bne	.Lfast_user_interrupt_return
	kuap_restore_amr r3
	andi.	r0,r4,MSR_RI
	li	r3,0 /* 0 return value, no EMULATE_STACK_STORE */
	bne+	.Lfast_kernel_interrupt_return
+1 −0
Original line number Diff line number Diff line
@@ -971,6 +971,7 @@ EXC_COMMON_BEGIN(system_reset_common)
	ld	r10,SOFTE(r1)
	stb	r10,PACAIRQSOFTMASK(r13)

	kuap_restore_amr r10
	EXCEPTION_RESTORE_REGS
	RFI_TO_USER_OR_KERNEL

Loading