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