Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

signal: clear non-uapi flag bits when passing/returning sa_flags

Previously we were not clearing non-uapi flag bits in
sigaction.sa_flags when storing the userspace-provided sa_flags or
when returning them via oldact. Start doing so.

This allows userspace to detect missing support for flag bits and
allows the kernel to use non-uapi bits internally, as we are already
doing in arch/x86 for two flag bits. Now that this change is in
place, we no longer need the code in arch/x86 that was hiding these
bits from userspace, so remove it.

This is technically a userspace-visible behavior change for sigaction, as
the unknown bits returned via oldact.sa_flags are no longer set. However,
we are free to define the behavior for unknown bits exactly because
their behavior is currently undefined, so for now we can define the
meaning of each of them to be "clear the bit in oldact.sa_flags unless
the bit becomes known in the future". Furthermore, this behavior is
consistent with OpenBSD [1], illumos [2] and XNU [3] (FreeBSD [4] and
NetBSD [5] fail the syscall if unknown bits are set). So there is some
precedent for this behavior in other kernels, and in particular in XNU,
which is probably the most popular kernel among those that I looked at,
which means that this change is less likely to be a compatibility issue.

Link: [1] https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
Link: [2] https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
Link: [3] https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
Link: [4] https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
Link: [5] https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
Signed-off-by: Peter Collingbourne <pcc@google.com>
Reviewed-by: Dave Martin <Dave.Martin@arm.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Link: https://linux-review.googlesource.com/id/I35aab6f5be932505d90f3b3450c083b4db1eca86
Link: https://lkml.kernel.org/r/878dbcb5f47bc9b11881c81f745c0bef5c23f97f.1605235762.git.pcc@google.com
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

authored by

Peter Collingbourne and committed by
Eric W. Biederman
23acdc76 1d82b789

+26 -7
+2
arch/arm/include/asm/signal.h
··· 17 17 unsigned long sig[_NSIG_WORDS]; 18 18 } sigset_t; 19 19 20 + #define __ARCH_UAPI_SA_FLAGS (SA_THIRTYTWO | SA_RESTORER) 21 + 20 22 #define __ARCH_HAS_SA_RESTORER 21 23 22 24 #include <asm/sigcontext.h>
+2
arch/parisc/include/asm/signal.h
··· 21 21 unsigned long sig[_NSIG_WORDS]; 22 22 } sigset_t; 23 23 24 + #define __ARCH_UAPI_SA_FLAGS _SA_SIGGFAULT 25 + 24 26 #include <asm/sigcontext.h> 25 27 26 28 #endif /* !__ASSEMBLY */
-7
arch/x86/kernel/signal_compat.c
··· 165 165 { 166 166 signal_compat_build_tests(); 167 167 168 - /* Don't leak in-kernel non-uapi flags to user-space */ 169 - if (oact) 170 - oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI); 171 - 172 168 if (!act) 173 169 return; 174 - 175 - /* Don't let flags to be set from userspace */ 176 - act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI); 177 170 178 171 if (in_ia32_syscall()) 179 172 act->sa.sa_flags |= SA_IA32_ABI;
+12
include/linux/signal_types.h
··· 68 68 int sig; 69 69 }; 70 70 71 + #ifndef __ARCH_UAPI_SA_FLAGS 72 + #ifdef SA_RESTORER 73 + #define __ARCH_UAPI_SA_FLAGS SA_RESTORER 74 + #else 75 + #define __ARCH_UAPI_SA_FLAGS 0 76 + #endif 77 + #endif 78 + 79 + #define UAPI_SA_FLAGS \ 80 + (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART | \ 81 + SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS) 82 + 71 83 #endif /* _LINUX_SIGNAL_TYPES_H */
+10
kernel/signal.c
··· 3985 3985 if (oact) 3986 3986 *oact = *k; 3987 3987 3988 + /* 3989 + * Clear unknown flag bits in order to allow userspace to detect missing 3990 + * support for flag bits and to allow the kernel to use non-uapi bits 3991 + * internally. 3992 + */ 3993 + if (act) 3994 + act->sa.sa_flags &= UAPI_SA_FLAGS; 3995 + if (oact) 3996 + oact->sa.sa_flags &= UAPI_SA_FLAGS; 3997 + 3988 3998 sigaction_compat_abi(act, oact); 3989 3999 3990 4000 if (act) {