Skip to content

Commit befc42e

Browse files
committed
Merge tag 'powerpc-5.7-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
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
2 parents 26b089a + 249c9b0 commit befc42e

File tree

9 files changed

+78
-33
lines changed

9 files changed

+78
-33
lines changed

arch/powerpc/include/asm/book3s/32/kup.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575

7676
.macro kuap_check current, gpr
7777
#ifdef CONFIG_PPC_KUAP_DEBUG
78-
lwz \gpr2, KUAP(thread)
78+
lwz \gpr, KUAP(thread)
7979
999: twnei \gpr, 0
8080
EMIT_BUG_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE)
8181
#endif

arch/powerpc/include/asm/hw_irq.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,27 @@ static inline bool arch_irqs_disabled(void)
250250
} \
251251
} while(0)
252252

253+
static inline bool __lazy_irq_pending(u8 irq_happened)
254+
{
255+
return !!(irq_happened & ~PACA_IRQ_HARD_DIS);
256+
}
257+
258+
/*
259+
* Check if a lazy IRQ is pending. Should be called with IRQs hard disabled.
260+
*/
253261
static inline bool lazy_irq_pending(void)
254262
{
255-
return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS);
263+
return __lazy_irq_pending(get_paca()->irq_happened);
264+
}
265+
266+
/*
267+
* Check if a lazy IRQ is pending, with no debugging checks.
268+
* Should be called with IRQs hard disabled.
269+
* For use in RI disabled code or other constrained situations.
270+
*/
271+
static inline bool lazy_irq_pending_nocheck(void)
272+
{
273+
return __lazy_irq_pending(local_paca->irq_happened);
256274
}
257275

258276
/*

arch/powerpc/include/asm/uaccess.h

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -166,32 +166,44 @@ do { \
166166
({ \
167167
long __pu_err; \
168168
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
169+
__typeof__(*(ptr)) __pu_val = (x); \
170+
__typeof__(size) __pu_size = (size); \
171+
\
169172
if (!is_kernel_addr((unsigned long)__pu_addr)) \
170173
might_fault(); \
171-
__chk_user_ptr(ptr); \
174+
__chk_user_ptr(__pu_addr); \
172175
if (do_allow) \
173-
__put_user_size((x), __pu_addr, (size), __pu_err); \
176+
__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
174177
else \
175-
__put_user_size_allowed((x), __pu_addr, (size), __pu_err); \
178+
__put_user_size_allowed(__pu_val, __pu_addr, __pu_size, __pu_err); \
179+
\
176180
__pu_err; \
177181
})
178182

179183
#define __put_user_check(x, ptr, size) \
180184
({ \
181185
long __pu_err = -EFAULT; \
182186
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
187+
__typeof__(*(ptr)) __pu_val = (x); \
188+
__typeof__(size) __pu_size = (size); \
189+
\
183190
might_fault(); \
184-
if (access_ok(__pu_addr, size)) \
185-
__put_user_size((x), __pu_addr, (size), __pu_err); \
191+
if (access_ok(__pu_addr, __pu_size)) \
192+
__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
193+
\
186194
__pu_err; \
187195
})
188196

189197
#define __put_user_nosleep(x, ptr, size) \
190198
({ \
191199
long __pu_err; \
192200
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
193-
__chk_user_ptr(ptr); \
194-
__put_user_size((x), __pu_addr, (size), __pu_err); \
201+
__typeof__(*(ptr)) __pu_val = (x); \
202+
__typeof__(size) __pu_size = (size); \
203+
\
204+
__chk_user_ptr(__pu_addr); \
205+
__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
206+
\
195207
__pu_err; \
196208
})
197209

@@ -283,15 +295,18 @@ do { \
283295
long __gu_err; \
284296
__long_type(*(ptr)) __gu_val; \
285297
__typeof__(*(ptr)) __user *__gu_addr = (ptr); \
286-
__chk_user_ptr(ptr); \
298+
__typeof__(size) __gu_size = (size); \
299+
\
300+
__chk_user_ptr(__gu_addr); \
287301
if (!is_kernel_addr((unsigned long)__gu_addr)) \
288302
might_fault(); \
289303
barrier_nospec(); \
290304
if (do_allow) \
291-
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
305+
__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
292306
else \
293-
__get_user_size_allowed(__gu_val, __gu_addr, (size), __gu_err); \
307+
__get_user_size_allowed(__gu_val, __gu_addr, __gu_size, __gu_err); \
294308
(x) = (__typeof__(*(ptr)))__gu_val; \
309+
\
295310
__gu_err; \
296311
})
297312

@@ -300,12 +315,15 @@ do { \
300315
long __gu_err = -EFAULT; \
301316
__long_type(*(ptr)) __gu_val = 0; \
302317
__typeof__(*(ptr)) __user *__gu_addr = (ptr); \
318+
__typeof__(size) __gu_size = (size); \
319+
\
303320
might_fault(); \
304-
if (access_ok(__gu_addr, (size))) { \
321+
if (access_ok(__gu_addr, __gu_size)) { \
305322
barrier_nospec(); \
306-
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
323+
__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
307324
} \
308325
(x) = (__force __typeof__(*(ptr)))__gu_val; \
326+
\
309327
__gu_err; \
310328
})
311329

@@ -314,10 +332,13 @@ do { \
314332
long __gu_err; \
315333
__long_type(*(ptr)) __gu_val; \
316334
__typeof__(*(ptr)) __user *__gu_addr = (ptr); \
317-
__chk_user_ptr(ptr); \
335+
__typeof__(size) __gu_size = (size); \
336+
\
337+
__chk_user_ptr(__gu_addr); \
318338
barrier_nospec(); \
319-
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
339+
__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
320340
(x) = (__force __typeof__(*(ptr)))__gu_val; \
341+
\
321342
__gu_err; \
322343
})
323344

arch/powerpc/kernel/entry_64.S

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,15 +472,17 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
472472
#ifdef CONFIG_PPC_BOOK3S
473473
/*
474474
* If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not
475-
* touched, AMR not set, no exit work created, then this can be used.
475+
* touched, no exit work created, then this can be used.
476476
*/
477477
.balign IFETCH_ALIGN_BYTES
478478
.globl fast_interrupt_return
479479
fast_interrupt_return:
480480
_ASM_NOKPROBE_SYMBOL(fast_interrupt_return)
481+
kuap_check_amr r3, r4
481482
ld r4,_MSR(r1)
482483
andi. r0,r4,MSR_PR
483484
bne .Lfast_user_interrupt_return
485+
kuap_restore_amr r3
484486
andi. r0,r4,MSR_RI
485487
li r3,0 /* 0 return value, no EMULATE_STACK_STORE */
486488
bne+ .Lfast_kernel_interrupt_return

