Home | History | Annotate | Line # | Download | only in common
      1 /*	$NetBSD: linux32_signal.c,v 1.24 2021/11/26 13:32:38 christos Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *	This product includes software developed by Emmanuel Dreyfus
     17  * 4. The name of the author may not be used to endorse or promote
     18  *    products derived from this software without specific prior written
     19  *    permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
     22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
     25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31  * POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 __KERNEL_RCSID(0, "$NetBSD: linux32_signal.c,v 1.24 2021/11/26 13:32:38 christos Exp $");
     36 
     37 #include <sys/param.h>
     38 #include <sys/ucred.h>
     39 #include <sys/signalvar.h>
     40 #include <sys/lwp.h>
     41 #include <sys/time.h>
     42 #include <sys/proc.h>
     43 #include <sys/wait.h>
     44 
     45 #include <compat/netbsd32/netbsd32.h>
     46 
     47 #include <compat/linux/common/linux_types.h>
     48 #include <compat/linux/common/linux_signal.h>
     49 #include <compat/linux/common/linux_sigevent.h>
     50 
     51 #include <compat/linux32/common/linux32_types.h>
     52 #include <compat/linux32/common/linux32_signal.h>
     53 #include <compat/linux32/common/linux32_sigevent.h>
     54 #include <compat/linux32/common/linux32_siginfo.h>
     55 #include <compat/linux32/linux32_syscallargs.h>
     56 #include <compat/linux32/common/linux32_errno.h>
     57 #include <compat/linux32/common/linux32_sched.h>
     58 
     59 #define linux32_sigemptyset(s)    memset((s), 0, sizeof(*(s)))
     60 #define linux32_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW]  \
     61 				    & (1 << ((n) - 1) % LINUX32__NSIG_BPW))
     62 #define linux32_sigaddset(s, n)   ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW]  \
     63 				    |= (1 << ((n) - 1) % LINUX32__NSIG_BPW))
     64 
     65 extern const int native_to_linux32_signo[];
     66 extern const int linux32_to_native_signo[];
     67 
     68 #ifdef DEBUG_LINUX
     69 #define DPRINTF(a)      uprintf a
     70 #else
     71 #define DPRINTF(a)
     72 #endif
     73 
     74 void
     75 linux32_to_native_sigset(sigset_t *bss, const linux32_sigset_t *lss)
     76 {
     77 	int i, newsig;
     78 
     79 	sigemptyset(bss);
     80 	for (i = 1; i < LINUX32__NSIG; i++) {
     81 		if (linux32_sigismember(lss, i)) {
     82 			newsig = linux32_to_native_signo[i];
     83 			if (newsig)
     84 				sigaddset(bss, newsig);
     85 		}
     86 	}
     87 }
     88 
     89 void
     90 native_to_linux32_sigset(linux32_sigset_t *lss, const sigset_t *bss)
     91 {
     92 	int i, newsig;
     93 
     94 	linux32_sigemptyset(lss);
     95 	for (i = 1; i < NSIG; i++) {
     96 		if (sigismember(bss, i)) {
     97 			newsig = native_to_linux32_signo[i];
     98 			if (newsig)
     99 				linux32_sigaddset(lss, newsig);
    100 		}
    101 	}
    102 }
    103 
    104 void
    105 native_to_linux32_siginfo(linux32_siginfo_t *lsi, const struct _ksiginfo *ksi)
    106 {
    107 	memset(lsi, 0, sizeof(*lsi));
    108 
    109 	lsi->lsi_signo = native_to_linux32_signo[ksi->_signo];
    110 	lsi->lsi_errno = native_to_linux32_errno[ksi->_errno];
    111 	lsi->lsi_code = native_to_linux32_si_code(ksi->_code);
    112 
    113 	switch (ksi->_code) {
    114 	case SI_NOINFO:
    115 		break;
    116 
    117 	case SI_USER:
    118 		lsi->lsi_pid = ksi->_reason._rt._pid;
    119 		lsi->lsi_uid = ksi->_reason._rt._uid;
    120 		if (lsi->lsi_signo == LINUX_SIGALRM ||
    121 		    lsi->lsi_signo >= LINUX_SIGRTMIN)
    122 			NETBSD32PTR32(lsi->lsi_value.sival_ptr,
    123 			    ksi->_reason._rt._value.sival_ptr);
    124 		break;
    125 
    126 	case SI_TIMER:
    127 	case SI_QUEUE:
    128 		lsi->lsi_uid = ksi->_reason._rt._uid;
    129 		lsi->lsi_uid = ksi->_reason._rt._uid;
    130 		NETBSD32PTR32(lsi->lsi_value.sival_ptr,
    131 		    ksi->_reason._rt._value.sival_ptr);
    132 		break;
    133 
    134 	case SI_ASYNCIO:
    135 	case SI_MESGQ:
    136 		NETBSD32PTR32(lsi->lsi_value.sival_ptr,
    137 		    ksi->_reason._rt._value.sival_ptr);
    138 		break;
    139 
    140 	default:
    141 		switch (ksi->_signo) {
    142 		case SIGCHLD:
    143 			lsi->lsi_uid = ksi->_reason._child._uid;
    144 			lsi->lsi_pid = ksi->_reason._child._pid;
    145 			lsi->lsi_status = native_to_linux32_si_status(
    146 			    ksi->_code, ksi->_reason._child._status);
    147 			lsi->lsi_utime = ksi->_reason._child._utime;
    148 			lsi->lsi_stime = ksi->_reason._child._stime;
    149 			break;
    150 
    151 		case SIGILL:
    152 		case SIGFPE:
    153 		case SIGSEGV:
    154 		case SIGBUS:
    155 		case SIGTRAP:
    156 			NETBSD32PTR32(lsi->lsi_addr, ksi->_reason._fault._addr);
    157 			break;
    158 
    159 		case SIGIO:
    160 			lsi->lsi_fd = ksi->_reason._poll._fd;
    161 			lsi->lsi_band = ksi->_reason._poll._band;
    162 			break;
    163 		default:
    164 			break;
    165 		}
    166 	}
    167 }
    168 
    169 unsigned int
    170 native_to_linux32_sigflags(const int bsf)
    171 {
    172 	unsigned int lsf = 0;
    173 	if ((bsf & SA_NOCLDSTOP) != 0)
    174 		lsf |= LINUX32_SA_NOCLDSTOP;
    175 	if ((bsf & SA_NOCLDWAIT) != 0)
    176 		lsf |= LINUX32_SA_NOCLDWAIT;
    177 	if ((bsf & SA_ONSTACK) != 0)
    178 		lsf |= LINUX32_SA_ONSTACK;
    179 	if ((bsf & SA_RESTART) != 0)
    180 		lsf |= LINUX32_SA_RESTART;
    181 	if ((bsf & SA_NODEFER) != 0)
    182 		lsf |= LINUX32_SA_NOMASK;
    183 	if ((bsf & SA_RESETHAND) != 0)
    184 		lsf |= LINUX32_SA_ONESHOT;
    185 	if ((bsf & SA_SIGINFO) != 0)
    186 		lsf |= LINUX32_SA_SIGINFO;
    187 	return lsf;
    188 }
    189 
    190 int
    191 linux32_to_native_sigflags(const unsigned long lsf)
    192 {
    193 	int bsf = 0;
    194 	if ((lsf & LINUX32_SA_NOCLDSTOP) != 0)
    195 		bsf |= SA_NOCLDSTOP;
    196 	if ((lsf & LINUX32_SA_NOCLDWAIT) != 0)
    197 		bsf |= SA_NOCLDWAIT;
    198 	if ((lsf & LINUX32_SA_ONSTACK) != 0)
    199 		bsf |= SA_ONSTACK;
    200 	if ((lsf & LINUX32_SA_RESTART) != 0)
    201 		bsf |= SA_RESTART;
    202 	if ((lsf & LINUX32_SA_ONESHOT) != 0)
    203 		bsf |= SA_RESETHAND;
    204 	if ((lsf & LINUX32_SA_NOMASK) != 0)
    205 		bsf |= SA_NODEFER;
    206 	if ((lsf & LINUX32_SA_SIGINFO) != 0)
    207 		bsf |= SA_SIGINFO;
    208 	if ((lsf & ~LINUX32_SA_ALLBITS) != 0) {
    209 #ifdef DEBUG_LINUX
    210 		printf("linux32_old_to_native_sigflags: "
    211 		    "%lx extra bits ignored\n", lsf);
    212 #endif
    213 	}
    214 	return bsf;
    215 }
    216 
    217 void
    218 linux32_to_native_sigaction(struct sigaction *bsa, const struct linux32_sigaction *lsa)
    219 {
    220 	memset(bsa, 0, sizeof(*bsa));
    221 	bsa->sa_handler = NETBSD32PTR64(lsa->linux_sa_handler);
    222 	linux32_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask);
    223 	bsa->sa_flags = linux32_to_native_sigflags(lsa->linux_sa_flags);
    224 }
    225 
    226 void
    227 native_to_linux32_sigaction(struct linux32_sigaction *lsa, const struct sigaction *bsa)
    228 {
    229 	memset(lsa, 0, sizeof(*lsa));
    230 	NETBSD32PTR32(lsa->linux_sa_handler, bsa->sa_handler);
    231 	native_to_linux32_sigset(&lsa->linux_sa_mask, &bsa->sa_mask);
    232 	lsa->linux_sa_flags = native_to_linux32_sigflags(bsa->sa_flags);
    233 	NETBSD32PTR32(lsa->linux_sa_restorer, NULL);
    234 }
    235 
    236 void
    237 native_to_linux32_sigaltstack(struct linux32_sigaltstack *lss,
    238     const stack_t *bss)
    239 {
    240 	memset(lss, 0, sizeof(*lss));
    241 	NETBSD32PTR32(lss->ss_sp, bss->ss_sp);
    242 	lss->ss_size = bss->ss_size;
    243 	if (bss->ss_flags & SS_ONSTACK)
    244 	    lss->ss_flags = LINUX32_SS_ONSTACK;
    245 	else if (bss->ss_flags & SS_DISABLE)
    246 	    lss->ss_flags = LINUX32_SS_DISABLE;
    247 	else
    248 	    lss->ss_flags = 0;
    249 }
    250 
    251 
    252 void
    253 native_to_linux32_old_sigset(linux32_old_sigset_t *lss, const sigset_t *bss)
    254 {
    255 	linux32_sigset_t lsnew;
    256 
    257 	native_to_linux32_sigset(&lsnew, bss);
    258 
    259 	/* convert new sigset to old sigset */
    260 	*lss = lsnew.sig[0];
    261 }
    262 
    263 void
    264 linux32_old_to_native_sigset(sigset_t *bss, const linux32_old_sigset_t *lss)
    265 {
    266 	linux32_sigset_t ls;
    267 
    268 	memset(&ls, 0, sizeof(ls));
    269 	ls.sig[0] = *lss;
    270 
    271 	linux32_to_native_sigset(bss, &ls);
    272 }
    273 
    274 int
    275 linux32_sys_rt_sigaction(struct lwp *l, const struct linux32_sys_rt_sigaction_args *uap, register_t *retval)
    276 {
    277 	/* {
    278 		syscallarg(int) signum;
    279 		syscallarg(const linux32_sigactionp_t) nsa;
    280 		syscallarg(linux32_sigactionp_t) osa;
    281 		syscallarg(netbsd32_size_t) sigsetsize;
    282 	} */
    283 	struct linux32_sigaction nls32;
    284 	struct linux32_sigaction ols32;
    285 	struct sigaction ns;
    286 	struct sigaction os;
    287 	int error;
    288 	int sig;
    289 	int vers = 0;
    290 	void *tramp = NULL;
    291 
    292 	if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) {
    293 		DPRINTF(("rt_sigaction: Inconsistent sigsetsize %u %zu\n",
    294 		    SCARG(uap, sigsetsize), sizeof(linux32_sigset_t)));
    295 		return EINVAL;
    296 	}
    297 
    298 	if (SCARG_P32(uap, nsa) != NULL) {
    299 		if ((error = copyin(SCARG_P32(uap, nsa),
    300 		    &nls32, sizeof(nls32))) != 0) {
    301 			DPRINTF(("rt_sigaction: Copyin %d\n", error));
    302 			return error;
    303 		}
    304 		linux32_to_native_sigaction(&ns, &nls32);
    305 	}
    306 
    307 	sig = SCARG(uap, signum);
    308 	/*
    309 	 * XXX: Linux has 33 realtime signals, the go binary wants to
    310 	 * reset all of them; nothing else uses the last RT signal, so for
    311 	 * now ignore it.
    312 	 */
    313 	if (sig == LINUX__NSIG) {
    314 		uprintf("%s: setting signal %d ignored\n", __func__, sig);
    315 		sig--;	/* back to 63 which is ignored */
    316 	}
    317 	if (sig < 0 || sig >= LINUX32__NSIG) {
    318 		DPRINTF(("rt_sigaction: Bad signal number %d %d\n",
    319 		    sig, LINUX32__NSIG));
    320 		return EINVAL;
    321 	}
    322 	if (sig > 0 && !linux32_to_native_signo[sig]) {
    323 		/* unknown signal... */
    324 		os.sa_handler = SIG_IGN;
    325 		sigemptyset(&os.sa_mask);
    326 		os.sa_flags = 0;
    327 	} else {
    328 		if ((error = sigaction1(l,
    329 		    linux32_to_native_signo[sig],
    330 		    SCARG_P32(uap, nsa) ? &ns : NULL,
    331 		    SCARG_P32(uap, osa) ? &os : NULL,
    332 		    tramp, vers)) != 0) {
    333 			DPRINTF(("rt_sigaction: sigaction %d\n", error));
    334 			return error;
    335 		}
    336 	}
    337 
    338 	if (SCARG_P32(uap, osa) != NULL) {
    339 		native_to_linux32_sigaction(&ols32, &os);
    340 
    341 		if ((error = copyout(&ols32, SCARG_P32(uap, osa),
    342 		    sizeof(ols32))) != 0) {
    343 			DPRINTF(("rt_sigaction: Copyout %d\n", error));
    344 			return error;
    345 		}
    346 	}
    347 
    348 	return 0;
    349 }
    350 
    351 int
    352 linux32_sys_rt_sigprocmask(struct lwp *l, const struct linux32_sys_rt_sigprocmask_args *uap, register_t *retval)
    353 {
    354 	/* {
    355 		syscallarg(int) how;
    356 		syscallarg(const linux32_sigsetp_t) set;
    357 		syscallarg(linux32_sigsetp_t) oset;
    358 		syscallarg(netbsd32_size_t) sigsetsize;
    359 	} */
    360 	struct proc *p = l->l_proc;
    361 	linux32_sigset_t nls32, ols32;
    362 	sigset_t ns, os;
    363 	int error;
    364 	int how;
    365 
    366 	if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
    367 		return EINVAL;
    368 
    369 	switch (SCARG(uap, how)) {
    370 	case LINUX32_SIG_BLOCK:
    371 		how = SIG_BLOCK;
    372 		break;
    373 	case LINUX32_SIG_UNBLOCK:
    374 		how = SIG_UNBLOCK;
    375 		break;
    376 	case LINUX32_SIG_SETMASK:
    377 		how = SIG_SETMASK;
    378 		break;
    379 	default:
    380 		return EINVAL;
    381 		break;
    382 	}
    383 
    384 	if (SCARG_P32(uap, set) != NULL) {
    385 		if ((error = copyin(SCARG_P32(uap, set),
    386 		    &nls32, sizeof(nls32))) != 0)
    387 			return error;
    388 		linux32_to_native_sigset(&ns, &nls32);
    389 	}
    390 
    391 	mutex_enter(p->p_lock);
    392 	error = sigprocmask1(l, how,
    393 	    SCARG_P32(uap, set) ? &ns : NULL,
    394 	    SCARG_P32(uap, oset) ? &os : NULL);
    395 	mutex_exit(p->p_lock);
    396 
    397         if (error != 0)
    398 		return error;
    399 
    400 	if (SCARG_P32(uap, oset) != NULL) {
    401 		native_to_linux32_sigset(&ols32, &os);
    402 		if ((error = copyout(&ols32,
    403 		    SCARG_P32(uap, oset), sizeof(ols32))) != 0)
    404 			return error;
    405 	}
    406 
    407 	return 0;
    408 }
    409 
    410 int
    411 linux32_sys_kill(struct lwp *l, const struct linux32_sys_kill_args *uap, register_t *retval)
    412 {
    413 	/* {
    414 		syscallarg(int) pid;
    415 		syscallarg(int) signum;
    416 	} */
    417 
    418 	struct sys_kill_args ka;
    419 	int sig;
    420 
    421 	SCARG(&ka, pid) = SCARG(uap, pid);
    422 	sig = SCARG(uap, signum);
    423 	if (sig < 0 || sig >= LINUX32__NSIG)
    424 		return (EINVAL);
    425 	SCARG(&ka, signum) = linux32_to_native_signo[sig];
    426 	return sys_kill(l, &ka, retval);
    427 }
    428 
    429 int
    430 linux32_sys_rt_sigsuspend(struct lwp *l, const struct linux32_sys_rt_sigsuspend_args *uap, register_t *retval)
    431 {
    432 	/* {
    433 		syscallarg(linux32_sigsetp_t) unewset;
    434                 syscallarg(netbsd32_size_t) sigsetsize;
    435 	} */
    436 	linux32_sigset_t lss;
    437 	sigset_t bss;
    438 	int error;
    439 
    440 	if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
    441 		return EINVAL;
    442 
    443 	if ((error = copyin(SCARG_P32(uap, unewset),
    444 	    &lss, sizeof(linux32_sigset_t))) != 0)
    445 		return error;
    446 
    447 	linux32_to_native_sigset(&bss, &lss);
    448 
    449 	return sigsuspend1(l, &bss);
    450 }
    451 
    452 static int
    453 fetchss(const void *u, void *s, size_t len)
    454 {
    455 	int error;
    456 	linux32_sigset_t lss;
    457 
    458 	if ((error = copyin(u, &lss, sizeof(lss))) != 0)
    459 		return error;
    460 
    461 	linux32_to_native_sigset(s, &lss);
    462 	return 0;
    463 }
    464 
    465 static int
    466 fetchts(const void *u, void *s, size_t len)
    467 {
    468 	int error;
    469 	struct linux32_timespec lts;
    470 
    471 	if ((error = copyin(u, &lts, sizeof(lts))) != 0)
    472 		return error;
    473 
    474 	linux32_to_native_timespec(s, &lts);
    475 	return 0;
    476 }
    477 
    478 static int
    479 fakestorets(const void *u, void *s, size_t len)
    480 {
    481 	/* Do nothing, sigtimedwait does not alter timeout like ours */
    482 	return 0;
    483 }
    484 
    485 static int
    486 storeinfo(const void *s, void *u, size_t len)
    487 {
    488 	linux32_siginfo_t lsi;
    489 
    490 
    491 	native_to_linux32_siginfo(&lsi, &((const siginfo_t *)s)->_info);
    492 	return copyout(&lsi, u, sizeof(lsi));
    493 }
    494 
    495 int
    496 linux32_sys_rt_sigtimedwait(struct lwp *l,
    497     const struct linux32_sys_rt_sigtimedwait_args *uap, register_t *retval)
    498 {
    499 	/* {
    500 		syscallarg(const linux32_sigset_t *) set;
    501 		syscallarg(linux32_siginfo_t *) info);
    502 		syscallarg(const struct linux32_timespec *) timeout;
    503 	} */
    504 	struct sys_____sigtimedwait50_args ap;
    505 
    506 	SCARG(&ap, set) = SCARG_P32(uap, set);
    507 	SCARG(&ap, info) = SCARG_P32(uap, info);
    508 	SCARG(&ap, timeout) = SCARG_P32(uap, timeout);
    509 
    510 	return sigtimedwait1(l, &ap,
    511 	    retval, fetchss, storeinfo, fetchts, fakestorets);
    512 }
    513 
    514 int
    515 linux32_sys_signal(struct lwp *l, const struct linux32_sys_signal_args *uap, register_t *retval)
    516 {
    517 	/* {
    518 		syscallarg(int) signum;
    519 		syscallarg(linux32_handlerp_t) handler;
    520 	} */
    521         struct sigaction nbsa, obsa;
    522         int error, sig;
    523 
    524         *retval = -1;
    525 
    526         sig = SCARG(uap, signum);
    527         if (sig < 0 || sig >= LINUX32__NSIG)
    528                 return EINVAL;
    529 
    530         nbsa.sa_handler = SCARG_P32(uap, handler);
    531         sigemptyset(&nbsa.sa_mask);
    532         nbsa.sa_flags = SA_RESETHAND | SA_NODEFER;
    533 
    534         if ((error = sigaction1(l, linux32_to_native_signo[sig],
    535             &nbsa, &obsa, NULL, 0)) != 0)
    536 		return error;
    537 
    538         *retval = (int)(long)obsa.sa_handler;
    539         return 0;
    540 }
    541 
    542 int
    543 linux32_sys_rt_sigpending(struct lwp *l, const struct linux32_sys_rt_sigpending_args *uap, register_t *retval)
    544 {
    545 	/* {
    546 		syscallarg(linux32_sigsetp_t) set;
    547 		syscallarg(netbsd32_size_t) sigsetsize;
    548 	} */
    549 	sigset_t bss;
    550 	linux32_sigset_t lss;
    551 
    552 	if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
    553 		return EINVAL;
    554 
    555 	sigpending1(l, &bss);
    556 	native_to_linux32_sigset(&lss, &bss);
    557 	return copyout(&lss, SCARG_P32(uap, set), sizeof(lss));
    558 }
    559 
    560 int
    561 linux32_sys_siggetmask(struct lwp *l, const void *v, register_t *retval)
    562 {
    563 	struct proc *p = l->l_proc;
    564 	sigset_t bss;
    565 	linux32_old_sigset_t lss;
    566 	int error;
    567 
    568 	mutex_enter(p->p_lock);
    569 	error = sigprocmask1(l, SIG_SETMASK, 0, &bss);
    570 	mutex_exit(p->p_lock);
    571 	if (error)
    572 		return error;
    573 	native_to_linux32_old_sigset(&lss, &bss);
    574 	*retval = lss;
    575 	return 0;
    576 }
    577 
    578 int
    579 linux32_sys_sigsetmask(struct lwp *l, const struct linux32_sys_sigsetmask_args *uap, register_t *retval)
    580 {
    581 	/* {
    582 		syscallarg(linux32_old_sigset_t) mask;
    583 	} */
    584 	sigset_t nbss, obss;
    585 	linux32_old_sigset_t nlss, olss;
    586 	struct proc *p = l->l_proc;
    587 	int error;
    588 
    589 	nlss = SCARG(uap, mask);
    590 	linux32_old_to_native_sigset(&nbss, &nlss);
    591 	mutex_enter(p->p_lock);
    592 	error = sigprocmask1(l, SIG_SETMASK, &nbss, &obss);
    593 	mutex_exit(p->p_lock);
    594 	if (error)
    595 		return error;
    596 	native_to_linux32_old_sigset(&olss, &obss);
    597 	*retval = olss;
    598 	return 0;
    599 }
    600 
    601 int
    602 linux32_sys_rt_queueinfo(struct lwp *l, const struct linux32_sys_rt_queueinfo_args *uap, register_t *retval)
    603 {
    604 	/*
    605 		syscallarg(int) pid;
    606 		syscallarg(int) sig;
    607 		syscallarg(linux32_siginfop_t) uinfo;
    608 	*/
    609 	int error;
    610 	linux32_siginfo_t info;
    611 
    612 	error = copyin(SCARG_P32(uap, uinfo), &info, sizeof(info));
    613 	if (error)
    614 		return error;
    615 	if (info.lsi_code >= 0)
    616 		return EPERM;
    617 
    618 	/* XXX To really implement this we need to      */
    619 	/* XXX keep a list of queued signals somewhere. */
    620 	return linux32_sys_kill(l, (const void *)uap, retval);
    621 }
    622 
    623 int
    624 native_to_linux32_si_code(int code)
    625 {
    626 	int si_codes[] = {
    627 	    LINUX32_SI_USER, LINUX32_SI_QUEUE, LINUX32_SI_TIMER,
    628 	    LINUX32_SI_ASYNCIO, LINUX32_SI_MESGQ, LINUX32_SI_TKILL /* SI_LWP */
    629 	};
    630 
    631 	if (code <= 0 && -code < __arraycount(si_codes))
    632 		return si_codes[-code];
    633 
    634 	return code;
    635 }
    636 
    637 int
    638 native_to_linux32_si_status(int code, int status)
    639 {
    640 	int sts;
    641 
    642 	switch (code) {
    643 	case CLD_CONTINUED:
    644 		sts = LINUX_SIGCONT;
    645 		break;
    646 	case CLD_EXITED:
    647 		sts = WEXITSTATUS(status);
    648 		break;
    649 	case CLD_STOPPED:
    650 	case CLD_TRAPPED:
    651 	case CLD_DUMPED:
    652 	case CLD_KILLED:
    653 	default:
    654 		sts = native_to_linux32_signo[WTERMSIG(status)];
    655 		break;
    656 	}
    657 
    658 	return sts;
    659 }
    660 
    661 int
    662 linux32_to_native_sigevent(struct sigevent *nsep,
    663     const struct linux32_sigevent *lsep)
    664 {
    665 	memset(nsep, 0, sizeof(*nsep));
    666 
    667 	switch (lsep->sigev_notify) {
    668 	case LINUX_SIGEV_SIGNAL:
    669 		nsep->sigev_notify = SIGEV_SIGNAL;
    670 		break;
    671 
    672 	case LINUX_SIGEV_NONE:
    673 		nsep->sigev_notify = SIGEV_NONE;
    674 		break;
    675 
    676 	case LINUX_SIGEV_THREAD:
    677 	case LINUX_SIGEV_THREAD_ID:
    678 	default:
    679 		return ENOTSUP;
    680 	}
    681 
    682 	nsep->sigev_value.sival_ptr =
    683 	    NETBSD32PTR64(lsep->sigev_value.sival_ptr);
    684 
    685 	if (lsep->sigev_signo < 0 || lsep->sigev_signo >= LINUX32__NSIG) {
    686 		return EINVAL;
    687 	}
    688 	nsep->sigev_signo = linux32_to_native_signo[lsep->sigev_signo];
    689 
    690 	return 0;
    691 }
    692 
    693 int
    694 linux32_sigevent_copyin(const void *src, void *dst, size_t size)
    695 {
    696 	struct linux32_sigevent lse;
    697 	struct sigevent *sep = dst;
    698 	int error;
    699 
    700 	KASSERT(size == sizeof(*sep));
    701 
    702 	error = copyin(src, &lse, sizeof(lse));
    703 	if (error) {
    704 		return error;
    705 	}
    706 
    707 	return linux32_to_native_sigevent(sep, &lse);
    708 }
    709