1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1998-2000 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include <sys/param.h> 34 #include <sys/types.h> 35 #include <sys/sysmacros.h> 36 #include <sys/systm.h> 37 #include <sys/errno.h> 38 #include <sys/proc.h> 39 #include <sys/procset.h> 40 #include <sys/fault.h> 41 #include <sys/signal.h> 42 #include <sys/siginfo.h> 43 #include <sys/debug.h> 44 45 static int 46 sigqkill(pid_t pid, int signo, sigsend_t *sigsend) 47 { 48 register proc_t *p; 49 int error; 50 51 if (signo < 0 || signo >= NSIG) 52 return (set_errno(EINVAL)); 53 54 if (pid == -1) { 55 procset_t set; 56 57 setprocset(&set, POP_AND, P_ALL, P_MYID, P_ALL, P_MYID); 58 error = sigsendset(&set, sigsend); 59 } else if (pid > 0) { 60 mutex_enter(&pidlock); 61 if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) 62 error = ESRCH; 63 else { 64 error = sigsendproc(p, sigsend); 65 if (error == 0 && sigsend->perm == 0) 66 error = EPERM; 67 } 68 mutex_exit(&pidlock); 69 } else { 70 int nfound = 0; 71 pid_t pgid; 72 73 if (pid == 0) 74 pgid = ttoproc(curthread)->p_pgrp; 75 else 76 pgid = -pid; 77 78 error = 0; 79 mutex_enter(&pidlock); 80 for (p = pgfind(pgid); p && !error; p = p->p_pglink) { 81 if (p->p_stat != SIDL) { 82 nfound++; 83 error = sigsendproc(p, sigsend); 84 } 85 } 86 mutex_exit(&pidlock); 87 if (nfound == 0) 88 error = ESRCH; 89 else if (error == 0 && sigsend->perm == 0) 90 error = EPERM; 91 } 92 93 if (error) 94 return (set_errno(error)); 95 return (0); 96 } 97 98 99 /* 100 * for implementations that don't require binary compatibility, 101 * the kill system call may be made into a library call to the 102 * sigsend system call 103 */ 104 int 105 kill(pid_t pid, int sig) 106 { 107 sigsend_t v; 108 109 bzero(&v, sizeof (v)); 110 v.sig = sig; 111 v.checkperm = 1; 112 v.sicode = SI_USER; 113 114 return (sigqkill(pid, sig, &v)); 115 } 116 117 /* 118 * The handling of small unions, like the sigval argument to sigqueue, 119 * is architecture dependent. We have adapted the convention that the 120 * value itself is passed in the storage which crosses the kernel 121 * protection boundary. This procedure will accept a scalar argument, 122 * and store it in the appropriate value member of the sigsend_t structure. 123 */ 124 int 125 sigqueue(pid_t pid, int signo, /* union sigval */ void *value, int si_code) 126 { 127 sigsend_t v; 128 sigqhdr_t *sqh; 129 proc_t *p = curproc; 130 131 /* The si_code value must indicate the signal will be queued */ 132 if (pid <= 0 || !sigwillqueue(signo, si_code)) 133 return (set_errno(EINVAL)); 134 135 if (p->p_sigqhdr == NULL) { 136 /* Allocate sigqueue pool first time */ 137 sqh = sigqhdralloc(sizeof (sigqueue_t), _SIGQUEUE_MAX); 138 mutex_enter(&p->p_lock); 139 if (p->p_sigqhdr == NULL) { 140 /* hang the pool head on proc */ 141 p->p_sigqhdr = sqh; 142 } else { 143 /* another lwp allocated the pool, free ours */ 144 sigqhdrfree(sqh); 145 } 146 mutex_exit(&p->p_lock); 147 } 148 149 bzero(&v, sizeof (v)); 150 v.sig = signo; 151 v.checkperm = 1; 152 v.sicode = si_code; 153 v.value.sival_ptr = value; 154 155 return (sigqkill(pid, signo, &v)); 156 } 157 158 #ifdef _SYSCALL32_IMPL 159 /* 160 * sigqueue32 - System call entry point for 32-bit callers on LP64 kernel, 161 * needed to handle the 32-bit sigvals as correctly as we can. We always 162 * assume that a 32-bit caller is passing an int. A 64-bit recipient 163 * that expects an int will therefore get it correctly. A 32-bit 164 * recipient will also get it correctly since siginfo_kto32() uses 165 * sival_int in the conversion. Since a 32-bit pointer has the same 166 * size and address in the sigval, it also converts correctly so that 167 * two 32-bit apps can exchange a pointer value. However, this means 168 * that a pointer sent by a 32-bit caller will be seen in the upper half 169 * by a 64-bit recipient, and only the upper half of a 64-bit pointer will 170 * be seen by a 32-bit recipient. This is the best solution that does 171 * not require severe hacking of the sigval union. Anyways, what it 172 * means to be sending pointers between processes with dissimilar 173 * models is unclear. 174 */ 175 int 176 sigqueue32(pid_t pid, int signo, /* union sigval32 */ caddr32_t value, 177 int si_code) 178 { 179 union sigval sv; 180 181 bzero(&sv, sizeof (sv)); 182 sv.sival_int = (int)value; 183 return (sigqueue(pid, signo, sv.sival_ptr, si_code)); 184 } 185 #endif 186