Sun Apr 14 12:51:17 2024 UTC (25d)
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.


(skrll)
diff -r1.14 -r1.15 src/sys/arch/aarch64/aarch64/cpu_machdep.c
diff -r1.8 -r1.9 src/sys/arch/aarch64/aarch64/sig_machdep.c

cvs diff -r1.14 -r1.15 src/sys/arch/aarch64/aarch64/cpu_machdep.c (expand / switch to unified diff)

--- 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
158int 158int
159cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp) 159cpu_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 */
173CTASSERT(sizeof(ucontext_t) % 16 == 0); 177CTASSERT(sizeof(ucontext_t) % 16 == 0);
174 178
175CTASSERT(sizeof(struct reg) == sizeof(__gregset_t)); 179CTASSERT(sizeof(struct reg) == sizeof(__gregset_t));
176CTASSERT(offsetof(struct reg, r_pc) == _REG_PC * sizeof(__greg_t)); 180CTASSERT(offsetof(struct reg, r_pc) == _REG_PC * sizeof(__greg_t));

cvs diff -r1.8 -r1.9 src/sys/arch/aarch64/aarch64/sig_machdep.c (expand / switch to unified diff)

--- 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
45void 45void
46sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) 46sendsig_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;