1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 1994-1995 Søren Schmidt
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/lock.h>
35 #include <sys/mutex.h>
36 #include <sys/sx.h>
37 #include <sys/proc.h>
38 #include <sys/signalvar.h>
39 #include <sys/syscallsubr.h>
40 #include <sys/sysproto.h>
41 
42 #include <security/audit/audit.h>
43 
44 #include "opt_compat.h"
45 
46 #ifdef COMPAT_LINUX32
47 #include <machine/../linux32/linux.h>
48 #include <machine/../linux32/linux32_proto.h>
49 #else
50 #include <machine/../linux/linux.h>
51 #include <machine/../linux/linux_proto.h>
52 #endif
53 #include <compat/linux/linux_signal.h>
54 #include <compat/linux/linux_util.h>
55 #include <compat/linux/linux_emul.h>
56 #include <compat/linux/linux_misc.h>
57 
58 static int	linux_do_tkill(struct thread *td, struct thread *tdt,
59 		    ksiginfo_t *ksi);
60 static void	sicode_to_lsicode(int si_code, int *lsi_code);
61 
62 static void
linux_to_bsd_sigaction(l_sigaction_t * lsa,struct sigaction * bsa)63 linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
64 {
65 	unsigned long flags;
66 
67 	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
68 	bsa->sa_handler = PTRIN(lsa->lsa_handler);
69 	bsa->sa_flags = 0;
70 
71 	flags = lsa->lsa_flags;
72 	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) {
73 		flags &= ~LINUX_SA_NOCLDSTOP;
74 		bsa->sa_flags |= SA_NOCLDSTOP;
75 	}
76 	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) {
77 		flags &= ~LINUX_SA_NOCLDWAIT;
78 		bsa->sa_flags |= SA_NOCLDWAIT;
79 	}
80 	if (lsa->lsa_flags & LINUX_SA_SIGINFO) {
81 		flags &= ~LINUX_SA_SIGINFO;
82 		bsa->sa_flags |= SA_SIGINFO;
83 #ifdef notyet
84 		/*
85 		 * XXX: We seem to be missing code to convert
86 		 *      some of the fields in ucontext_t.
87 		 */
88 		linux_msg(curthread,
89 		    "partially unsupported sigaction flag SA_SIGINFO");
90 #endif
91 	}
92 	if (lsa->lsa_flags & LINUX_SA_RESTORER) {
93 		flags &= ~LINUX_SA_RESTORER;
94 		/*
95 		 * We ignore the lsa_restorer and always use our own signal
96 		 * trampoline instead.  It looks like SA_RESTORER is obsolete
97 		 * in Linux too - it doesn't seem to be used at all on arm64.
98 		 * In any case: see Linux sigreturn(2).
99 		 */
100 	}
101 	if (lsa->lsa_flags & LINUX_SA_ONSTACK) {
102 		flags &= ~LINUX_SA_ONSTACK;
103 		bsa->sa_flags |= SA_ONSTACK;
104 	}
105 	if (lsa->lsa_flags & LINUX_SA_RESTART) {
106 		flags &= ~LINUX_SA_RESTART;
107 		bsa->sa_flags |= SA_RESTART;
108 	}
109 	if (lsa->lsa_flags & LINUX_SA_INTERRUPT) {
110 		flags &= ~LINUX_SA_INTERRUPT;
111 		/* Documented to be a "historical no-op". */
112 	}
113 	if (lsa->lsa_flags & LINUX_SA_ONESHOT) {
114 		flags &= ~LINUX_SA_ONESHOT;
115 		bsa->sa_flags |= SA_RESETHAND;
116 	}
117 	if (lsa->lsa_flags & LINUX_SA_NOMASK) {
118 		flags &= ~LINUX_SA_NOMASK;
119 		bsa->sa_flags |= SA_NODEFER;
120 	}
121 
122 	if (flags != 0)
123 		linux_msg(curthread, "unsupported sigaction flag %#lx", flags);
124 }
125 
126 static void
bsd_to_linux_sigaction(struct sigaction * bsa,l_sigaction_t * lsa)127 bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
128 {
129 
130 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
131 #ifdef COMPAT_LINUX32
132 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
133 #else
134 	lsa->lsa_handler = bsa->sa_handler;
135 #endif
136 	lsa->lsa_restorer = 0;		/* unsupported */
137 	lsa->lsa_flags = 0;
138 	if (bsa->sa_flags & SA_NOCLDSTOP)
139 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
140 	if (bsa->sa_flags & SA_NOCLDWAIT)
141 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
142 	if (bsa->sa_flags & SA_SIGINFO)
143 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
144 	if (bsa->sa_flags & SA_ONSTACK)
145 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
146 	if (bsa->sa_flags & SA_RESTART)
147 		lsa->lsa_flags |= LINUX_SA_RESTART;
148 	if (bsa->sa_flags & SA_RESETHAND)
149 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
150 	if (bsa->sa_flags & SA_NODEFER)
151 		lsa->lsa_flags |= LINUX_SA_NOMASK;
152 }
153 
154 int
linux_do_sigaction(struct thread * td,int linux_sig,l_sigaction_t * linux_nsa,l_sigaction_t * linux_osa)155 linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
156 		   l_sigaction_t *linux_osa)
157 {
158 	struct sigaction act, oact, *nsa, *osa;
159 	int error, sig;
160 
161 	if (!LINUX_SIG_VALID(linux_sig))
162 		return (EINVAL);
163 
164 	osa = (linux_osa != NULL) ? &oact : NULL;
165 	if (linux_nsa != NULL) {
166 		nsa = &act;
167 		linux_to_bsd_sigaction(linux_nsa, nsa);
168 	} else
169 		nsa = NULL;
170 	sig = linux_to_bsd_signal(linux_sig);
171 
172 	error = kern_sigaction(td, sig, nsa, osa, 0);
173 	if (error)
174 		return (error);
175 
176 	if (linux_osa != NULL)
177 		bsd_to_linux_sigaction(osa, linux_osa);
178 
179 	return (0);
180 }
181 
182 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
183 int
linux_signal(struct thread * td,struct linux_signal_args * args)184 linux_signal(struct thread *td, struct linux_signal_args *args)
185 {
186 	l_sigaction_t nsa, osa;
187 	int error;
188 
189 	nsa.lsa_handler = args->handler;
190 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
191 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
192 
193 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
194 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
195 
196 	return (error);
197 }
198 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
199 
200 int
linux_rt_sigaction(struct thread * td,struct linux_rt_sigaction_args * args)201 linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
202 {
203 	l_sigaction_t nsa, osa;
204 	int error;
205 
206 	if (args->sigsetsize != sizeof(l_sigset_t))
207 		return (EINVAL);
208 
209 	if (args->act != NULL) {
210 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
211 		if (error)
212 			return (error);
213 	}
214 
215 	error = linux_do_sigaction(td, args->sig,
216 				   args->act ? &nsa : NULL,
217 				   args->oact ? &osa : NULL);
218 
219 	if (args->oact != NULL && !error) {
220 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
221 	}
222 
223 	return (error);
224 }
225 
226 static int
linux_do_sigprocmask(struct thread * td,int how,l_sigset_t * new,l_sigset_t * old)227 linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
228 		     l_sigset_t *old)
229 {
230 	sigset_t omask, nmask;
231 	sigset_t *nmaskp;
232 	int error;
233 
234 	td->td_retval[0] = 0;
235 
236 	switch (how) {
237 	case LINUX_SIG_BLOCK:
238 		how = SIG_BLOCK;
239 		break;
240 	case LINUX_SIG_UNBLOCK:
241 		how = SIG_UNBLOCK;
242 		break;
243 	case LINUX_SIG_SETMASK:
244 		how = SIG_SETMASK;
245 		break;
246 	default:
247 		return (EINVAL);
248 	}
249 	if (new != NULL) {
250 		linux_to_bsd_sigset(new, &nmask);
251 		nmaskp = &nmask;
252 	} else
253 		nmaskp = NULL;
254 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
255 	if (error == 0 && old != NULL)
256 		bsd_to_linux_sigset(&omask, old);
257 
258 	return (error);
259 }
260 
261 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
262 int
linux_sigprocmask(struct thread * td,struct linux_sigprocmask_args * args)263 linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
264 {
265 	l_osigset_t mask;
266 	l_sigset_t set, oset;
267 	int error;
268 
269 	if (args->mask != NULL) {
270 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
271 		if (error)
272 			return (error);
273 		LINUX_SIGEMPTYSET(set);
274 		set.__mask = mask;
275 	}
276 
277 	error = linux_do_sigprocmask(td, args->how,
278 				     args->mask ? &set : NULL,
279 				     args->omask ? &oset : NULL);
280 
281 	if (args->omask != NULL && !error) {
282 		mask = oset.__mask;
283 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
284 	}
285 
286 	return (error);
287 }
288 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
289 
290 int
linux_rt_sigprocmask(struct thread * td,struct linux_rt_sigprocmask_args * args)291 linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
292 {
293 	l_sigset_t set, oset;
294 	int error;
295 
296 	if (args->sigsetsize != sizeof(l_sigset_t))
297 		return (EINVAL);
298 
299 	if (args->mask != NULL) {
300 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
301 		if (error)
302 			return (error);
303 	}
304 
305 	error = linux_do_sigprocmask(td, args->how,
306 				     args->mask ? &set : NULL,
307 				     args->omask ? &oset : NULL);
308 
309 	if (args->omask != NULL && !error) {
310 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
311 	}
312 
313 	return (error);
314 }
315 
316 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
317 int
linux_sgetmask(struct thread * td,struct linux_sgetmask_args * args)318 linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
319 {
320 	struct proc *p = td->td_proc;
321 	l_sigset_t mask;
322 
323 	PROC_LOCK(p);
324 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
325 	PROC_UNLOCK(p);
326 	td->td_retval[0] = mask.__mask;
327 	return (0);
328 }
329 
330 int
linux_ssetmask(struct thread * td,struct linux_ssetmask_args * args)331 linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
332 {
333 	struct proc *p = td->td_proc;
334 	l_sigset_t lset;
335 	sigset_t bset;
336 
337 	PROC_LOCK(p);
338 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
339 	td->td_retval[0] = lset.__mask;
340 	LINUX_SIGEMPTYSET(lset);
341 	lset.__mask = args->mask;
342 	linux_to_bsd_sigset(&lset, &bset);
343 	td->td_sigmask = bset;
344 	SIG_CANTMASK(td->td_sigmask);
345 	signotify(td);
346 	PROC_UNLOCK(p);
347 	return (0);
348 }
349 
350 int
linux_sigpending(struct thread * td,struct linux_sigpending_args * args)351 linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
352 {
353 	struct proc *p = td->td_proc;
354 	sigset_t bset;
355 	l_sigset_t lset;
356 	l_osigset_t mask;
357 
358 	PROC_LOCK(p);
359 	bset = p->p_siglist;
360 	SIGSETOR(bset, td->td_siglist);
361 	SIGSETAND(bset, td->td_sigmask);
362 	PROC_UNLOCK(p);
363 	bsd_to_linux_sigset(&bset, &lset);
364 	mask = lset.__mask;
365 	return (copyout(&mask, args->mask, sizeof(mask)));
366 }
367 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
368 
369 /*
370  * MPSAFE
371  */
372 int
linux_rt_sigpending(struct thread * td,struct linux_rt_sigpending_args * args)373 linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
374 {
375 	struct proc *p = td->td_proc;
376 	sigset_t bset;
377 	l_sigset_t lset;
378 
379 	if (args->sigsetsize > sizeof(lset))
380 		return (EINVAL);
381 		/* NOT REACHED */
382 
383 	PROC_LOCK(p);
384 	bset = p->p_siglist;
385 	SIGSETOR(bset, td->td_siglist);
386 	SIGSETAND(bset, td->td_sigmask);
387 	PROC_UNLOCK(p);
388 	bsd_to_linux_sigset(&bset, &lset);
389 	return (copyout(&lset, args->set, args->sigsetsize));
390 }
391 
392 /*
393  * MPSAFE
394  */
395 int
linux_rt_sigtimedwait(struct thread * td,struct linux_rt_sigtimedwait_args * args)396 linux_rt_sigtimedwait(struct thread *td,
397 	struct linux_rt_sigtimedwait_args *args)
398 {
399 	int error, sig;
400 	l_timeval ltv;
401 	struct timeval tv;
402 	struct timespec ts, *tsa;
403 	l_sigset_t lset;
404 	sigset_t bset;
405 	l_siginfo_t linfo;
406 	ksiginfo_t info;
407 
408 	if (args->sigsetsize != sizeof(l_sigset_t))
409 		return (EINVAL);
410 
411 	if ((error = copyin(args->mask, &lset, sizeof(lset))))
412 		return (error);
413 	linux_to_bsd_sigset(&lset, &bset);
414 
415 	tsa = NULL;
416 	if (args->timeout) {
417 		if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
418 			return (error);
419 		tv.tv_sec = (long)ltv.tv_sec;
420 		tv.tv_usec = (suseconds_t)ltv.tv_usec;
421 		if (itimerfix(&tv)) {
422 			/*
423 			 * The timeout was invalid. Convert it to something
424 			 * valid that will act as it does under Linux.
425 			 */
426 			tv.tv_sec += tv.tv_usec / 1000000;
427 			tv.tv_usec %= 1000000;
428 			if (tv.tv_usec < 0) {
429 				tv.tv_sec -= 1;
430 				tv.tv_usec += 1000000;
431 			}
432 			if (tv.tv_sec < 0)
433 				timevalclear(&tv);
434 		}
435 		TIMEVAL_TO_TIMESPEC(&tv, &ts);
436 		tsa = &ts;
437 	}
438 	error = kern_sigtimedwait(td, bset, &info, tsa);
439 	if (error)
440 		return (error);
441 
442 	sig = bsd_to_linux_signal(info.ksi_signo);
443 
444 	if (args->ptr) {
445 		memset(&linfo, 0, sizeof(linfo));
446 		ksiginfo_to_lsiginfo(&info, &linfo, sig);
447 		error = copyout(&linfo, args->ptr, sizeof(linfo));
448 	}
449 	if (error == 0)
450 		td->td_retval[0] = sig;
451 
452 	return (error);
453 }
454 
455 int
linux_kill(struct thread * td,struct linux_kill_args * args)456 linux_kill(struct thread *td, struct linux_kill_args *args)
457 {
458 	int l_signum;
459 
460 	/*
461 	 * Allow signal 0 as a means to check for privileges
462 	 */
463 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
464 		return (EINVAL);
465 
466 	if (args->signum > 0)
467 		l_signum = linux_to_bsd_signal(args->signum);
468 	else
469 		l_signum = 0;
470 
471 	return (kern_kill(td, args->pid, l_signum));
472 }
473 
474 static int
linux_do_tkill(struct thread * td,struct thread * tdt,ksiginfo_t * ksi)475 linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
476 {
477 	struct proc *p;
478 	int error;
479 
480 	p = tdt->td_proc;
481 	AUDIT_ARG_SIGNUM(ksi->ksi_signo);
482 	AUDIT_ARG_PID(p->p_pid);
483 	AUDIT_ARG_PROCESS(p);
484 
485 	error = p_cansignal(td, p, ksi->ksi_signo);
486 	if (error != 0 || ksi->ksi_signo == 0)
487 		goto out;
488 
489 	tdksignal(tdt, ksi->ksi_signo, ksi);
490 
491 out:
492 	PROC_UNLOCK(p);
493 	return (error);
494 }
495 
496 int
linux_tgkill(struct thread * td,struct linux_tgkill_args * args)497 linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
498 {
499 	struct thread *tdt;
500 	ksiginfo_t ksi;
501 	int sig;
502 
503 	if (args->pid <= 0 || args->tgid <=0)
504 		return (EINVAL);
505 
506 	/*
507 	 * Allow signal 0 as a means to check for privileges
508 	 */
509 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
510 		return (EINVAL);
511 
512 	if (args->sig > 0)
513 		sig = linux_to_bsd_signal(args->sig);
514 	else
515 		sig = 0;
516 
517 	tdt = linux_tdfind(td, args->pid, args->tgid);
518 	if (tdt == NULL)
519 		return (ESRCH);
520 
521 	ksiginfo_init(&ksi);
522 	ksi.ksi_signo = sig;
523 	ksi.ksi_code = SI_LWP;
524 	ksi.ksi_errno = 0;
525 	ksi.ksi_pid = td->td_proc->p_pid;
526 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
527 	return (linux_do_tkill(td, tdt, &ksi));
528 }
529 
530 /*
531  * Deprecated since 2.5.75. Replaced by tgkill().
532  */
533 int
linux_tkill(struct thread * td,struct linux_tkill_args * args)534 linux_tkill(struct thread *td, struct linux_tkill_args *args)
535 {
536 	struct thread *tdt;
537 	ksiginfo_t ksi;
538 	int sig;
539 
540 	if (args->tid <= 0)
541 		return (EINVAL);
542 
543 	if (!LINUX_SIG_VALID(args->sig))
544 		return (EINVAL);
545 
546 	sig = linux_to_bsd_signal(args->sig);
547 
548 	tdt = linux_tdfind(td, args->tid, -1);
549 	if (tdt == NULL)
550 		return (ESRCH);
551 
552 	ksiginfo_init(&ksi);
553 	ksi.ksi_signo = sig;
554 	ksi.ksi_code = SI_LWP;
555 	ksi.ksi_errno = 0;
556 	ksi.ksi_pid = td->td_proc->p_pid;
557 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
558 	return (linux_do_tkill(td, tdt, &ksi));
559 }
560 
561 void
ksiginfo_to_lsiginfo(const ksiginfo_t * ksi,l_siginfo_t * lsi,l_int sig)562 ksiginfo_to_lsiginfo(const ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
563 {
564 
565 	siginfo_to_lsiginfo(&ksi->ksi_info, lsi, sig);
566 }
567 
568 static void
sicode_to_lsicode(int si_code,int * lsi_code)569 sicode_to_lsicode(int si_code, int *lsi_code)
570 {
571 
572 	switch (si_code) {
573 	case SI_USER:
574 		*lsi_code = LINUX_SI_USER;
575 		break;
576 	case SI_KERNEL:
577 		*lsi_code = LINUX_SI_KERNEL;
578 		break;
579 	case SI_QUEUE:
580 		*lsi_code = LINUX_SI_QUEUE;
581 		break;
582 	case SI_TIMER:
583 		*lsi_code = LINUX_SI_TIMER;
584 		break;
585 	case SI_MESGQ:
586 		*lsi_code = LINUX_SI_MESGQ;
587 		break;
588 	case SI_ASYNCIO:
589 		*lsi_code = LINUX_SI_ASYNCIO;
590 		break;
591 	case SI_LWP:
592 		*lsi_code = LINUX_SI_TKILL;
593 		break;
594 	default:
595 		*lsi_code = si_code;
596 		break;
597 	}
598 }
599 
600 void
siginfo_to_lsiginfo(const siginfo_t * si,l_siginfo_t * lsi,l_int sig)601 siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
602 {
603 
604 	/* sig alredy converted */
605 	lsi->lsi_signo = sig;
606 	sicode_to_lsicode(si->si_code, &lsi->lsi_code);
607 
608 	switch (si->si_code) {
609 	case SI_LWP:
610 		lsi->lsi_pid = si->si_pid;
611 		lsi->lsi_uid = si->si_uid;
612 		break;
613 
614 	case SI_TIMER:
615 		lsi->lsi_int = si->si_value.sival_int;
616 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
617 		lsi->lsi_tid = si->si_timerid;
618 		break;
619 
620 	case SI_QUEUE:
621 		lsi->lsi_pid = si->si_pid;
622 		lsi->lsi_uid = si->si_uid;
623 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
624 		break;
625 
626 	case SI_ASYNCIO:
627 		lsi->lsi_int = si->si_value.sival_int;
628 		lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
629 		break;
630 
631 	default:
632 		switch (sig) {
633 		case LINUX_SIGPOLL:
634 			/* XXX si_fd? */
635 			lsi->lsi_band = si->si_band;
636 			break;
637 
638 		case LINUX_SIGCHLD:
639 			lsi->lsi_errno = 0;
640 			lsi->lsi_pid = si->si_pid;
641 			lsi->lsi_uid = si->si_uid;
642 
643 			if (si->si_code == CLD_STOPPED || si->si_code == CLD_KILLED)
644 				lsi->lsi_status = bsd_to_linux_signal(si->si_status);
645 			else if (si->si_code == CLD_CONTINUED)
646 				lsi->lsi_status = bsd_to_linux_signal(SIGCONT);
647 			else
648 				lsi->lsi_status = si->si_status;
649 			break;
650 
651 		case LINUX_SIGBUS:
652 		case LINUX_SIGILL:
653 		case LINUX_SIGFPE:
654 		case LINUX_SIGSEGV:
655 			lsi->lsi_addr = PTROUT(si->si_addr);
656 			break;
657 
658 		default:
659 			lsi->lsi_pid = si->si_pid;
660 			lsi->lsi_uid = si->si_uid;
661 			if (sig >= LINUX_SIGRTMIN) {
662 				lsi->lsi_int = si->si_value.sival_int;
663 				lsi->lsi_ptr = PTROUT(si->si_value.sival_ptr);
664 			}
665 			break;
666 		}
667 		break;
668 	}
669 }
670 
671 void
lsiginfo_to_ksiginfo(const l_siginfo_t * lsi,ksiginfo_t * ksi,int sig)672 lsiginfo_to_ksiginfo(const l_siginfo_t *lsi, ksiginfo_t *ksi, int sig)
673 {
674 
675 	ksi->ksi_signo = sig;
676 	ksi->ksi_code = lsi->lsi_code;	/* XXX. Convert. */
677 	ksi->ksi_pid = lsi->lsi_pid;
678 	ksi->ksi_uid = lsi->lsi_uid;
679 	ksi->ksi_status = lsi->lsi_status;
680 	ksi->ksi_addr = PTRIN(lsi->lsi_addr);
681 	ksi->ksi_info.si_value.sival_int = lsi->lsi_int;
682 }
683 
684 int
linux_rt_sigqueueinfo(struct thread * td,struct linux_rt_sigqueueinfo_args * args)685 linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args)
686 {
687 	l_siginfo_t linfo;
688 	struct proc *p;
689 	ksiginfo_t ksi;
690 	int error;
691 	int sig;
692 
693 	if (!LINUX_SIG_VALID(args->sig))
694 		return (EINVAL);
695 
696 	error = copyin(args->info, &linfo, sizeof(linfo));
697 	if (error != 0)
698 		return (error);
699 
700 	if (linfo.lsi_code >= 0)
701 		return (EPERM);
702 
703 	sig = linux_to_bsd_signal(args->sig);
704 
705 	error = ESRCH;
706 	if ((p = pfind_any(args->pid)) != NULL) {
707 		error = p_cansignal(td, p, sig);
708 		if (error != 0) {
709 			PROC_UNLOCK(p);
710 			return (error);
711 		}
712 
713 		ksiginfo_init(&ksi);
714 		lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
715 		error = tdsendsignal(p, NULL, sig, &ksi);
716 		PROC_UNLOCK(p);
717 	}
718 
719 	return (error);
720 }
721 
722 int
linux_rt_tgsigqueueinfo(struct thread * td,struct linux_rt_tgsigqueueinfo_args * args)723 linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *args)
724 {
725 	l_siginfo_t linfo;
726 	struct thread *tds;
727 	ksiginfo_t ksi;
728 	int error;
729 	int sig;
730 
731 	if (!LINUX_SIG_VALID(args->sig))
732 		return (EINVAL);
733 
734 	error = copyin(args->uinfo, &linfo, sizeof(linfo));
735 	if (error != 0)
736 		return (error);
737 
738 	if (linfo.lsi_code >= 0)
739 		return (EPERM);
740 
741 	tds = linux_tdfind(td, args->tid, args->tgid);
742 	if (tds == NULL)
743 		return (ESRCH);
744 
745 	sig = linux_to_bsd_signal(args->sig);
746 	ksiginfo_init(&ksi);
747 	lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
748 	return (linux_do_tkill(td, tds, &ksi));
749 }
750 
751 int
linux_rt_sigsuspend(struct thread * td,struct linux_rt_sigsuspend_args * uap)752 linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap)
753 {
754 	l_sigset_t lmask;
755 	sigset_t sigmask;
756 	int error;
757 
758 	if (uap->sigsetsize != sizeof(l_sigset_t))
759 		return (EINVAL);
760 
761 	error = copyin(uap->newset, &lmask, sizeof(l_sigset_t));
762 	if (error != 0)
763 		return (error);
764 
765 	linux_to_bsd_sigset(&lmask, &sigmask);
766 	return (kern_sigsuspend(td, sigmask));
767 }
768