diff options
Diffstat (limited to 'arch/x86/mm/fault.c')
| -rw-r--r-- | arch/x86/mm/fault.c | 26 | 
1 files changed, 18 insertions, 8 deletions
| diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index b2eefdefc108..84a2c8c4af73 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -710,7 +710,8 @@ oops:  static noinline void  kernelmode_fixup_or_oops(struct pt_regs *regs, unsigned long error_code, -			 unsigned long address, int signal, int si_code) +			 unsigned long address, int signal, int si_code, +			 u32 pkey)  {  	WARN_ON_ONCE(user_mode(regs)); @@ -735,8 +736,12 @@ kernelmode_fixup_or_oops(struct pt_regs *regs, unsigned long error_code,  			set_signal_archinfo(address, error_code); -			/* XXX: hwpoison faults will set the wrong code. */ -			force_sig_fault(signal, si_code, (void __user *)address); +			if (si_code == SEGV_PKUERR) { +				force_sig_pkuerr((void __user *)address, pkey); +			} else { +				/* XXX: hwpoison faults will set the wrong code. */ +				force_sig_fault(signal, si_code, (void __user *)address); +			}  		}  		/* @@ -798,7 +803,8 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,  	struct task_struct *tsk = current;  	if (!user_mode(regs)) { -		kernelmode_fixup_or_oops(regs, error_code, address, pkey, si_code); +		kernelmode_fixup_or_oops(regs, error_code, address, +					 SIGSEGV, si_code, pkey);  		return;  	} @@ -930,7 +936,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,  {  	/* Kernel mode? Handle exceptions or die: */  	if (!user_mode(regs)) { -		kernelmode_fixup_or_oops(regs, error_code, address, SIGBUS, BUS_ADRERR); +		kernelmode_fixup_or_oops(regs, error_code, address, +					 SIGBUS, BUS_ADRERR, ARCH_DEFAULT_PKEY);  		return;  	} @@ -1396,7 +1403,8 @@ good_area:  		 */  		if (!user_mode(regs))  			kernelmode_fixup_or_oops(regs, error_code, address, -						 SIGBUS, BUS_ADRERR); +						 SIGBUS, BUS_ADRERR, +						 ARCH_DEFAULT_PKEY);  		return;  	} @@ -1416,7 +1424,8 @@ good_area:  		return;  	if (fatal_signal_pending(current) && !user_mode(regs)) { -		kernelmode_fixup_or_oops(regs, error_code, address, 0, 0); +		kernelmode_fixup_or_oops(regs, error_code, address, +					 0, 0, ARCH_DEFAULT_PKEY);  		return;  	} @@ -1424,7 +1433,8 @@ good_area:  		/* Kernel mode? Handle exceptions or die: */  		if (!user_mode(regs)) {  			kernelmode_fixup_or_oops(regs, error_code, address, -						 SIGSEGV, SEGV_MAPERR); +						 SIGSEGV, SEGV_MAPERR, +						 ARCH_DEFAULT_PKEY);  			return;  		} |