[PATCH v21 1/2] signal: define the SA_EXPOSE_TAGBITS bit in sa_flags
Eric W. Biederman
ebiederm at xmission.com
Fri Nov 20 18:22:58 EST 2020
Peter Collingbourne <pcc at google.com> writes:
> Architectures that support address tagging, such as arm64, may want to
> expose fault address tag bits to the signal handler to help diagnose
> memory errors. However, these bits have not been previously set,
> and their presence may confuse unaware user applications. Therefore,
> introduce a SA_EXPOSE_TAGBITS flag bit in sa_flags that a signal
> handler may use to explicitly request that the bits are set.
>
> The generic signal handler APIs expect to receive tagged addresses.
> Architectures may specify how to untag addresses in the case where
> SA_EXPOSE_TAGBITS is clear by defining the arch_untagged_si_addr
> function.
>
> Signed-off-by: Peter Collingbourne <pcc at google.com>
> Acked-by: "Eric W. Biederman" <ebiederm at xmission.com>
> Link: https://linux-review.googlesource.com/id/I16dd0ed2081f091fce97be0190cb8caa874c26cb
> ---
> To be applied on top of:
> https://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git signal-for-v5.11
I have merged this first patch into signal-for-v5.11 and pushed
everything out to linux-next.
Eric
> include/linux/signal.h | 14 ++++++++++++++
> include/linux/signal_types.h | 2 +-
> include/uapi/asm-generic/signal-defs.h | 3 +++
> kernel/signal.c | 24 ++++++++++++++++++++++++
> 4 files changed, 42 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/signal.h b/include/linux/signal.h
> index b256f9c65661..205526c4003a 100644
> --- a/include/linux/signal.h
> +++ b/include/linux/signal.h
> @@ -469,4 +469,18 @@ struct seq_file;
> extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
> #endif
>
> +#ifndef arch_untagged_si_addr
> +/*
> + * Given a fault address and a signal and si_code which correspond to the
> + * _sigfault union member, returns the address that must appear in si_addr if
> + * the signal handler does not have SA_EXPOSE_TAGBITS enabled in sa_flags.
> + */
> +static inline void __user *arch_untagged_si_addr(void __user *addr,
> + unsigned long sig,
> + unsigned long si_code)
> +{
> + return addr;
> +}
> +#endif
> +
> #endif /* _LINUX_SIGNAL_H */
> diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> index a7887ad84d36..68e06c75c5b2 100644
> --- a/include/linux/signal_types.h
> +++ b/include/linux/signal_types.h
> @@ -78,6 +78,6 @@ struct ksignal {
>
> #define UAPI_SA_FLAGS \
> (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART | \
> - SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> + SA_NODEFER | SA_RESETHAND | SA_EXPOSE_TAGBITS | __ARCH_UAPI_SA_FLAGS)
>
> #endif /* _LINUX_SIGNAL_TYPES_H */
> diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> index c790f67304ba..fe929e7b77ca 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -20,6 +20,8 @@
> * so this bit allows flag bit support to be detected from userspace while
> * allowing an old kernel to be distinguished from a kernel that supports every
> * flag bit.
> + * SA_EXPOSE_TAGBITS exposes an architecture-defined set of tag bits in
> + * siginfo.si_addr.
> *
> * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
> * Unix names RESETHAND and NODEFER respectively.
> @@ -41,6 +43,7 @@
> /* 0x00000100 used on sparc */
> /* 0x00000200 used on sparc */
> #define SA_UNSUPPORTED 0x00000400
> +#define SA_EXPOSE_TAGBITS 0x00000800
> /* 0x00010000 used on mips */
> /* 0x01000000 used on x86 */
> /* 0x02000000 used on x86 */
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 8f34819e80de..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 @@ bool get_signal(struct ksignal *ksig)
> 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;
> }
More information about the linux-arm-kernel
mailing list