17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5f841f6adSraf * Common Development and Distribution License (the "License"). 6f841f6adSraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21f841f6adSraf 227c478bd9Sstevel@tonic-gate /* 23f841f6adSraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24f841f6adSraf * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <sys/param.h> 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 327c478bd9Sstevel@tonic-gate #include <sys/systm.h> 337c478bd9Sstevel@tonic-gate #include <sys/errno.h> 347c478bd9Sstevel@tonic-gate #include <sys/proc.h> 357c478bd9Sstevel@tonic-gate #include <sys/procset.h> 367c478bd9Sstevel@tonic-gate #include <sys/fault.h> 377c478bd9Sstevel@tonic-gate #include <sys/signal.h> 387c478bd9Sstevel@tonic-gate #include <sys/siginfo.h> 397c478bd9Sstevel@tonic-gate #include <sys/debug.h> 407c478bd9Sstevel@tonic-gate 41*5e989a96SDavid Höppner extern rctl_hndl_t rc_process_sigqueue; 42*5e989a96SDavid Höppner 437c478bd9Sstevel@tonic-gate static int 44f841f6adSraf sigqkill(pid_t pid, sigsend_t *sigsend) 457c478bd9Sstevel@tonic-gate { 46f841f6adSraf proc_t *p; 477c478bd9Sstevel@tonic-gate int error; 487c478bd9Sstevel@tonic-gate 49f841f6adSraf if ((uint_t)sigsend->sig >= NSIG) 50f841f6adSraf return (EINVAL); 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate if (pid == -1) { 537c478bd9Sstevel@tonic-gate procset_t set; 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate setprocset(&set, POP_AND, P_ALL, P_MYID, P_ALL, P_MYID); 567c478bd9Sstevel@tonic-gate error = sigsendset(&set, sigsend); 577c478bd9Sstevel@tonic-gate } else if (pid > 0) { 587c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 597c478bd9Sstevel@tonic-gate if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) 607c478bd9Sstevel@tonic-gate error = ESRCH; 617c478bd9Sstevel@tonic-gate else { 627c478bd9Sstevel@tonic-gate error = sigsendproc(p, sigsend); 637c478bd9Sstevel@tonic-gate if (error == 0 && sigsend->perm == 0) 647c478bd9Sstevel@tonic-gate error = EPERM; 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 677c478bd9Sstevel@tonic-gate } else { 687c478bd9Sstevel@tonic-gate int nfound = 0; 697c478bd9Sstevel@tonic-gate pid_t pgid; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate if (pid == 0) 727c478bd9Sstevel@tonic-gate pgid = ttoproc(curthread)->p_pgrp; 737c478bd9Sstevel@tonic-gate else 747c478bd9Sstevel@tonic-gate pgid = -pid; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate error = 0; 777c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 787c478bd9Sstevel@tonic-gate for (p = pgfind(pgid); p && !error; p = p->p_pglink) { 797c478bd9Sstevel@tonic-gate if (p->p_stat != SIDL) { 807c478bd9Sstevel@tonic-gate nfound++; 817c478bd9Sstevel@tonic-gate error = sigsendproc(p, sigsend); 827c478bd9Sstevel@tonic-gate } 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 857c478bd9Sstevel@tonic-gate if (nfound == 0) 867c478bd9Sstevel@tonic-gate error = ESRCH; 877c478bd9Sstevel@tonic-gate else if (error == 0 && sigsend->perm == 0) 887c478bd9Sstevel@tonic-gate error = EPERM; 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate 91f841f6adSraf return (error); 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /* 967c478bd9Sstevel@tonic-gate * for implementations that don't require binary compatibility, 977c478bd9Sstevel@tonic-gate * the kill system call may be made into a library call to the 987c478bd9Sstevel@tonic-gate * sigsend system call 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate int 1017c478bd9Sstevel@tonic-gate kill(pid_t pid, int sig) 1027c478bd9Sstevel@tonic-gate { 103f841f6adSraf int error; 1047c478bd9Sstevel@tonic-gate sigsend_t v; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate bzero(&v, sizeof (v)); 1077c478bd9Sstevel@tonic-gate v.sig = sig; 1087c478bd9Sstevel@tonic-gate v.checkperm = 1; 1097c478bd9Sstevel@tonic-gate v.sicode = SI_USER; 110f841f6adSraf if ((error = sigqkill(pid, &v)) != 0) 111f841f6adSraf return (set_errno(error)); 112f841f6adSraf return (0); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * The handling of small unions, like the sigval argument to sigqueue, 117f841f6adSraf * is architecture dependent. We have adopted the convention that the 1187c478bd9Sstevel@tonic-gate * value itself is passed in the storage which crosses the kernel 1197c478bd9Sstevel@tonic-gate * protection boundary. This procedure will accept a scalar argument, 1207c478bd9Sstevel@tonic-gate * and store it in the appropriate value member of the sigsend_t structure. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate int 123f841f6adSraf sigqueue(pid_t pid, int sig, /* union sigval */ void *value, 124f841f6adSraf int si_code, int block) 1257c478bd9Sstevel@tonic-gate { 126f841f6adSraf int error; 1277c478bd9Sstevel@tonic-gate sigsend_t v; 1287c478bd9Sstevel@tonic-gate sigqhdr_t *sqh; 1297c478bd9Sstevel@tonic-gate proc_t *p = curproc; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* The si_code value must indicate the signal will be queued */ 132f841f6adSraf if (pid <= 0 || !sigwillqueue(sig, si_code)) 1337c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 1347c478bd9Sstevel@tonic-gate 135f841f6adSraf if ((sqh = p->p_sigqhdr) == NULL) { 136*5e989a96SDavid Höppner rlim64_t sigqsz_max; 137*5e989a96SDavid Höppner 138*5e989a96SDavid Höppner mutex_enter(&p->p_lock); 139*5e989a96SDavid Höppner sigqsz_max = rctl_enforced_value(rc_process_sigqueue, 140*5e989a96SDavid Höppner p->p_rctls, p); 141*5e989a96SDavid Höppner mutex_exit(&p->p_lock); 142*5e989a96SDavid Höppner 1437c478bd9Sstevel@tonic-gate /* Allocate sigqueue pool first time */ 144*5e989a96SDavid Höppner sqh = sigqhdralloc(sizeof (sigqueue_t), (uint_t)sigqsz_max); 1457c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1467c478bd9Sstevel@tonic-gate if (p->p_sigqhdr == NULL) { 1477c478bd9Sstevel@tonic-gate /* hang the pool head on proc */ 1487c478bd9Sstevel@tonic-gate p->p_sigqhdr = sqh; 1497c478bd9Sstevel@tonic-gate } else { 1507c478bd9Sstevel@tonic-gate /* another lwp allocated the pool, free ours */ 1517c478bd9Sstevel@tonic-gate sigqhdrfree(sqh); 152f841f6adSraf sqh = p->p_sigqhdr; 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 157f841f6adSraf do { 1587c478bd9Sstevel@tonic-gate bzero(&v, sizeof (v)); 159f841f6adSraf v.sig = sig; 1607c478bd9Sstevel@tonic-gate v.checkperm = 1; 1617c478bd9Sstevel@tonic-gate v.sicode = si_code; 1627c478bd9Sstevel@tonic-gate v.value.sival_ptr = value; 163f841f6adSraf if ((error = sigqkill(pid, &v)) != EAGAIN || !block) 164f841f6adSraf break; 165f841f6adSraf /* block waiting for another chance to allocate a sigqueue_t */ 166f841f6adSraf mutex_enter(&sqh->sqb_lock); 167f841f6adSraf while (sqh->sqb_count == 0) { 168f841f6adSraf if (!cv_wait_sig(&sqh->sqb_cv, &sqh->sqb_lock)) { 169f841f6adSraf error = EINTR; 170f841f6adSraf break; 171f841f6adSraf } 172f841f6adSraf } 173f841f6adSraf mutex_exit(&sqh->sqb_lock); 174f841f6adSraf } while (error == EAGAIN); 1757c478bd9Sstevel@tonic-gate 176f841f6adSraf if (error) 177f841f6adSraf return (set_errno(error)); 178f841f6adSraf return (0); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * sigqueue32 - System call entry point for 32-bit callers on LP64 kernel, 1847c478bd9Sstevel@tonic-gate * needed to handle the 32-bit sigvals as correctly as we can. We always 1857c478bd9Sstevel@tonic-gate * assume that a 32-bit caller is passing an int. A 64-bit recipient 1867c478bd9Sstevel@tonic-gate * that expects an int will therefore get it correctly. A 32-bit 1877c478bd9Sstevel@tonic-gate * recipient will also get it correctly since siginfo_kto32() uses 1887c478bd9Sstevel@tonic-gate * sival_int in the conversion. Since a 32-bit pointer has the same 1897c478bd9Sstevel@tonic-gate * size and address in the sigval, it also converts correctly so that 1907c478bd9Sstevel@tonic-gate * two 32-bit apps can exchange a pointer value. However, this means 1917c478bd9Sstevel@tonic-gate * that a pointer sent by a 32-bit caller will be seen in the upper half 1927c478bd9Sstevel@tonic-gate * by a 64-bit recipient, and only the upper half of a 64-bit pointer will 1937c478bd9Sstevel@tonic-gate * be seen by a 32-bit recipient. This is the best solution that does 1947c478bd9Sstevel@tonic-gate * not require severe hacking of the sigval union. Anyways, what it 1957c478bd9Sstevel@tonic-gate * means to be sending pointers between processes with dissimilar 1967c478bd9Sstevel@tonic-gate * models is unclear. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate int 199f841f6adSraf sigqueue32(pid_t pid, int sig, /* union sigval32 */ caddr32_t value, 200f841f6adSraf int si_code, int block) 2017c478bd9Sstevel@tonic-gate { 2027c478bd9Sstevel@tonic-gate union sigval sv; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate bzero(&sv, sizeof (sv)); 2057c478bd9Sstevel@tonic-gate sv.sival_int = (int)value; 206f841f6adSraf return (sigqueue(pid, sig, sv.sival_ptr, si_code, block)); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate #endif 209