Skip to content

Commit 29ba26a

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux
Pull ARM updates from Russell King: - disable jump label and high PTE for PREEMPT RT kernels - fix input operand modification in load_unaligned_zeropad() - fix hash_name() / fault path induced warnings - fix branch predictor hardening * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux: ARM: fix branch predictor hardening ARM: fix hash_name() fault ARM: allow __do_kernel_fault() to report execution of memory faults ARM: group is_permission_fault() with is_translation_fault() ARM: 9464/1: fix input-only operand modification in load_unaligned_zeropad() ARM: 9461/1: Disable HIGHPTE on PREEMPT_RT kernels ARM: 9459/1: Disable jump-label on PREEMPT_RT
2 parents 0048fbb + dd91433 commit 29ba26a

4 files changed

Lines changed: 87 additions & 33 deletions

File tree

arch/arm/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ config ARM
8282
select HAS_IOPORT
8383
select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT
8484
select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6
85-
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU
85+
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU && (!PREEMPT_RT || !SMP)
8686
select HAVE_ARCH_KFENCE if MMU && !XIP_KERNEL
8787
select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU
8888
select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL
@@ -1213,7 +1213,7 @@ config HIGHMEM
12131213

12141214
config HIGHPTE
12151215
bool "Allocate 2nd-level pagetables from highmem" if EXPERT
1216-
depends on HIGHMEM
1216+
depends on HIGHMEM && !PREEMPT_RT
12171217
default y
12181218
help
12191219
The VM uses one page of physical memory for each page table.

arch/arm/include/asm/word-at-a-time.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,17 @@ static inline unsigned long find_zero(unsigned long mask)
6767
*/
6868
static inline unsigned long load_unaligned_zeropad(const void *addr)
6969
{
70-
unsigned long ret, offset;
70+
unsigned long ret, tmp;
7171

7272
/* Load word from unaligned pointer addr */
7373
asm(
7474
"1: ldr %0, [%2]\n"
7575
"2:\n"
7676
" .pushsection .text.fixup,\"ax\"\n"
7777
" .align 2\n"
78-
"3: and %1, %2, #0x3\n"
79-
" bic %2, %2, #0x3\n"
80-
" ldr %0, [%2]\n"
78+
"3: bic %1, %2, #0x3\n"
79+
" ldr %0, [%1]\n"
80+
" and %1, %2, #0x3\n"
8181
" lsl %1, %1, #0x3\n"
8282
#ifndef __ARMEB__
8383
" lsr %0, %0, %1\n"
@@ -90,7 +90,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr)
9090
" .align 3\n"
9191
" .long 1b, 3b\n"
9292
" .popsection"
93-
: "=&r" (ret), "=&r" (offset)
93+
: "=&r" (ret), "=&r" (tmp)
9494
: "r" (addr), "Qo" (*(unsigned long *)addr));
9595

9696
return ret;

arch/arm/mm/alignment.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919
#include <linux/init.h>
2020
#include <linux/sched/signal.h>
2121
#include <linux/uaccess.h>
22+
#include <linux/unaligned.h>
2223

2324
#include <asm/cp15.h>
2425
#include <asm/system_info.h>
25-
#include <linux/unaligned.h>
26+
#include <asm/system_misc.h>
2627
#include <asm/opcodes.h>
2728

2829
#include "fault.h"
@@ -809,6 +810,9 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
809810
int thumb2_32b = 0;
810811
int fault;
811812

813+
if (addr >= TASK_SIZE && user_mode(regs))
814+
harden_branch_predictor();
815+
812816
if (interrupts_enabled(regs))
813817
local_irq_enable();
814818

arch/arm/mm/fault.c

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,19 @@ static inline bool is_translation_fault(unsigned int fsr)
128128
return false;
129129
}
130130

