diff options
Diffstat (limited to 'kernel/signal.c')
| -rw-r--r-- | kernel/signal.c | 40 | 
1 files changed, 40 insertions, 0 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index ef8f2a28d37c..26018c59821d 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2524,6 +2524,26 @@ static int ptrace_signal(int signr, kernel_siginfo_t *info)  	return signr;  } +static void hide_si_addr_tag_bits(struct ksignal *ksig) +{ +	switch (siginfo_layout(ksig->sig, ksig->info.si_code)) { +	case SIL_FAULT: +	case SIL_FAULT_MCEERR: +	case SIL_FAULT_BNDERR: +	case SIL_FAULT_PKUERR: +		ksig->info.si_addr = arch_untagged_si_addr( +			ksig->info.si_addr, ksig->sig, ksig->info.si_code); +		break; +	case SIL_KILL: +	case SIL_TIMER: +	case SIL_POLL: +	case SIL_CHLD: +	case SIL_RT: +	case SIL_SYS: +		break; +	} +} +  bool get_signal(struct ksignal *ksig)  {  	struct sighand_struct *sighand = current->sighand; @@ -2761,6 +2781,10 @@ relock:  	spin_unlock_irq(&sighand->siglock);  	ksig->sig = signr; + +	if (!(ksig->ka.sa.sa_flags & SA_EXPOSE_TAGBITS)) +		hide_si_addr_tag_bits(ksig); +  	return ksig->sig > 0;  } @@ -3985,6 +4009,22 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)  	if (oact)  		*oact = *k; +	/* +	 * Make sure that we never accidentally claim to support SA_UNSUPPORTED, +	 * e.g. by having an architecture use the bit in their uapi. +	 */ +	BUILD_BUG_ON(UAPI_SA_FLAGS & SA_UNSUPPORTED); + +	/* +	 * Clear unknown flag bits in order to allow userspace to detect missing +	 * support for flag bits and to allow the kernel to use non-uapi bits +	 * internally. +	 */ +	if (act) +		act->sa.sa_flags &= UAPI_SA_FLAGS; +	if (oact) +		oact->sa.sa_flags &= UAPI_SA_FLAGS; +  	sigaction_compat_abi(act, oact);  	if (act) {  |