kern/58149: aarch64: Cannot return from a signal handler if SP was misaligned when the signal arrived Apply the kernel diff from the PR 1. sendsig_siginfo() previously assumed that user SP was always aligned to 16 bytes and could call signal handlers with SP misaligned. This is a wrong assumption because aarch64 demands that SP is aligned *only while* it's being used to access memory. Now it properly aligns it before pusing anything on the stack. 2. cpu_mcontext_validate() used to check if _REG_SP was aligned and considered the ucontext invalid otherwise. This meant if a signal was sent to a process whose SP was misaligned, the signal handler would fail to return because the ucontext passed from the kernel was an invalid one. Now setcontext(2) doesn't complain about misaligned SP.diff -r1.14 -r1.15 src/sys/arch/aarch64/aarch64/cpu_machdep.c
(skrll)
--- src/sys/arch/aarch64/aarch64/cpu_machdep.c 2023/02/25 00:40:22 1.14
+++ src/sys/arch/aarch64/aarch64/cpu_machdep.c 2024/04/14 12:51:16 1.15
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: cpu_machdep.c,v 1.14 2023/02/25 00:40:22 riastradh Exp $ */ | 1 | /* $NetBSD: cpu_machdep.c,v 1.15 2024/04/14 12:51:16 skrll Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2014, 2019 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2014, 2019 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Matt Thomas of 3am Software Foundry. | 8 | * by Matt Thomas of 3am Software Foundry. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -21,27 +21,27 @@ | @@ -21,27 +21,27 @@ | |||
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | 33 | |||
34 | __KERNEL_RCSID(1, "$NetBSD: cpu_machdep.c,v 1.14 2023/02/25 00:40:22 riastradh Exp $"); | 34 | __KERNEL_RCSID(1, "$NetBSD: cpu_machdep.c,v 1.15 2024/04/14 12:51:16 skrll Exp $"); | |
35 | 35 | |||
36 | #include "opt_multiprocessor.h" | 36 | #include "opt_multiprocessor.h" | |
37 | 37 | |||
38 | #define _INTR_PRIVATE | 38 | #define _INTR_PRIVATE | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/types.h> | 41 | #include <sys/types.h> | |
42 | #include <sys/atomic.h> | 42 | #include <sys/atomic.h> | |
43 | #include <sys/cpu.h> | 43 | #include <sys/cpu.h> | |
44 | #include <sys/intr.h> | 44 | #include <sys/intr.h> | |
45 | #include <sys/kmem.h> | 45 | #include <sys/kmem.h> | |
46 | #include <sys/xcall.h> | 46 | #include <sys/xcall.h> | |
47 | 47 | |||
@@ -148,29 +148,33 @@ dosoftints(void) | @@ -148,29 +148,33 @@ dosoftints(void) | |||
148 | DOSOFTINT(NET); | 148 | DOSOFTINT(NET); | |
149 | DOSOFTINT(BIO); | 149 | DOSOFTINT(BIO); | |
150 | DOSOFTINT(CLOCK); | 150 | DOSOFTINT(CLOCK); | |
151 | panic("dosoftints wtf (softints=%u?, ipl=%d)", softints, opl); | 151 | panic("dosoftints wtf (softints=%u?, ipl=%d)", softints, opl); | |
152 | } | 152 | } | |
153 | splx(s); | 153 | splx(s); | |
154 | } | 154 | } | |
155 | #endif /* !__HAVE_PIC_FAST_SOFTINTS */ | 155 | #endif /* !__HAVE_PIC_FAST_SOFTINTS */ | |
156 | #endif /* __HAVE_FAST_SOFTINTS */ | 156 | #endif /* __HAVE_FAST_SOFTINTS */ | |
157 | 157 | |||
158 | int | 158 | int | |
159 | cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp) | 159 | cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp) | |
160 | { | 160 | { | |
161 | /* | |||
162 | * We intentionally don't verify that _REG_SP is aligned to | |||
163 | * 16-bytes boundaries because it can be legally misaligned as long | |||
164 | * as it's not used for accessing memory. | |||
165 | */ | |||
161 | if ((mcp->__gregs[_REG_SPSR] & ~SPSR_NZCV) | 166 | if ((mcp->__gregs[_REG_SPSR] & ~SPSR_NZCV) | |
162 | || (mcp->__gregs[_REG_PC] & 3) | 167 | || (mcp->__gregs[_REG_PC] & 3)) | |
163 | || (mcp->__gregs[_REG_SP] & 15)) | |||
164 | return EINVAL; | 168 | return EINVAL; | |
165 | 169 | |||
166 | return 0; | 170 | return 0; | |
167 | } | 171 | } | |
168 | 172 | |||
169 | /* | 173 | /* | |
170 | * Since the ucontext_t will be on the stack most of the time, make sure | 174 | * Since the ucontext_t will be on the stack most of the time, make sure | |
171 | * it will keep the stack aligned. | 175 | * it will keep the stack aligned. | |
172 | */ | 176 | */ | |
173 | CTASSERT(sizeof(ucontext_t) % 16 == 0); | 177 | CTASSERT(sizeof(ucontext_t) % 16 == 0); | |
174 | 178 | |||
175 | CTASSERT(sizeof(struct reg) == sizeof(__gregset_t)); | 179 | CTASSERT(sizeof(struct reg) == sizeof(__gregset_t)); | |
176 | CTASSERT(offsetof(struct reg, r_pc) == _REG_PC * sizeof(__greg_t)); | 180 | CTASSERT(offsetof(struct reg, r_pc) == _REG_PC * sizeof(__greg_t)); |
--- src/sys/arch/aarch64/aarch64/sig_machdep.c 2021/11/01 05:07:15 1.8
+++ src/sys/arch/aarch64/aarch64/sig_machdep.c 2024/04/14 12:51:16 1.9
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: sig_machdep.c,v 1.8 2021/11/01 05:07:15 thorpej Exp $ */ | 1 | /* $NetBSD: sig_machdep.c,v 1.9 2024/04/14 12:51:16 skrll Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Matt Thomas of 3am Software Foundry. | 8 | * by Matt Thomas of 3am Software Foundry. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -21,55 +21,61 @@ | @@ -21,55 +21,61 @@ | |||
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | 33 | |||
34 | __KERNEL_RCSID(1, "$NetBSD: sig_machdep.c,v 1.8 2021/11/01 05:07:15 thorpej Exp $"); | 34 | __KERNEL_RCSID(1, "$NetBSD: sig_machdep.c,v 1.9 2024/04/14 12:51:16 skrll Exp $"); | |
35 | 35 | |||
36 | #include <sys/param.h> | 36 | #include <sys/param.h> | |
37 | #include <sys/types.h> | 37 | #include <sys/types.h> | |
38 | #include <sys/cpu.h> | 38 | #include <sys/cpu.h> | |
39 | #include <sys/proc.h> | 39 | #include <sys/proc.h> | |
40 | #include <sys/signalvar.h> | 40 | #include <sys/signalvar.h> | |
41 | #include <sys/siginfo.h> | 41 | #include <sys/siginfo.h> | |
42 | 42 | |||
43 | #include <aarch64/frame.h> | 43 | #include <aarch64/frame.h> | |
44 | 44 | |||
45 | void | 45 | void | |
46 | sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) | 46 | sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) | |
47 | { | 47 | { | |
48 | struct lwp * const l = curlwp; | 48 | struct lwp * const l = curlwp; | |
49 | struct proc * const p = l->l_proc; | 49 | struct proc * const p = l->l_proc; | |
50 | struct trapframe * const tf = lwp_trapframe(l); | 50 | struct trapframe * const tf = lwp_trapframe(l); | |
51 | stack_t * const ss = &l->l_sigstk; | 51 | stack_t * const ss = &l->l_sigstk; | |
52 | const struct sigact_sigdesc * const sd = | 52 | const struct sigact_sigdesc * const sd = | |
53 | &p->p_sigacts->sa_sigdesc[ksi->ksi_signo]; | 53 | &p->p_sigacts->sa_sigdesc[ksi->ksi_signo]; | |
54 | 54 | |||
55 | const uintptr_t handler = (uintptr_t) sd->sd_sigact.sa_handler; | 55 | const uintptr_t handler = (uintptr_t) sd->sd_sigact.sa_handler; | |
56 | const bool onstack_p = (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 | 56 | const bool onstack_p = (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 | |
57 | && (sd->sd_sigact.sa_flags & SA_ONSTACK) != 0; | 57 | && (sd->sd_sigact.sa_flags & SA_ONSTACK) != 0; | |
58 | 58 | |||
59 | vaddr_t sp; | 59 | vaddr_t sp; | |
60 | 60 | |||
61 | sp = onstack_p ? ((vaddr_t)ss->ss_sp + ss->ss_size) & -16 : tf->tf_sp; | 61 | /* | |
62 | * The user stack isn't guaranteed to be aligned to 16 bytes. Align | |||
63 | * it before pushing anything onto it. | |||
64 | */ | |||
65 | sp = onstack_p ? ((vaddr_t)ss->ss_sp + ss->ss_size) : tf->tf_sp; | |||
66 | sp &= -16; | |||
62 | 67 | |||
68 | __CTASSERT(sizeof(ucontext_t) % 16 == 0); | |||
63 | sp -= sizeof(ucontext_t); | 69 | sp -= sizeof(ucontext_t); | |
64 | const vaddr_t ucp = sp; | 70 | const vaddr_t ucp = sp; | |
65 | 71 | |||
66 | sp -= roundup(sizeof(siginfo_t), 16); | 72 | sp -= roundup(sizeof(siginfo_t), 16); | |
67 | const vaddr_t sip = sp; | 73 | const vaddr_t sip = sp; | |
68 | 74 | |||
69 | ucontext_t uc; | 75 | ucontext_t uc; | |
70 | memset(&uc, 0, sizeof(uc)); | 76 | memset(&uc, 0, sizeof(uc)); | |
71 | uc.uc_flags = _UC_SIGMASK; | 77 | uc.uc_flags = _UC_SIGMASK; | |
72 | uc.uc_sigmask = *mask; | 78 | uc.uc_sigmask = *mask; | |
73 | uc.uc_link = l->l_ctxlink; | 79 | uc.uc_link = l->l_ctxlink; | |
74 | uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) | 80 | uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) | |
75 | ? _UC_SETSTACK : _UC_CLRSTACK; | 81 | ? _UC_SETSTACK : _UC_CLRSTACK; |