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 5f48068adSraf * Common Development and Distribution License (the "License"). 6f48068adSraf * 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 */ 21f48068adSraf 227c478bd9Sstevel@tonic-gate /* 23*7be238fcSRoger A. Faulkner * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <sys/param.h> 287c478bd9Sstevel@tonic-gate #include <sys/types.h> 297c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 307c478bd9Sstevel@tonic-gate #include <sys/systm.h> 317c478bd9Sstevel@tonic-gate #include <sys/errno.h> 327c478bd9Sstevel@tonic-gate #include <sys/proc.h> 337c478bd9Sstevel@tonic-gate #include <sys/procset.h> 347c478bd9Sstevel@tonic-gate #include <sys/fault.h> 357c478bd9Sstevel@tonic-gate #include <sys/signal.h> 367c478bd9Sstevel@tonic-gate #include <sys/siginfo.h> 37f48068adSraf #include <sys/schedctl.h> 387c478bd9Sstevel@tonic-gate #include <vm/as.h> 397c478bd9Sstevel@tonic-gate #include <sys/debug.h> 407c478bd9Sstevel@tonic-gate #include <sys/contract/process_impl.h> 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 437c478bd9Sstevel@tonic-gate static int 447c478bd9Sstevel@tonic-gate copyin_siginfo(model_t datamodel, void *uaddr, k_siginfo_t *ksip) 457c478bd9Sstevel@tonic-gate { 467c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 477c478bd9Sstevel@tonic-gate int ret; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate if (datamodel == DATAMODEL_NATIVE) { 507c478bd9Sstevel@tonic-gate #endif 517c478bd9Sstevel@tonic-gate return (copyin(uaddr, ksip, sizeof (k_siginfo_t))); 527c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 537c478bd9Sstevel@tonic-gate } else { 547c478bd9Sstevel@tonic-gate siginfo32_t si32; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate if (ret = copyin(uaddr, &si32, sizeof (si32))) 577c478bd9Sstevel@tonic-gate return (ret); 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate siginfo_32tok(&si32, ksip); 607c478bd9Sstevel@tonic-gate } 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate return (0); 637c478bd9Sstevel@tonic-gate #endif 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* 677c478bd9Sstevel@tonic-gate * To find secured 64 bit id for signotify() call 687c478bd9Sstevel@tonic-gate * This depends upon as_getmemid() which returns 697c478bd9Sstevel@tonic-gate * unique vnode/offset for a user virtual address. 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate static u_longlong_t 727c478bd9Sstevel@tonic-gate get_sigid(proc_t *p, caddr_t addr) 737c478bd9Sstevel@tonic-gate { 747c478bd9Sstevel@tonic-gate u_longlong_t snid = 0; 757c478bd9Sstevel@tonic-gate memid_t memid; 767c478bd9Sstevel@tonic-gate quad_t *tquad = (quad_t *)&snid; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate if (!as_getmemid(p->p_as, addr, &memid)) { 797c478bd9Sstevel@tonic-gate tquad->val[0] = (int)memid.val[0]; 807c478bd9Sstevel@tonic-gate tquad->val[1] = (int)memid.val[1]; 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate return (snid); 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate #define SIGN_PTR(p, n) &((signotifyq_t *)(&p->p_signhdr[1]))[n]; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate int 887c478bd9Sstevel@tonic-gate signotify(int cmd, siginfo_t *siginfo, signotify_id_t *sn_id) 897c478bd9Sstevel@tonic-gate { 907c478bd9Sstevel@tonic-gate k_siginfo_t info; 917c478bd9Sstevel@tonic-gate signotify_id_t id; 927c478bd9Sstevel@tonic-gate proc_t *p; 937c478bd9Sstevel@tonic-gate proc_t *cp = curproc; 947c478bd9Sstevel@tonic-gate signotifyq_t *snqp; 957c478bd9Sstevel@tonic-gate struct cred *cr; 967c478bd9Sstevel@tonic-gate sigqueue_t *sqp; 977c478bd9Sstevel@tonic-gate sigqhdr_t *sqh; 987c478bd9Sstevel@tonic-gate u_longlong_t sid; 997c478bd9Sstevel@tonic-gate model_t datamodel = get_udatamodel(); 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate if (copyin(sn_id, &id, sizeof (signotify_id_t))) 1027c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate if (id.sn_index >= _SIGNOTIFY_MAX || id.sn_index < 0) 1057c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate switch (cmd) { 1087c478bd9Sstevel@tonic-gate case SN_PROC: 1097c478bd9Sstevel@tonic-gate /* get snid for the given user address of signotifyid_t */ 1107c478bd9Sstevel@tonic-gate sid = get_sigid(cp, (caddr_t)sn_id); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate if (id.sn_pid > 0) { 1137c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 1147c478bd9Sstevel@tonic-gate if ((p = prfind(id.sn_pid)) != NULL) { 1157c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1167c478bd9Sstevel@tonic-gate if (p->p_signhdr != NULL) { 1177c478bd9Sstevel@tonic-gate snqp = SIGN_PTR(p, id.sn_index); 1187c478bd9Sstevel@tonic-gate if (snqp->sn_snid == sid) { 1197c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1207c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 1217c478bd9Sstevel@tonic-gate return (set_errno(EBUSY)); 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate if (copyin_siginfo(datamodel, siginfo, &info)) 1307c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* The si_code value must indicate the signal will be queued */ 1337c478bd9Sstevel@tonic-gate if (!sigwillqueue(info.si_signo, info.si_code)) 1347c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate if (cp->p_signhdr == NULL) { 1377c478bd9Sstevel@tonic-gate /* Allocate signotify pool first time */ 1387c478bd9Sstevel@tonic-gate sqh = sigqhdralloc(sizeof (signotifyq_t), 1397c478bd9Sstevel@tonic-gate _SIGNOTIFY_MAX); 1407c478bd9Sstevel@tonic-gate mutex_enter(&cp->p_lock); 1417c478bd9Sstevel@tonic-gate if (cp->p_signhdr == NULL) { 1427c478bd9Sstevel@tonic-gate /* hang the pool head on proc */ 1437c478bd9Sstevel@tonic-gate cp->p_signhdr = sqh; 1447c478bd9Sstevel@tonic-gate } else { 1457c478bd9Sstevel@tonic-gate /* another lwp allocated the pool, free ours */ 1467c478bd9Sstevel@tonic-gate sigqhdrfree(sqh); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate } else { 1497c478bd9Sstevel@tonic-gate mutex_enter(&cp->p_lock); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate sqp = sigqalloc(cp->p_signhdr); 1537c478bd9Sstevel@tonic-gate if (sqp == NULL) { 1547c478bd9Sstevel@tonic-gate mutex_exit(&cp->p_lock); 1557c478bd9Sstevel@tonic-gate return (set_errno(EAGAIN)); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate cr = CRED(); 1587c478bd9Sstevel@tonic-gate sqp->sq_info = info; 1597c478bd9Sstevel@tonic-gate sqp->sq_info.si_pid = cp->p_pid; 1607c478bd9Sstevel@tonic-gate sqp->sq_info.si_ctid = PRCTID(cp); 1617c478bd9Sstevel@tonic-gate sqp->sq_info.si_zoneid = getzoneid(); 1627c478bd9Sstevel@tonic-gate sqp->sq_info.si_uid = crgetruid(cr); 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* fill the signotifyq_t fields */ 1657c478bd9Sstevel@tonic-gate ((signotifyq_t *)sqp)->sn_snid = sid; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate mutex_exit(&cp->p_lock); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* complete the signotify_id_t fields */ 1707c478bd9Sstevel@tonic-gate id.sn_index = (signotifyq_t *)sqp - SIGN_PTR(cp, 0); 1717c478bd9Sstevel@tonic-gate id.sn_pid = cp->p_pid; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate break; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate case SN_CANCEL: 1767c478bd9Sstevel@tonic-gate case SN_SEND: 1777c478bd9Sstevel@tonic-gate 1787fabbdb7SDhanaraj M sid = get_sigid(cp, (caddr_t)sn_id); 1797c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 1807c478bd9Sstevel@tonic-gate if ((id.sn_pid <= 0) || ((p = prfind(id.sn_pid)) == NULL)) { 1817c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 1827c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 1857c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate if (p->p_signhdr == NULL) { 1887c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1897c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate snqp = SIGN_PTR(p, id.sn_index); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate if (snqp->sn_snid == 0) { 1957c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 1967c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 1997fabbdb7SDhanaraj M if (snqp->sn_snid != sid) { 2007c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 2017c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate snqp->sn_snid = 0; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* cmd == SN_CANCEL or signo == 0 (SIGEV_NONE) */ 2077c478bd9Sstevel@tonic-gate if (((sigqueue_t *)snqp)->sq_info.si_signo <= 0) 2087c478bd9Sstevel@tonic-gate cmd = SN_CANCEL; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate sigqsend(cmd, p, 0, (sigqueue_t *)snqp); 2117c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate id.sn_pid = 0; 2147c478bd9Sstevel@tonic-gate id.sn_index = 0; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate break; 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate default : 2197c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate if (copyout(&id, sn_id, sizeof (signotify_id_t))) 2237c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate return (0); 2267c478bd9Sstevel@tonic-gate } 227f48068adSraf 228f48068adSraf int 229f48068adSraf sigresend(int sig, siginfo_t *siginfo, sigset_t *mask) 230f48068adSraf { 231f48068adSraf kthread_t *t = curthread; 232f48068adSraf klwp_t *lwp = ttolwp(t); 233f48068adSraf sigqueue_t *sqp = kmem_zalloc(sizeof (*sqp), KM_SLEEP); 234f48068adSraf sigset_t set; 235f48068adSraf k_sigset_t kset; 236f48068adSraf int error; 237f48068adSraf 238f48068adSraf if (sig <= 0 || sig >= NSIG || sigismember(&cantmask, sig)) { 239f48068adSraf error = EINVAL; 240f48068adSraf goto bad; 241f48068adSraf } 242f48068adSraf 243f48068adSraf if (siginfo == NULL) { 244f48068adSraf sqp->sq_info.si_signo = sig; 245f48068adSraf sqp->sq_info.si_code = SI_NOINFO; 246f48068adSraf } else { 247f48068adSraf if (copyin_siginfo(get_udatamodel(), siginfo, &sqp->sq_info)) { 248f48068adSraf error = EFAULT; 249f48068adSraf goto bad; 250f48068adSraf } 251f48068adSraf if (sqp->sq_info.si_signo != sig) { 252f48068adSraf error = EINVAL; 253f48068adSraf goto bad; 254f48068adSraf } 255f48068adSraf } 256f48068adSraf 257f48068adSraf if (copyin(mask, &set, sizeof (set))) { 258f48068adSraf error = EFAULT; 259f48068adSraf goto bad; 260f48068adSraf } 261f48068adSraf sigutok(&set, &kset); 262f48068adSraf 263*7be238fcSRoger A. Faulkner /* 264*7be238fcSRoger A. Faulkner * We don't need to acquire p->p_lock here; 265*7be238fcSRoger A. Faulkner * we are manipulating thread-private data. 266*7be238fcSRoger A. Faulkner */ 267f48068adSraf if (lwp->lwp_cursig || lwp->lwp_curinfo) { 268f48068adSraf t->t_sig_check = 1; 269f48068adSraf error = EAGAIN; 270f48068adSraf goto bad; 271f48068adSraf } 272f48068adSraf lwp->lwp_cursig = sig; 273f48068adSraf lwp->lwp_curinfo = sqp; 274f48068adSraf schedctl_finish_sigblock(t); 275f48068adSraf t->t_hold = kset; 276f48068adSraf t->t_sig_check = 1; 277f48068adSraf return (0); 278f48068adSraf bad: 279f48068adSraf kmem_free(sqp, sizeof (*sqp)); 280f48068adSraf return (set_errno(error)); 281f48068adSraf } 282