xref: /freebsd/sys/compat/linux/linux_signal.c (revision d66a506616078adf4d266a309f979ffd95fe634f)
1c21dee17SSøren Schmidt /*-
2c21dee17SSøren Schmidt  * Copyright (c) 1994-1995 S�ren Schmidt
3c21dee17SSøren Schmidt  * All rights reserved.
4c21dee17SSøren Schmidt  *
5c21dee17SSøren Schmidt  * Redistribution and use in source and binary forms, with or without
6c21dee17SSøren Schmidt  * modification, are permitted provided that the following conditions
7c21dee17SSøren Schmidt  * are met:
8c21dee17SSøren Schmidt  * 1. Redistributions of source code must retain the above copyright
9c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer
10c21dee17SSøren Schmidt  *    in this position and unchanged.
11c21dee17SSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
12c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
13c21dee17SSøren Schmidt  *    documentation and/or other materials provided with the distribution.
14c21dee17SSøren Schmidt  * 3. The name of the author may not be used to endorse or promote products
15c21dee17SSøren Schmidt  *    derived from this software withough specific prior written permission
16c21dee17SSøren Schmidt  *
17c21dee17SSøren Schmidt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18c21dee17SSøren Schmidt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19c21dee17SSøren Schmidt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20c21dee17SSøren Schmidt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21c21dee17SSøren Schmidt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22c21dee17SSøren Schmidt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23c21dee17SSøren Schmidt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24c21dee17SSøren Schmidt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25c21dee17SSøren Schmidt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26c21dee17SSøren Schmidt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27c21dee17SSøren Schmidt  *
28d66a5066SPeter Wemm  *  $Id: linux_signal.c,v 1.3 1995/12/15 03:06:56 peter Exp $
29c21dee17SSøren Schmidt  */
30c21dee17SSøren Schmidt 
31c21dee17SSøren Schmidt #include <sys/param.h>
32c21dee17SSøren Schmidt #include <sys/systm.h>
331f3dad5aSBruce Evans #include <sys/sysproto.h>
34c21dee17SSøren Schmidt #include <sys/proc.h>
35c21dee17SSøren Schmidt #include <sys/exec.h>
36c21dee17SSøren Schmidt #include <sys/signal.h>
37c21dee17SSøren Schmidt #include <sys/signalvar.h>
38c21dee17SSøren Schmidt 
39c21dee17SSøren Schmidt #include <i386/linux/linux.h>
40d66a5066SPeter Wemm #include <i386/linux/linux_proto.h>
41d66a5066SPeter Wemm #include <i386/linux/linux_util.h>
42c21dee17SSøren Schmidt 
43c21dee17SSøren Schmidt static sigset_t
44d66a5066SPeter Wemm linux_to_bsd_sigset(linux_sigset_t mask) {
45d66a5066SPeter Wemm     int b, l;
46c21dee17SSøren Schmidt     sigset_t new = 0;
47c21dee17SSøren Schmidt 
48d66a5066SPeter Wemm     for (l = 1; l <= LINUX_NSIG; l++) {
49d66a5066SPeter Wemm 	if (mask & (1 << (l - 1))) {
50d66a5066SPeter Wemm 	    if ((b = linux_to_bsd_signal[l]))
51d66a5066SPeter Wemm 		new |= (1 << (b - 1));
52d66a5066SPeter Wemm 	}
53d66a5066SPeter Wemm     }
54c21dee17SSøren Schmidt     return new;
55c21dee17SSøren Schmidt }
56c21dee17SSøren Schmidt 
57c21dee17SSøren Schmidt static linux_sigset_t
58d66a5066SPeter Wemm bsd_to_linux_sigset(sigset_t mask) {
59d66a5066SPeter Wemm     int b, l;
60c21dee17SSøren Schmidt     sigset_t new = 0;
61c21dee17SSøren Schmidt 
62d66a5066SPeter Wemm     for (b = 1; b <= NSIG; b++) {
63d66a5066SPeter Wemm 	if (mask & (1 << (b - 1))) {
64d66a5066SPeter Wemm 	    if ((l = bsd_to_linux_signal[b]))
65d66a5066SPeter Wemm 		new |= (1 << (l - 1));
66d66a5066SPeter Wemm 	}
67d66a5066SPeter Wemm     }
68c21dee17SSøren Schmidt     return new;
69c21dee17SSøren Schmidt }
70c21dee17SSøren Schmidt 
71d66a5066SPeter Wemm void
72d66a5066SPeter Wemm linux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa)
73d66a5066SPeter Wemm {
74d66a5066SPeter Wemm     bsa->sa_mask = linux_to_bsd_sigset(lsa->sa_mask);
75d66a5066SPeter Wemm     bsa->sa_handler = lsa->sa_handler;
76d66a5066SPeter Wemm     bsa->sa_flags = 0;
77d66a5066SPeter Wemm     if (lsa->sa_flags & LINUX_SA_NOCLDSTOP)
78d66a5066SPeter Wemm 	bsa->sa_flags |= SA_NOCLDSTOP;
79d66a5066SPeter Wemm     if (lsa->sa_flags & LINUX_SA_ONSTACK)
80d66a5066SPeter Wemm 	bsa->sa_flags |= SA_ONSTACK;
81d66a5066SPeter Wemm     if (lsa->sa_flags & LINUX_SA_RESTART)
82d66a5066SPeter Wemm 	bsa->sa_flags |= SA_RESTART;
83d66a5066SPeter Wemm     if (lsa->sa_flags & LINUX_SA_ONESHOT)
84d66a5066SPeter Wemm 	bsa->sa_flags |= SA_RESETHAND;
85d66a5066SPeter Wemm     if (lsa->sa_flags & LINUX_SA_NOMASK)
86d66a5066SPeter Wemm 	bsa->sa_flags |= SA_NODEFER;
87d66a5066SPeter Wemm }
88d66a5066SPeter Wemm 
89d66a5066SPeter Wemm void
90d66a5066SPeter Wemm bsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa)
91d66a5066SPeter Wemm {
92d66a5066SPeter Wemm     lsa->sa_handler = bsa->sa_handler;
93d66a5066SPeter Wemm     lsa->sa_restorer = NULL;	/* unsupported */
94d66a5066SPeter Wemm     lsa->sa_mask = bsd_to_linux_sigset(bsa->sa_mask);
95d66a5066SPeter Wemm     lsa->sa_flags = 0;
96d66a5066SPeter Wemm     if (bsa->sa_flags & SA_NOCLDSTOP)
97d66a5066SPeter Wemm 	lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
98d66a5066SPeter Wemm     if (bsa->sa_flags & SA_ONSTACK)
99d66a5066SPeter Wemm 	lsa->sa_flags |= LINUX_SA_ONSTACK;
100d66a5066SPeter Wemm     if (bsa->sa_flags & SA_RESTART)
101d66a5066SPeter Wemm 	lsa->sa_flags |= LINUX_SA_RESTART;
102d66a5066SPeter Wemm     if (bsa->sa_flags & SA_RESETHAND)
103d66a5066SPeter Wemm 	lsa->sa_flags |= LINUX_SA_ONESHOT;
104d66a5066SPeter Wemm     if (bsa->sa_flags & SA_NODEFER)
105d66a5066SPeter Wemm 	lsa->sa_flags |= LINUX_SA_NOMASK;
106d66a5066SPeter Wemm }
107c21dee17SSøren Schmidt 
108c21dee17SSøren Schmidt int
109c21dee17SSøren Schmidt linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval)
110c21dee17SSøren Schmidt {
111c21dee17SSøren Schmidt     linux_sigaction_t linux_sa;
112c21dee17SSøren Schmidt     struct sigaction *nsa = NULL, *osa = NULL, bsd_sa;
113d66a5066SPeter Wemm     struct sigaction_args sa;
114c21dee17SSøren Schmidt     int error;
115d66a5066SPeter Wemm     caddr_t sg = stackgap_init();
116c21dee17SSøren Schmidt 
117c21dee17SSøren Schmidt #ifdef DEBUG
118d66a5066SPeter Wemm     printf("Linux-emul(%d): sigaction(%d, %08x, %08x)\n", p->p_pid, args->sig,
119d66a5066SPeter Wemm 	args->nsa, args->osa);
120c21dee17SSøren Schmidt #endif
121d66a5066SPeter Wemm 
122c21dee17SSøren Schmidt     if (args->osa)
123d66a5066SPeter Wemm 	osa = (struct sigaction *)stackgap_alloc(&sg, sizeof(struct sigaction));
124c21dee17SSøren Schmidt 
125c21dee17SSøren Schmidt     if (args->nsa) {
126d66a5066SPeter Wemm 	nsa = (struct sigaction *)stackgap_alloc(&sg, sizeof(struct sigaction));
127c21dee17SSøren Schmidt 	if (error = copyin(args->nsa, &linux_sa, sizeof(linux_sigaction_t)))
128c21dee17SSøren Schmidt 	    return error;
129d66a5066SPeter Wemm 	linux_to_bsd_sigaction(&linux_sa, &bsd_sa);
130c21dee17SSøren Schmidt 	if (error = copyout(&bsd_sa, nsa, sizeof(struct sigaction)))
131c21dee17SSøren Schmidt 	    return error;
132c21dee17SSøren Schmidt     }
133ef04503dSPeter Wemm     sa.signum = linux_to_bsd_signal[args->sig];
134c21dee17SSøren Schmidt     sa.nsa = nsa;
135c21dee17SSøren Schmidt     sa.osa = osa;
136c21dee17SSøren Schmidt     if ((error = sigaction(p, &sa, retval)))
137c21dee17SSøren Schmidt 	return error;
138c21dee17SSøren Schmidt 
139c21dee17SSøren Schmidt     if (args->osa) {
140c21dee17SSøren Schmidt 	if (error = copyin(osa, &bsd_sa, sizeof(struct sigaction)))
141c21dee17SSøren Schmidt 	    return error;
142d66a5066SPeter Wemm 	bsd_to_linux_sigaction(&bsd_sa, &linux_sa);
143c21dee17SSøren Schmidt 	if (error = copyout(&linux_sa, args->osa, sizeof(linux_sigaction_t)))
144c21dee17SSøren Schmidt 	    return error;
145c21dee17SSøren Schmidt     }
146c21dee17SSøren Schmidt     return 0;
147c21dee17SSøren Schmidt }
148c21dee17SSøren Schmidt 
149d66a5066SPeter Wemm int
150d66a5066SPeter Wemm linux_signal(struct proc *p, struct linux_signal_args *args, int *retval)
151d66a5066SPeter Wemm {
152d66a5066SPeter Wemm     caddr_t sg;
153d66a5066SPeter Wemm     struct sigaction_args sa_args;
154d66a5066SPeter Wemm     struct sigaction *osa, *nsa, tmpsa;
155d66a5066SPeter Wemm     int error;
156d66a5066SPeter Wemm 
157d66a5066SPeter Wemm #ifdef DEBUG
158d66a5066SPeter Wemm     printf("Linux-emul(%d): signal(%d, %08x)\n", p->p_pid,
159d66a5066SPeter Wemm 	    args->sig, args->handler);
160d66a5066SPeter Wemm #endif
161d66a5066SPeter Wemm     sg = stackgap_init();
162d66a5066SPeter Wemm     nsa = stackgap_alloc(&sg, sizeof *nsa);
163d66a5066SPeter Wemm     osa = stackgap_alloc(&sg, sizeof *osa);
164d66a5066SPeter Wemm 
165d66a5066SPeter Wemm     tmpsa.sa_handler = args->handler;
166d66a5066SPeter Wemm     tmpsa.sa_mask = (sigset_t) 0;
167d66a5066SPeter Wemm     tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER;
168d66a5066SPeter Wemm     if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
169d66a5066SPeter Wemm 	return error;
170d66a5066SPeter Wemm 
171d66a5066SPeter Wemm     sa_args.signum = linux_to_bsd_signal[args->sig];
172d66a5066SPeter Wemm     sa_args.osa = osa;
173d66a5066SPeter Wemm     sa_args.nsa = nsa;
174d66a5066SPeter Wemm     if ((error = sigaction(p, &sa_args, retval)))
175d66a5066SPeter Wemm 	return error;
176d66a5066SPeter Wemm 
177d66a5066SPeter Wemm     if ((error = copyin(osa, &tmpsa, sizeof *osa)))
178d66a5066SPeter Wemm 	return error;
179d66a5066SPeter Wemm 
180d66a5066SPeter Wemm     *retval = (int)tmpsa.sa_handler;
181d66a5066SPeter Wemm 
182d66a5066SPeter Wemm     return 0;
183d66a5066SPeter Wemm }
184d66a5066SPeter Wemm 
185c21dee17SSøren Schmidt 
186c21dee17SSøren Schmidt int
187c21dee17SSøren Schmidt linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
188c21dee17SSøren Schmidt 		  int *retval)
189c21dee17SSøren Schmidt {
190c21dee17SSøren Schmidt     int error, s;
191c21dee17SSøren Schmidt     sigset_t mask;
192c21dee17SSøren Schmidt     sigset_t omask;
193c21dee17SSøren Schmidt 
194c21dee17SSøren Schmidt #ifdef DEBUG
195c21dee17SSøren Schmidt     printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how);
196c21dee17SSøren Schmidt #endif
197d66a5066SPeter Wemm 
198d66a5066SPeter Wemm     *retval = 0;
199d66a5066SPeter Wemm 
200c21dee17SSøren Schmidt     if (args->omask != NULL) {
201d66a5066SPeter Wemm 	omask = bsd_to_linux_sigset(p->p_sigmask);
202c21dee17SSøren Schmidt 	if (error = copyout(&omask, args->omask, sizeof(sigset_t)))
203c21dee17SSøren Schmidt 	    return error;
204c21dee17SSøren Schmidt     }
205c21dee17SSøren Schmidt     if (!(args->mask))
206c21dee17SSøren Schmidt 	return 0;
207c21dee17SSøren Schmidt     if (error = copyin(args->mask, &mask, sizeof(linux_sigset_t)))
208c21dee17SSøren Schmidt 	return error;
209c21dee17SSøren Schmidt 
210d66a5066SPeter Wemm     mask = linux_to_bsd_sigset(mask);
211c21dee17SSøren Schmidt     s = splhigh();
212c21dee17SSøren Schmidt     switch (args->how) {
213c21dee17SSøren Schmidt     case LINUX_SIG_BLOCK:
214d66a5066SPeter Wemm 	p->p_sigmask |= (mask & ~sigcantmask);
215c21dee17SSøren Schmidt 	break;
216c21dee17SSøren Schmidt     case LINUX_SIG_UNBLOCK:
217c21dee17SSøren Schmidt 	p->p_sigmask &= ~mask;
218c21dee17SSøren Schmidt 	break;
219c21dee17SSøren Schmidt     case LINUX_SIG_SETMASK:
220d66a5066SPeter Wemm 	p->p_sigmask = (mask & ~sigcantmask);
221c21dee17SSøren Schmidt 	break;
222c21dee17SSøren Schmidt     default:
223c21dee17SSøren Schmidt 	error = EINVAL;
224c21dee17SSøren Schmidt 	break;
225c21dee17SSøren Schmidt     }
226c21dee17SSøren Schmidt     splx(s);
227c21dee17SSøren Schmidt     return error;
228c21dee17SSøren Schmidt }
229c21dee17SSøren Schmidt 
230c21dee17SSøren Schmidt int
231d66a5066SPeter Wemm linux_siggetmask(struct proc *p, struct linux_siggetmask_args *args, int *retval)
232c21dee17SSøren Schmidt {
233c21dee17SSøren Schmidt #ifdef DEBUG
234c21dee17SSøren Schmidt     printf("Linux-emul(%d): siggetmask()\n", p->p_pid);
235c21dee17SSøren Schmidt #endif
236d66a5066SPeter Wemm     *retval = bsd_to_linux_sigset(p->p_sigmask);
237c21dee17SSøren Schmidt     return 0;
238c21dee17SSøren Schmidt }
239c21dee17SSøren Schmidt 
240c21dee17SSøren Schmidt int
241c21dee17SSøren Schmidt linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args,int *retval)
242c21dee17SSøren Schmidt {
243c21dee17SSøren Schmidt     int s;
244d66a5066SPeter Wemm     sigset_t mask;
245c21dee17SSøren Schmidt 
246c21dee17SSøren Schmidt #ifdef DEBUG
247c21dee17SSøren Schmidt     printf("Linux-emul(%d): sigsetmask(%08x)\n", p->p_pid, args->mask);
248c21dee17SSøren Schmidt #endif
249d66a5066SPeter Wemm     *retval = bsd_to_linux_sigset(p->p_sigmask);
250d66a5066SPeter Wemm 
251d66a5066SPeter Wemm     mask = linux_to_bsd_sigset(args->mask);
252c21dee17SSøren Schmidt     s = splhigh();
253d66a5066SPeter Wemm     p->p_sigmask = mask & ~sigcantmask;
254c21dee17SSøren Schmidt     splx(s);
255c21dee17SSøren Schmidt     return 0;
256c21dee17SSøren Schmidt }
257c21dee17SSøren Schmidt 
258c21dee17SSøren Schmidt int
259c21dee17SSøren Schmidt linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval)
260c21dee17SSøren Schmidt {
261c21dee17SSøren Schmidt     linux_sigset_t linux_sig;
262c21dee17SSøren Schmidt 
263c21dee17SSøren Schmidt #ifdef DEBUG
264c21dee17SSøren Schmidt     printf("Linux-emul(%d): sigpending(*)\n", p->p_pid);
265c21dee17SSøren Schmidt #endif
266d66a5066SPeter Wemm     linux_sig = bsd_to_linux_sigset(p->p_siglist & p->p_sigmask);
267c21dee17SSøren Schmidt     return copyout(&linux_sig, args->mask, sizeof(linux_sig));
268c21dee17SSøren Schmidt }
269c21dee17SSøren Schmidt 
270c21dee17SSøren Schmidt int
271c21dee17SSøren Schmidt linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args,int *retval)
272c21dee17SSøren Schmidt {
273d66a5066SPeter Wemm     struct sigsuspend_args tmp;
274d66a5066SPeter Wemm     int error;
275c21dee17SSøren Schmidt 
276c21dee17SSøren Schmidt #ifdef DEBUG
277c21dee17SSøren Schmidt     printf("Linux-emul(%d): sigsuspend(%08x)\n", p->p_pid, args->mask);
278c21dee17SSøren Schmidt #endif
279d66a5066SPeter Wemm     tmp.mask = linux_to_bsd_sigset(args->mask);
280c21dee17SSøren Schmidt     return sigsuspend(p, &tmp , retval);
281c21dee17SSøren Schmidt }
282c21dee17SSøren Schmidt 
283d66a5066SPeter Wemm int
284d66a5066SPeter Wemm linux_pause(struct proc *p, struct linux_pause_args *args,int *retval)
285d66a5066SPeter Wemm {
286d66a5066SPeter Wemm     struct sigsuspend_args tmp;
287d66a5066SPeter Wemm     int error;
288d66a5066SPeter Wemm 
289d66a5066SPeter Wemm #ifdef DEBUG
290d66a5066SPeter Wemm     printf("Linux-emul(%d): pause()\n", p->p_pid);
291d66a5066SPeter Wemm #endif
292d66a5066SPeter Wemm     tmp.mask = p->p_sigmask;
293d66a5066SPeter Wemm     return sigsuspend(p, &tmp , retval);
294d66a5066SPeter Wemm }
295c21dee17SSøren Schmidt 
296c21dee17SSøren Schmidt int
297c21dee17SSøren Schmidt linux_kill(struct proc *p, struct linux_kill_args *args, int *retval)
298c21dee17SSøren Schmidt {
299ef04503dSPeter Wemm     struct kill_args /* {
300c21dee17SSøren Schmidt 	int pid;
301c21dee17SSøren Schmidt 	int signum;
302ef04503dSPeter Wemm     } */ tmp;
303c21dee17SSøren Schmidt 
304c21dee17SSøren Schmidt #ifdef DEBUG
305c21dee17SSøren Schmidt     printf("Linux-emul(%d): kill(%d, %d)\n",
306c21dee17SSøren Schmidt 	   p->p_pid, args->pid, args->signum);
307c21dee17SSøren Schmidt #endif
308c21dee17SSøren Schmidt     tmp.pid = args->pid;
309c21dee17SSøren Schmidt     tmp.signum = linux_to_bsd_signal[args->signum];
310c21dee17SSøren Schmidt     return kill(p, &tmp, retval);
311c21dee17SSøren Schmidt }
312