diff options
Diffstat (limited to 'arch/arm/mm/fault.c')
| -rw-r--r-- | arch/arm/mm/fault.c | 24 | 
1 files changed, 17 insertions, 7 deletions
| diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index bc8779d54a64..a062e07516dd 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -17,6 +17,7 @@  #include <linux/sched/debug.h>  #include <linux/highmem.h>  #include <linux/perf_event.h> +#include <linux/kfence.h>  #include <asm/system_misc.h>  #include <asm/system_info.h> @@ -99,6 +100,11 @@ void show_pte(const char *lvl, struct mm_struct *mm, unsigned long addr)  { }  #endif					/* CONFIG_MMU */ +static inline bool is_write_fault(unsigned int fsr) +{ +	return (fsr & FSR_WRITE) && !(fsr & FSR_CM); +} +  static void die_kernel_fault(const char *msg, struct mm_struct *mm,  			     unsigned long addr, unsigned int fsr,  			     struct pt_regs *regs) @@ -111,7 +117,7 @@ static void die_kernel_fault(const char *msg, struct mm_struct *mm,  	show_pte(KERN_ALERT, mm, addr);  	die("Oops", regs, fsr);  	bust_spinlocks(0); -	do_exit(SIGKILL); +	make_task_dead(SIGKILL);  }  /* @@ -131,10 +137,14 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,  	/*  	 * No handler, we'll have to terminate things with extreme prejudice.  	 */ -	if (addr < PAGE_SIZE) +	if (addr < PAGE_SIZE) {  		msg = "NULL pointer dereference"; -	else +	} else { +		if (kfence_handle_page_fault(addr, is_write_fault(fsr), regs)) +			return; +  		msg = "paging request"; +	}  	die_kernel_fault(msg, mm, addr, fsr, regs);  } @@ -191,8 +201,8 @@ void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)  }  #ifdef CONFIG_MMU -#define VM_FAULT_BADMAP		0x010000 -#define VM_FAULT_BADACCESS	0x020000 +#define VM_FAULT_BADMAP		((__force vm_fault_t)0x010000) +#define VM_FAULT_BADACCESS	((__force vm_fault_t)0x020000)  static inline bool is_permission_fault(unsigned int fsr)  { @@ -261,7 +271,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)  	if (user_mode(regs))  		flags |= FAULT_FLAG_USER; -	if ((fsr & FSR_WRITE) && !(fsr & FSR_CM)) { +	if (is_write_fault(fsr)) {  		flags |= FAULT_FLAG_WRITE;  		vm_flags = VM_WRITE;  	} @@ -312,7 +322,7 @@ retry:  		return 0;  	} -	if (!(fault & VM_FAULT_ERROR) && flags & FAULT_FLAG_ALLOW_RETRY) { +	if (!(fault & VM_FAULT_ERROR)) {  		if (fault & VM_FAULT_RETRY) {  			flags |= FAULT_FLAG_TRIED;  			goto retry; |