arch/powerpc/kernel/exceptions-64s.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,7 @@ EXC_COMMON_BEGIN(system_reset_common)
971971
ld r10,SOFTE(r1)
972972
stb r10,PACAIRQSOFTMASK(r13)
973973

974+
kuap_restore_amr r10
974975
EXCEPTION_RESTORE_REGS
975976
RFI_TO_USER_OR_KERNEL
976977

arch/powerpc/kernel/head_40x.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,9 @@ _ENTRY(saved_ksp_limit)
344344
/* 0x0C00 - System Call Exception */
345345
START_EXCEPTION(0x0C00, SystemCall)
346346
SYSCALL_ENTRY 0xc00
347+
/* Trap_0D is commented out to get more space for system call exception */
347348

348-
EXCEPTION(0x0D00, Trap_0D, unknown_exception, EXC_XFER_STD)
349+
/* EXCEPTION(0x0D00, Trap_0D, unknown_exception, EXC_XFER_STD) */
349350
EXCEPTION(0x0E00, Trap_0E, unknown_exception, EXC_XFER_STD)
350351
EXCEPTION(0x0F00, Trap_0F, unknown_exception, EXC_XFER_STD)
351352

arch/powerpc/kernel/ima_arch.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ bool arch_ima_get_secureboot(void)
1919
* to be stored as an xattr or as an appended signature.
2020
*
2121
* To avoid duplicate signature verification as much as possible, the IMA
22-
* policy rule for module appraisal is added only if CONFIG_MODULE_SIG_FORCE
22+
* policy rule for module appraisal is added only if CONFIG_MODULE_SIG
2323
* is not enabled.
2424
*/
2525
static const char *const secure_rules[] = {
2626
"appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist appraise_type=imasig|modsig",
27-
#ifndef CONFIG_MODULE_SIG_FORCE
27+
#ifndef CONFIG_MODULE_SIG
2828
"appraise func=MODULE_CHECK appraise_flag=check_blacklist appraise_type=imasig|modsig",
2929
#endif
3030
NULL
@@ -50,7 +50,7 @@ static const char *const secure_and_trusted_rules[] = {
5050
"measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
5151
"measure func=MODULE_CHECK template=ima-modsig",
5252
"appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist appraise_type=imasig|modsig",
53-
#ifndef CONFIG_MODULE_SIG_FORCE
53+
#ifndef CONFIG_MODULE_SIG
5454
"appraise func=MODULE_CHECK appraise_flag=check_blacklist appraise_type=imasig|modsig",
5555
#endif
5656
NULL

arch/powerpc/kernel/syscall_64.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ notrace long system_call_exception(long r3, long r4, long r5,
3535
BUG_ON(!FULL_REGS(regs));
3636
BUG_ON(regs->softe != IRQS_ENABLED);
3737

38+
kuap_check_amr();
39+
3840
account_cpu_user_entry();
3941

4042
#ifdef CONFIG_PPC_SPLPAR
@@ -47,8 +49,6 @@ notrace long system_call_exception(long r3, long r4, long r5,
4749
}
4850
#endif
4951

50-
kuap_check_amr();
51-
5252
/*
5353
* This is not required for the syscall exit path, but makes the
5454
* stack frame look nicer. If this was initialised in the first stack
@@ -117,6 +117,8 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
117117
unsigned long ti_flags;
118118
unsigned long ret = 0;
119119

120+
kuap_check_amr();
121+
120122
regs->result = r3;
121123

122124
/* Check whether the syscall is issued inside a restartable sequence */
@@ -189,7 +191,7 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
189191

190192
/* This pattern matches prep_irq_for_idle */
191193
__hard_EE_RI_disable();
192-
if (unlikely(lazy_irq_pending())) {
194+
if (unlikely(lazy_irq_pending_nocheck())) {
193195
__hard_RI_enable();
194196
trace_hardirqs_off();
195197
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
@@ -204,8 +206,6 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
204206
local_paca->tm_scratch = regs->msr;
205207
#endif
206208

207-
kuap_check_amr();
208-
209209
account_cpu_user_exit();
210210

211211
return ret;
@@ -228,6 +228,8 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned
228228
BUG_ON(!FULL_REGS(regs));
229229
BUG_ON(regs->softe != IRQS_ENABLED);
230230

231+
kuap_check_amr();
232+
231233
local_irq_save(flags);
232234

233235
again:
@@ -264,7 +266,7 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned
264266

265267
trace_hardirqs_on();
266268
__hard_EE_RI_disable();
267-
if (unlikely(lazy_irq_pending())) {
269+
if (unlikely(lazy_irq_pending_nocheck())) {
268270
__hard_RI_enable();
269271
trace_hardirqs_off();
270272
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
@@ -292,8 +294,6 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned
292294
local_paca->tm_scratch = regs->msr;
293295
#endif
294296

295-
kuap_check_amr();
296-
297297
account_cpu_user_exit();
298298

299299
return ret;
@@ -313,6 +313,8 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs, unsign
313313
BUG_ON(regs->msr & MSR_PR);
314314
BUG_ON(!FULL_REGS(regs));
315315

316+
kuap_check_amr();
317+
316318
if (unlikely(*ti_flagsp & _TIF_EMULATE_STACK_STORE)) {
317319
clear_bits(_TIF_EMULATE_STACK_STORE, ti_flagsp);
318320
ret = 1;
@@ -334,7 +336,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs, unsign
334336

335337
trace_hardirqs_on();
336338
__hard_EE_RI_disable();
337-
if (unlikely(lazy_irq_pending())) {
339+
if (unlikely(lazy_irq_pending_nocheck())) {
338340
__hard_RI_enable();
339341
irq_soft_mask_set(IRQS_ALL_DISABLED);
340342
trace_hardirqs_off();

arch/powerpc/kernel/vdso32/gettimeofday.S

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,11 @@ V_FUNCTION_BEGIN(__kernel_clock_getres)
218218
blr
219219

220220
/*
221-
* invalid clock
221+
* syscall fallback
222222
*/
223223
99:
224-
li r3, EINVAL
225-
crset so
224+
li r0,__NR_clock_getres
225+
sc
226226
blr
227227
.cfi_endproc
228228
V_FUNCTION_END(__kernel_clock_getres)

0 commit comments

Comments
 (0)