131+
static inline bool is_permission_fault(unsigned int fsr)
132+
{
133+
int fs = fsr_fs(fsr);
134+
#ifdef CONFIG_ARM_LPAE
135+
if ((fs & FS_MMU_NOLL_MASK) == FS_PERM_NOLL)
136+
return true;
137+
#else
138+
if (fs == FS_L1_PERM || fs == FS_L2_PERM)
139+
return true;
140+
#endif
141+
return false;
142+
}
143+
131144
static void die_kernel_fault(const char *msg, struct mm_struct *mm,
132145
unsigned long addr, unsigned int fsr,
133146
struct pt_regs *regs)
@@ -162,6 +175,8 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
162175
*/
163176
if (addr < PAGE_SIZE) {
164177
msg = "NULL pointer dereference";
178+
} else if (is_permission_fault(fsr) && fsr & FSR_LNX_PF) {
179+
msg = "execution of memory";
165180
} else {
166181
if (is_translation_fault(fsr) &&
167182
kfence_handle_page_fault(addr, is_write_fault(fsr), regs))
@@ -183,9 +198,6 @@ __do_user_fault(unsigned long addr, unsigned int fsr, unsigned int sig,
183198
{
184199
struct task_struct *tsk = current;
185200

186-
if (addr > TASK_SIZE)
187-
harden_branch_predictor();
188-
189201
#ifdef CONFIG_DEBUG_USER
190202
if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) ||
191203
((user_debug & UDBG_BUS) && (sig == SIGBUS))) {
@@ -225,19 +237,6 @@ void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
225237
}
226238

227239
#ifdef CONFIG_MMU
228-
static inline bool is_permission_fault(unsigned int fsr)
229-
{
230-
int fs = fsr_fs(fsr);
231-
#ifdef CONFIG_ARM_LPAE
232-
if ((fs & FS_MMU_NOLL_MASK) == FS_PERM_NOLL)
233-
return true;
234-
#else
235-
if (fs == FS_L1_PERM || fs == FS_L2_PERM)
236-
return true;
237-
#endif
238-
return false;
239-
}
240-
241240
#ifdef CONFIG_CPU_TTBR0_PAN
242241
static inline bool ttbr0_usermode_access_allowed(struct pt_regs *regs)
243242
{
@@ -259,6 +258,37 @@ static inline bool ttbr0_usermode_access_allowed(struct pt_regs *regs)
259258
}
260259
#endif
261260

261+
static int __kprobes
262+
do_kernel_address_page_fault(struct mm_struct *mm, unsigned long addr,
263+
unsigned int fsr, struct pt_regs *regs)
264+
{
265+
if (user_mode(regs)) {
266+
/*
267+
* Fault from user mode for a kernel space address. User mode
268+
* should not be faulting in kernel space, which includes the
269+
* vector/khelper page. Handle the branch predictor hardening
270+
* while interrupts are still disabled, then send a SIGSEGV.
271+
*/
272+
harden_branch_predictor();
273+
__do_user_fault(addr, fsr, SIGSEGV, SEGV_MAPERR, regs);
274+
} else {
275+
/*
276+
* Fault from kernel mode. Enable interrupts if they were
277+
* enabled in the parent context. Section (upper page table)
278+
* translation faults are handled via do_translation_fault(),
279+
* so we will only get here for a non-present kernel space
280+
* PTE or PTE permission fault. This may happen in exceptional
281+
* circumstances and need the fixup tables to be walked.
282+
*/
283+
if (interrupts_enabled(regs))
284+
local_irq_enable();
285+
286+
__do_kernel_fault(mm, addr, fsr, regs);
287+
}
288+
289+
return 0;
290+
}
291+
262292
static int __kprobes
263293
do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
264294
{
@@ -272,6 +302,12 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
272302
if (kprobe_page_fault(regs, fsr))
273303
return 0;
274304

305+
/*
306+
* Handle kernel addresses faults separately, which avoids touching
307+
* the mmap lock from contexts that are not able to sleep.
308+
*/
309+
if (addr >= TASK_SIZE)
310+
return do_kernel_address_page_fault(mm, addr, fsr, regs);
275311

276312
/* Enable interrupts if they were enabled in the parent context. */
277313
if (interrupts_enabled(regs))
@@ -448,16 +484,20 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
448484
* We enter here because the first level page table doesn't contain
449485
* a valid entry for the address.
450486
*
451-
* If the address is in kernel space (>= TASK_SIZE), then we are
452-
* probably faulting in the vmalloc() area.
487+
* If this is a user address (addr < TASK_SIZE), we handle this as a
488+
* normal page fault. This leaves the remainder of the function to handle
489+
* kernel address translation faults.
490+
*
491+
* Since user mode is not permitted to access kernel addresses, pass these
492+
* directly to do_kernel_address_page_fault() to handle.
453493
*
454-
* If the init_task's first level page tables contains the relevant
455-
* entry, we copy the it to this task. If not, we send the process
456-
* a signal, fixup the exception, or oops the kernel.
494+
* Otherwise, we're probably faulting in the vmalloc() area, so try to fix
495+
* that up. Note that we must not take any locks or enable interrupts in
496+
* this case.
457497
*
458-
* NOTE! We MUST NOT take any locks for this case. We may be in an
459-
* interrupt or a critical region, and should only copy the information
460-
* from the master page table, nothing more.
498+
* If vmalloc() fixup fails, that means the non-leaf page tables did not
499+
* contain an entry for this address, so handle this via
500+
* do_kernel_address_page_fault().
461501
*/
462502
#ifdef CONFIG_MMU
463503
static int __kprobes
@@ -523,7 +563,8 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
523563
return 0;
524564

525565
bad_area:
526-
do_bad_area(addr, fsr, regs);
566+
do_kernel_address_page_fault(current->mm, addr, fsr, regs);
567+
527568
return 0;
528569
}
529570
#else /* CONFIG_MMU */
@@ -543,7 +584,16 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
543584
static int
544585
do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
545586
{
587+
/*
588+
* If this is a kernel address, but from user mode, then userspace
589+
* is trying bad stuff. Invoke the branch predictor handling.
590+
* Interrupts are disabled here.
591+
*/
592+
if (addr >= TASK_SIZE && user_mode(regs))
593+
harden_branch_predictor();
594+
546595
do_bad_area(addr, fsr, regs);
596+
547597
return 0;
548598
}
549599
#endif /* CONFIG_ARM_LPAE */

0 commit comments

Comments
 (0)