xref: /onnv-gate/usr/src/uts/common/syscall/sigqueue.c (revision 2248:4609e8bb25ad)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*2248Sraf  * Common Development and Distribution License (the "License").
6*2248Sraf  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*2248Sraf 
220Sstevel@tonic-gate /*
23*2248Sraf  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*2248Sraf  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
27*2248Sraf /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <sys/param.h>
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/sysmacros.h>
340Sstevel@tonic-gate #include <sys/systm.h>
350Sstevel@tonic-gate #include <sys/errno.h>
360Sstevel@tonic-gate #include <sys/proc.h>
370Sstevel@tonic-gate #include <sys/procset.h>
380Sstevel@tonic-gate #include <sys/fault.h>
390Sstevel@tonic-gate #include <sys/signal.h>
400Sstevel@tonic-gate #include <sys/siginfo.h>
410Sstevel@tonic-gate #include <sys/debug.h>
420Sstevel@tonic-gate 
430Sstevel@tonic-gate static int
sigqkill(pid_t pid,sigsend_t * sigsend)44*2248Sraf sigqkill(pid_t pid, sigsend_t *sigsend)
450Sstevel@tonic-gate {
46*2248Sraf 	proc_t *p;
470Sstevel@tonic-gate 	int error;
480Sstevel@tonic-gate 
49*2248Sraf 	if ((uint_t)sigsend->sig >= NSIG)
50*2248Sraf 		return (EINVAL);
510Sstevel@tonic-gate 
520Sstevel@tonic-gate 	if (pid == -1) {
530Sstevel@tonic-gate 		procset_t set;
540Sstevel@tonic-gate 
550Sstevel@tonic-gate 		setprocset(&set, POP_AND, P_ALL, P_MYID, P_ALL, P_MYID);
560Sstevel@tonic-gate 		error = sigsendset(&set, sigsend);
570Sstevel@tonic-gate 	} else if (pid > 0) {
580Sstevel@tonic-gate 		mutex_enter(&pidlock);
590Sstevel@tonic-gate 		if ((p = prfind(pid)) == NULL || p->p_stat == SIDL)
600Sstevel@tonic-gate 			error = ESRCH;
610Sstevel@tonic-gate 		else {
620Sstevel@tonic-gate 			error = sigsendproc(p, sigsend);
630Sstevel@tonic-gate 			if (error == 0 && sigsend->perm == 0)
640Sstevel@tonic-gate 				error = EPERM;
650Sstevel@tonic-gate 		}
660Sstevel@tonic-gate 		mutex_exit(&pidlock);
670Sstevel@tonic-gate 	} else {
680Sstevel@tonic-gate 		int nfound = 0;
690Sstevel@tonic-gate 		pid_t pgid;
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 		if (pid == 0)
720Sstevel@tonic-gate 			pgid = ttoproc(curthread)->p_pgrp;
730Sstevel@tonic-gate 		else
740Sstevel@tonic-gate 			pgid = -pid;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 		error = 0;
770Sstevel@tonic-gate 		mutex_enter(&pidlock);
780Sstevel@tonic-gate 		for (p = pgfind(pgid); p && !error; p = p->p_pglink) {
790Sstevel@tonic-gate 			if (p->p_stat != SIDL) {
800Sstevel@tonic-gate 				nfound++;
810Sstevel@tonic-gate 				error = sigsendproc(p, sigsend);
820Sstevel@tonic-gate 			}
830Sstevel@tonic-gate 		}
840Sstevel@tonic-gate 		mutex_exit(&pidlock);
850Sstevel@tonic-gate 		if (nfound == 0)
860Sstevel@tonic-gate 			error = ESRCH;
870Sstevel@tonic-gate 		else if (error == 0 && sigsend->perm == 0)
880Sstevel@tonic-gate 			error = EPERM;
890Sstevel@tonic-gate 	}
900Sstevel@tonic-gate 
91*2248Sraf 	return (error);
920Sstevel@tonic-gate }
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate  * for implementations that don't require binary compatibility,
970Sstevel@tonic-gate  * the kill system call may be made into a library call to the
980Sstevel@tonic-gate  * sigsend system call
990Sstevel@tonic-gate  */
1000Sstevel@tonic-gate int
kill(pid_t pid,int sig)1010Sstevel@tonic-gate kill(pid_t pid, int sig)
1020Sstevel@tonic-gate {
103*2248Sraf 	int error;
1040Sstevel@tonic-gate 	sigsend_t v;
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	bzero(&v, sizeof (v));
1070Sstevel@tonic-gate 	v.sig = sig;
1080Sstevel@tonic-gate 	v.checkperm = 1;
1090Sstevel@tonic-gate 	v.sicode = SI_USER;
110*2248Sraf 	if ((error = sigqkill(pid, &v)) != 0)
111*2248Sraf 		return (set_errno(error));
112*2248Sraf 	return (0);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate /*
1160Sstevel@tonic-gate  * The handling of small unions, like the sigval argument to sigqueue,
117*2248Sraf  * is architecture dependent.  We have adopted the convention that the
1180Sstevel@tonic-gate  * value itself is passed in the storage which crosses the kernel
1190Sstevel@tonic-gate  * protection boundary.  This procedure will accept a scalar argument,
1200Sstevel@tonic-gate  * and store it in the appropriate value member of the sigsend_t structure.
1210Sstevel@tonic-gate  */
1220Sstevel@tonic-gate int
sigqueue(pid_t pid,int sig,void * value,int si_code,int block)123*2248Sraf sigqueue(pid_t pid, int sig, /* union sigval */ void *value,
124*2248Sraf 	int si_code, int block)
1250Sstevel@tonic-gate {
126*2248Sraf 	int error;
1270Sstevel@tonic-gate 	sigsend_t v;
1280Sstevel@tonic-gate 	sigqhdr_t *sqh;
1290Sstevel@tonic-gate 	proc_t *p = curproc;
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	/* The si_code value must indicate the signal will be queued */
132*2248Sraf 	if (pid <= 0 || !sigwillqueue(sig, si_code))
1330Sstevel@tonic-gate 		return (set_errno(EINVAL));
1340Sstevel@tonic-gate 
135*2248Sraf 	if ((sqh = p->p_sigqhdr) == NULL) {
1360Sstevel@tonic-gate 		/* Allocate sigqueue pool first time */
1370Sstevel@tonic-gate 		sqh = sigqhdralloc(sizeof (sigqueue_t), _SIGQUEUE_MAX);
1380Sstevel@tonic-gate 		mutex_enter(&p->p_lock);
1390Sstevel@tonic-gate 		if (p->p_sigqhdr == NULL) {
1400Sstevel@tonic-gate 			/* hang the pool head on proc */
1410Sstevel@tonic-gate 			p->p_sigqhdr = sqh;
1420Sstevel@tonic-gate 		} else {
1430Sstevel@tonic-gate 			/* another lwp allocated the pool, free ours */
1440Sstevel@tonic-gate 			sigqhdrfree(sqh);
145*2248Sraf 			sqh = p->p_sigqhdr;
1460Sstevel@tonic-gate 		}
1470Sstevel@tonic-gate 		mutex_exit(&p->p_lock);
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 
150*2248Sraf 	do {
151*2248Sraf 		bzero(&v, sizeof (v));
152*2248Sraf 		v.sig = sig;
153*2248Sraf 		v.checkperm = 1;
154*2248Sraf 		v.sicode = si_code;
155*2248Sraf 		v.value.sival_ptr = value;
156*2248Sraf 		if ((error = sigqkill(pid, &v)) != EAGAIN || !block)
157*2248Sraf 			break;
158*2248Sraf 		/* block waiting for another chance to allocate a sigqueue_t */
159*2248Sraf 		mutex_enter(&sqh->sqb_lock);
160*2248Sraf 		while (sqh->sqb_count == 0) {
161*2248Sraf 			if (!cv_wait_sig(&sqh->sqb_cv, &sqh->sqb_lock)) {
162*2248Sraf 				error = EINTR;
163*2248Sraf 				break;
164*2248Sraf 			}
165*2248Sraf 		}
166*2248Sraf 		mutex_exit(&sqh->sqb_lock);
167*2248Sraf 	} while (error == EAGAIN);
1680Sstevel@tonic-gate 
169*2248Sraf 	if (error)
170*2248Sraf 		return (set_errno(error));
171*2248Sraf 	return (0);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
1750Sstevel@tonic-gate /*
1760Sstevel@tonic-gate  * sigqueue32 - System call entry point for 32-bit callers on LP64 kernel,
1770Sstevel@tonic-gate  * needed to handle the 32-bit sigvals as correctly as we can.  We always
1780Sstevel@tonic-gate  * assume that a 32-bit caller is passing an int. A 64-bit recipient
1790Sstevel@tonic-gate  * that expects an int will therefore get it correctly.  A 32-bit
1800Sstevel@tonic-gate  * recipient will also get it correctly since siginfo_kto32() uses
1810Sstevel@tonic-gate  * sival_int in the conversion.  Since a 32-bit pointer has the same
1820Sstevel@tonic-gate  * size and address in the sigval, it also converts correctly so that
1830Sstevel@tonic-gate  * two 32-bit apps can exchange a pointer value.  However, this means
1840Sstevel@tonic-gate  * that a pointer sent by a 32-bit caller will be seen in the upper half
1850Sstevel@tonic-gate  * by a 64-bit recipient, and only the upper half of a 64-bit pointer will
1860Sstevel@tonic-gate  * be seen by a 32-bit recipient.  This is the best solution that does
1870Sstevel@tonic-gate  * not require severe hacking of the sigval union.  Anyways, what it
1880Sstevel@tonic-gate  * means to be sending pointers between processes with dissimilar
1890Sstevel@tonic-gate  * models is unclear.
1900Sstevel@tonic-gate  */
1910Sstevel@tonic-gate int
sigqueue32(pid_t pid,int sig,caddr32_t value,int si_code,int block)192*2248Sraf sigqueue32(pid_t pid, int sig, /* union sigval32 */ caddr32_t value,
193*2248Sraf 	int si_code, int block)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate 	union sigval sv;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	bzero(&sv, sizeof (sv));
1980Sstevel@tonic-gate 	sv.sival_int = (int)value;
199*2248Sraf 	return (sigqueue(pid, sig, sv.sival_ptr, si_code, block));
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate #endif
202