1 /* $NetBSD: svr4_signal.c,v 1.63 2008/04/24 18:39:23 ad Exp $ */
4 * Copyright (c) 1994, 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas and by Charles M. Hannum.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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
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
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: svr4_signal.c,v 1.63 2008/04/24 18:39:23 ad Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/namei.h>
39 #include <sys/filedesc.h>
40 #include <sys/ioctl.h>
41 #include <sys/mount.h>
42 #include <sys/kernel.h>
43 #include <sys/signal.h>
44 #include <sys/signalvar.h>
45 #include <sys/malloc.h>
48 #include <sys/syscallargs.h>
50 #include <uvm/uvm_extern.h>
52 #include <compat/svr4/svr4_types.h>
53 #include <compat/svr4/svr4_signal.h>
54 #include <compat/svr4/svr4_lwp.h>
55 #include <compat/svr4/svr4_ucontext.h>
56 #include <compat/svr4/svr4_syscallargs.h>
57 #include <compat/svr4/svr4_util.h>
59 #include <compat/common/compat_sigaltstack.h>
61 #define svr4_sigmask(n) (1 << (((n) - 1) & 31))
62 #define svr4_sigword(n) (((n) - 1) >> 5)
63 #define svr4_sigemptyset(s) memset((s), 0, sizeof(*(s)))
64 #define svr4_sigismember(s, n) ((s)->bits[svr4_sigword(n)] & svr4_sigmask(n))
65 #define svr4_sigaddset(s, n) ((s)->bits[svr4_sigword(n)] |= svr4_sigmask(n))
67 static inline void svr4_sigfillset(svr4_sigset_t
*);
68 void svr4_to_native_sigaction(const struct svr4_sigaction
*,
70 void native_to_svr4_sigaction(const struct sigaction
*,
71 struct svr4_sigaction
*);
73 extern const int native_to_svr4_signo
[];
74 extern const int svr4_to_native_signo
[];
77 svr4_sigfillset(svr4_sigset_t
*s
)
82 for (i
= 1; i
< SVR4_NSIG
; i
++)
83 if (svr4_to_native_signo
[i
] != 0)
88 svr4_to_native_sigset(const svr4_sigset_t
*sss
, sigset_t
*bss
)
93 for (i
= 1; i
< SVR4_NSIG
; i
++) {
94 if (svr4_sigismember(sss
, i
)) {
95 newsig
= svr4_to_native_signo
[i
];
97 sigaddset(bss
, newsig
);
104 native_to_svr4_sigset(const sigset_t
*bss
, svr4_sigset_t
*sss
)
108 svr4_sigemptyset(sss
);
109 for (i
= 1; i
< NSIG
; i
++) {
110 if (sigismember(bss
, i
)) {
111 newsig
= native_to_svr4_signo
[i
];
113 svr4_sigaddset(sss
, newsig
);
119 * XXX: Only a subset of the flags is currently implemented.
122 svr4_to_native_sigaction(const struct svr4_sigaction
*ssa
, struct sigaction
*bsa
)
125 bsa
->sa_handler
= (sig_t
) ssa
->svr4_sa_handler
;
126 svr4_to_native_sigset(&ssa
->svr4_sa_mask
, &bsa
->sa_mask
);
128 if ((ssa
->svr4_sa_flags
& SVR4_SA_ONSTACK
) != 0)
129 bsa
->sa_flags
|= SA_ONSTACK
;
130 if ((ssa
->svr4_sa_flags
& SVR4_SA_RESETHAND
) != 0)
131 bsa
->sa_flags
|= SA_RESETHAND
;
132 if ((ssa
->svr4_sa_flags
& SVR4_SA_RESTART
) != 0)
133 bsa
->sa_flags
|= SA_RESTART
;
134 if ((ssa
->svr4_sa_flags
& SVR4_SA_SIGINFO
) != 0)
135 bsa
->sa_flags
|= SA_SIGINFO
;
136 if ((ssa
->svr4_sa_flags
& SVR4_SA_NODEFER
) != 0)
137 bsa
->sa_flags
|= SA_NODEFER
;
138 if ((ssa
->svr4_sa_flags
& SVR4_SA_NOCLDWAIT
) != 0)
139 bsa
->sa_flags
|= SA_NOCLDWAIT
;
140 if ((ssa
->svr4_sa_flags
& SVR4_SA_NOCLDSTOP
) != 0)
141 bsa
->sa_flags
|= SA_NOCLDSTOP
;
142 if ((ssa
->svr4_sa_flags
& ~SVR4_SA_ALLBITS
) != 0) {
143 DPRINTF(("svr4_to_native_sigaction: extra bits %x ignored\n",
144 ssa
->svr4_sa_flags
& ~SVR4_SA_ALLBITS
));
149 native_to_svr4_sigaction(const struct sigaction
*bsa
, struct svr4_sigaction
*ssa
)
152 ssa
->svr4_sa_handler
= (svr4_sig_t
) bsa
->sa_handler
;
153 native_to_svr4_sigset(&bsa
->sa_mask
, &ssa
->svr4_sa_mask
);
154 ssa
->svr4_sa_flags
= 0;
155 if ((bsa
->sa_flags
& SA_ONSTACK
) != 0)
156 ssa
->svr4_sa_flags
|= SVR4_SA_ONSTACK
;
157 if ((bsa
->sa_flags
& SA_RESETHAND
) != 0)
158 ssa
->svr4_sa_flags
|= SVR4_SA_RESETHAND
;
159 if ((bsa
->sa_flags
& SA_RESTART
) != 0)
160 ssa
->svr4_sa_flags
|= SVR4_SA_RESTART
;
161 if ((bsa
->sa_flags
& SA_NODEFER
) != 0)
162 ssa
->svr4_sa_flags
|= SVR4_SA_NODEFER
;
163 if ((bsa
->sa_flags
& SA_NOCLDSTOP
) != 0)
164 ssa
->svr4_sa_flags
|= SVR4_SA_NOCLDSTOP
;
168 svr4_sys_sigaction(struct lwp
*l
, const struct svr4_sys_sigaction_args
*uap
, register_t
*retval
)
171 syscallarg(int) signum;
172 syscallarg(const struct svr4_sigaction *) nsa;
173 syscallarg(struct svr4_sigaction *) osa;
175 struct svr4_sigaction nssa
, ossa
;
176 struct sigaction nbsa
, obsa
;
179 if (SCARG(uap
, nsa
)) {
180 error
= copyin(SCARG(uap
, nsa
), &nssa
, sizeof(nssa
));
183 svr4_to_native_sigaction(&nssa
, &nbsa
);
185 error
= sigaction1(l
, svr4_to_native_signo
[SVR4_SIGNO(SCARG(uap
, signum
))],
186 SCARG(uap
, nsa
) ? &nbsa
: 0, SCARG(uap
, osa
) ? &obsa
: 0,
190 if (SCARG(uap
, osa
)) {
191 native_to_svr4_sigaction(&obsa
, &ossa
);
192 error
= copyout(&ossa
, SCARG(uap
, osa
), sizeof(ossa
));
200 svr4_sys_sigaltstack(struct lwp
*l
, const struct svr4_sys_sigaltstack_args
*uap
, register_t
*retval
)
203 syscallarg(const struct svr4_sigaltstack *) nss;
204 syscallarg(struct svr4_sigaltstack *) oss;
206 compat_sigaltstack(uap
, svr4_sigaltstack
,
207 SVR4_SS_ONSTACK
, SVR4_SS_DISABLE
);
211 * Stolen from the ibcs2 one
214 svr4_sys_signal(struct lwp
*l
, const struct svr4_sys_signal_args
*uap
, register_t
*retval
)
217 syscallarg(int) signum;
218 syscallarg(svr4_sig_t) handler;
220 int signum
= svr4_to_native_signo
[SVR4_SIGNO(SCARG(uap
, signum
))];
221 struct proc
*p
= l
->l_proc
;
222 struct sigaction nbsa
, obsa
;
226 if (signum
<= 0 || signum
>= SVR4_NSIG
)
229 switch (SVR4_SIGCALL(SCARG(uap
, signum
))) {
230 case SVR4_SIGDEFER_MASK
:
231 if (SCARG(uap
, handler
) == SVR4_SIG_HOLD
)
235 case SVR4_SIGNAL_MASK
:
236 nbsa
.sa_handler
= (sig_t
)SCARG(uap
, handler
);
237 sigemptyset(&nbsa
.sa_mask
);
239 error
= sigaction1(l
, signum
, &nbsa
, &obsa
, NULL
, 0);
242 *retval
= (u_int
)(u_long
)obsa
.sa_handler
;
245 case SVR4_SIGHOLD_MASK
:
248 sigaddset(&ss
, signum
);
249 mutex_enter(p
->p_lock
);
250 error
= sigprocmask1(l
, SIG_BLOCK
, &ss
, 0);
251 mutex_exit(p
->p_lock
);
254 case SVR4_SIGRELSE_MASK
:
256 sigaddset(&ss
, signum
);
257 mutex_enter(p
->p_lock
);
258 error
= sigprocmask1(l
, SIG_UNBLOCK
, &ss
, 0);
259 mutex_exit(p
->p_lock
);
262 case SVR4_SIGIGNORE_MASK
:
263 nbsa
.sa_handler
= SIG_IGN
;
264 sigemptyset(&nbsa
.sa_mask
);
266 return (sigaction1(l
, signum
, &nbsa
, 0, NULL
, 0));
268 case SVR4_SIGPAUSE_MASK
:
269 ss
= l
->l_sigmask
; /* XXXAD locking */
270 sigdelset(&ss
, signum
);
271 return (sigsuspend1(l
, &ss
));
279 svr4_sys_sigprocmask(struct lwp
*l
, const struct svr4_sys_sigprocmask_args
*uap
, register_t
*retval
)
283 syscallarg(const svr4_sigset_t *) set;
284 syscallarg(svr4_sigset_t *) oset;
286 struct proc
*p
= l
->l_proc
;
287 svr4_sigset_t nsss
, osss
;
293 * Initialize how to 0 to avoid a compiler warning. Note that
294 * this is safe because of the check in the default: case.
298 switch (SCARG(uap
, how
)) {
302 case SVR4_SIG_UNBLOCK
:
305 case SVR4_SIG_SETMASK
:
314 if (SCARG(uap
, set
)) {
315 error
= copyin(SCARG(uap
, set
), &nsss
, sizeof(nsss
));
318 svr4_to_native_sigset(&nsss
, &nbss
);
320 mutex_enter(p
->p_lock
);
321 error
= sigprocmask1(l
, how
,
322 SCARG(uap
, set
) ? &nbss
: NULL
, SCARG(uap
, oset
) ? &obss
: NULL
);
323 mutex_exit(p
->p_lock
);
326 if (SCARG(uap
, oset
)) {
327 native_to_svr4_sigset(&obss
, &osss
);
328 error
= copyout(&osss
, SCARG(uap
, oset
), sizeof(osss
));
336 svr4_sys_sigpending(struct lwp
*l
, const struct svr4_sys_sigpending_args
*uap
, register_t
*retval
)
339 syscallarg(int) what;
340 syscallarg(svr4_sigset_t *) set;
345 switch (SCARG(uap
, what
)) {
346 case 1: /* sigpending */
347 sigpending1(l
, &bss
);
348 native_to_svr4_sigset(&bss
, &sss
);
351 case 2: /* sigfillset */
352 svr4_sigfillset(&sss
);
358 return (copyout(&sss
, SCARG(uap
, set
), sizeof(sss
)));
362 svr4_sys_sigsuspend(struct lwp
*l
, const struct svr4_sys_sigsuspend_args
*uap
, register_t
*retval
)
365 syscallarg(const svr4_sigset_t *) set;
371 if (SCARG(uap
, set
)) {
372 error
= copyin(SCARG(uap
, set
), &sss
, sizeof(sss
));
375 svr4_to_native_sigset(&sss
, &bss
);
378 return (sigsuspend1(l
, SCARG(uap
, set
) ? &bss
: 0));
382 svr4_sys_pause(struct lwp
*l
, const void *v
, register_t
*retval
)
385 return (sigsuspend1(l
, 0));
389 svr4_sys_kill(struct lwp
*l
, const struct svr4_sys_kill_args
*uap
, register_t
*retval
)
393 syscallarg(int) signum;
395 struct sys_kill_args ka
;
397 SCARG(&ka
, pid
) = SCARG(uap
, pid
);
398 SCARG(&ka
, signum
) = svr4_to_native_signo
[SVR4_SIGNO(SCARG(uap
, signum
))];
399 return sys_kill(l
, &ka
, retval
);
403 svr4_getcontext(struct lwp
*l
, struct svr4_ucontext
*uc
)
406 struct proc
*p
= l
->l_proc
;
408 svr4_getmcontext(l
, &uc
->uc_mcontext
, &uc
->uc_flags
);
409 uc
->uc_link
= l
->l_ctxlink
;
412 * The (unsupplied) definition of the `current execution stack'
413 * in the System V Interface Definition appears to allow returning
414 * the main context stack.
416 if ((l
->l_sigstk
.ss_flags
& SS_ONSTACK
) == 0) {
417 uc
->uc_stack
.ss_sp
= (void *)USRSTACK
;
418 uc
->uc_stack
.ss_size
= ctob(p
->p_vmspace
->vm_ssize
);
419 uc
->uc_stack
.ss_flags
= 0; /* XXX, def. is Very Fishy */
421 /* Simply copy alternate signal execution stack. */
422 uc
->uc_stack
.ss_sp
= l
->l_sigstk
.ss_sp
;
423 uc
->uc_stack
.ss_size
= l
->l_sigstk
.ss_size
;
424 uc
->uc_stack
.ss_flags
= l
->l_sigstk
.ss_flags
;
426 (void)sigprocmask1(l
, 0, NULL
, &mask
);
428 native_to_svr4_sigset(&mask
, &uc
->uc_sigmask
);
429 uc
->uc_flags
|= _UC_SIGMASK
| _UC_STACK
;
434 svr4_setcontext(struct lwp
*l
, struct svr4_ucontext
*uc
)
436 struct proc
*p
= l
->l_proc
;
439 if (uc
->uc_flags
& _UC_SIGMASK
) {
440 svr4_to_native_sigset(&uc
->uc_sigmask
, &mask
);
441 mutex_enter(p
->p_lock
);
442 sigprocmask1(l
, SIG_SETMASK
, &mask
, NULL
);
443 mutex_exit(p
->p_lock
);
446 /* Ignore the stack; see comment in svr4_getcontext. */
448 l
->l_ctxlink
= uc
->uc_link
;
449 svr4_setmcontext(l
, &uc
->uc_mcontext
, uc
->uc_flags
);
455 svr4_sys_context(struct lwp
*l
, const struct svr4_sys_context_args
*uap
, register_t
*retval
)
458 syscallarg(int) func;
459 syscallarg(struct svr4_ucontext *) uc;
465 switch (SCARG(uap
, func
)) {
466 case SVR4_GETCONTEXT
:
467 DPRINTF(("getcontext(%p)\n", SCARG(uap
, uc
)));
468 svr4_getcontext(l
, &uc
);
469 return (copyout(&uc
, SCARG(uap
, uc
), sizeof (*SCARG(uap
, uc
))));
472 case SVR4_SETCONTEXT
:
473 DPRINTF(("setcontext(%p)\n", SCARG(uap
, uc
)));
474 error
= copyin(SCARG(uap
, uc
), &uc
, sizeof (uc
));
477 svr4_setcontext(l
, &uc
);
481 DPRINTF(("context(%d, %p)\n", SCARG(uap
, func
),