1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/pcb.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/policy.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/var.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/session.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate sess_t session0 = { 57*7c478bd9Sstevel@tonic-gate 1, /* s_ref */ 58*7c478bd9Sstevel@tonic-gate 0555, /* s_mode */ 59*7c478bd9Sstevel@tonic-gate 0, /* s_uid */ 60*7c478bd9Sstevel@tonic-gate 0, /* s_gid */ 61*7c478bd9Sstevel@tonic-gate 0, /* s_ctime */ 62*7c478bd9Sstevel@tonic-gate NODEV, /* s_dev */ 63*7c478bd9Sstevel@tonic-gate NULL, /* s_vp */ 64*7c478bd9Sstevel@tonic-gate &pid0, /* s_sidp */ 65*7c478bd9Sstevel@tonic-gate NULL /* s_cred */ 66*7c478bd9Sstevel@tonic-gate }; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate void 69*7c478bd9Sstevel@tonic-gate sess_rele(sess_t *sp) 70*7c478bd9Sstevel@tonic-gate { 71*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pidlock)); 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate ASSERT(sp->s_ref != 0); 74*7c478bd9Sstevel@tonic-gate if (--sp->s_ref == 0) { 75*7c478bd9Sstevel@tonic-gate if (sp == &session0) 76*7c478bd9Sstevel@tonic-gate panic("sp == &session0"); 77*7c478bd9Sstevel@tonic-gate PID_RELE(sp->s_sidp); 78*7c478bd9Sstevel@tonic-gate mutex_destroy(&sp->s_lock); 79*7c478bd9Sstevel@tonic-gate cv_destroy(&sp->s_wait_cv); 80*7c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (sess_t)); 81*7c478bd9Sstevel@tonic-gate } 82*7c478bd9Sstevel@tonic-gate } 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate void 85*7c478bd9Sstevel@tonic-gate sess_create(void) 86*7c478bd9Sstevel@tonic-gate { 87*7c478bd9Sstevel@tonic-gate proc_t *pp; 88*7c478bd9Sstevel@tonic-gate sess_t *sp; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate pp = ttoproc(curthread); 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate sp = kmem_zalloc(sizeof (sess_t), KM_SLEEP); 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate mutex_init(&sp->s_lock, NULL, MUTEX_DEFAULT, NULL); 95*7c478bd9Sstevel@tonic-gate cv_init(&sp->s_wait_cv, NULL, CV_DEFAULT, NULL); 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * We need to protect p_pgidp with p_lock because 101*7c478bd9Sstevel@tonic-gate * /proc looks at it while holding only p_lock. 102*7c478bd9Sstevel@tonic-gate */ 103*7c478bd9Sstevel@tonic-gate mutex_enter(&pp->p_lock); 104*7c478bd9Sstevel@tonic-gate pgexit(pp); 105*7c478bd9Sstevel@tonic-gate SESS_RELE(pp->p_sessp); 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate sp->s_sidp = pp->p_pidp; 108*7c478bd9Sstevel@tonic-gate sp->s_ref = 1; 109*7c478bd9Sstevel@tonic-gate sp->s_dev = NODEV; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate pp->p_sessp = sp; 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate pgjoin(pp, pp->p_pidp); 114*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate PID_HOLD(sp->s_sidp); 117*7c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate void 121*7c478bd9Sstevel@tonic-gate freectty(sess_t *sp) 122*7c478bd9Sstevel@tonic-gate { 123*7c478bd9Sstevel@tonic-gate vnode_t *vp; 124*7c478bd9Sstevel@tonic-gate cred_t *cred; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate vp = sp->s_vp; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate strfreectty(vp->v_stream); 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->s_lock); 131*7c478bd9Sstevel@tonic-gate while (sp->s_cnt > 0) { 132*7c478bd9Sstevel@tonic-gate cv_wait(&sp->s_wait_cv, &sp->s_lock); 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate ASSERT(sp->s_cnt == 0); 135*7c478bd9Sstevel@tonic-gate ASSERT(vp->v_count >= 1); 136*7c478bd9Sstevel@tonic-gate sp->s_vp = NULL; 137*7c478bd9Sstevel@tonic-gate cred = sp->s_cred; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate /* 140*7c478bd9Sstevel@tonic-gate * It is possible for the VOP_CLOSE below to call strctty 141*7c478bd9Sstevel@tonic-gate * and reallocate a new tty vnode. To prevent that the 142*7c478bd9Sstevel@tonic-gate * session is marked as closing here. 143*7c478bd9Sstevel@tonic-gate */ 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate sp->s_flag = SESS_CLOSE; 146*7c478bd9Sstevel@tonic-gate sp->s_cred = NULL; 147*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->s_lock); 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate /* 150*7c478bd9Sstevel@tonic-gate * This will be the only thread with access to 151*7c478bd9Sstevel@tonic-gate * this vnode, from this point on. 152*7c478bd9Sstevel@tonic-gate */ 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate (void) VOP_CLOSE(vp, 0, 1, (offset_t)0, cred); 155*7c478bd9Sstevel@tonic-gate VN_RELE(vp); 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate crfree(cred); 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate /* 161*7c478bd9Sstevel@tonic-gate * ++++++++++++++++++++++++ 162*7c478bd9Sstevel@tonic-gate * ++ SunOS4.1 Buyback ++ 163*7c478bd9Sstevel@tonic-gate * ++++++++++++++++++++++++ 164*7c478bd9Sstevel@tonic-gate * 165*7c478bd9Sstevel@tonic-gate * vhangup: Revoke access of the current tty by all processes 166*7c478bd9Sstevel@tonic-gate * Used by privileged users to give a "clean" terminal at login 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate int 169*7c478bd9Sstevel@tonic-gate vhangup() 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate if (secpolicy_sys_config(CRED(), B_FALSE) != 0) 172*7c478bd9Sstevel@tonic-gate return (set_errno(EPERM)); 173*7c478bd9Sstevel@tonic-gate /* 174*7c478bd9Sstevel@tonic-gate * This routine used to call freectty() under a condition that 175*7c478bd9Sstevel@tonic-gate * could never happen. So this code has never actually done 176*7c478bd9Sstevel@tonic-gate * anything, and evidently nobody has ever noticed. 4098399. 177*7c478bd9Sstevel@tonic-gate */ 178*7c478bd9Sstevel@tonic-gate return (0); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate dev_t 182*7c478bd9Sstevel@tonic-gate cttydev(proc_t *pp) 183*7c478bd9Sstevel@tonic-gate { 184*7c478bd9Sstevel@tonic-gate sess_t *sp = pp->p_sessp; 185*7c478bd9Sstevel@tonic-gate if (sp->s_vp == NULL) 186*7c478bd9Sstevel@tonic-gate return (NODEV); 187*7c478bd9Sstevel@tonic-gate return (sp->s_dev); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate void 191*7c478bd9Sstevel@tonic-gate alloctty(proc_t *pp, vnode_t *vp) 192*7c478bd9Sstevel@tonic-gate { 193*7c478bd9Sstevel@tonic-gate sess_t *sp = pp->p_sessp; 194*7c478bd9Sstevel@tonic-gate cred_t *crp; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate sp->s_vp = vp; 197*7c478bd9Sstevel@tonic-gate sp->s_dev = vp->v_rdev; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate mutex_enter(&pp->p_crlock); 200*7c478bd9Sstevel@tonic-gate crhold(crp = pp->p_cred); 201*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_crlock); 202*7c478bd9Sstevel@tonic-gate sp->s_cred = crp; 203*7c478bd9Sstevel@tonic-gate sp->s_uid = crgetuid(crp); 204*7c478bd9Sstevel@tonic-gate sp->s_ctime = gethrestime_sec(); 205*7c478bd9Sstevel@tonic-gate if (session0.s_mode & VSGID) 206*7c478bd9Sstevel@tonic-gate sp->s_gid = session0.s_gid; 207*7c478bd9Sstevel@tonic-gate else 208*7c478bd9Sstevel@tonic-gate sp->s_gid = crgetgid(crp); 209*7c478bd9Sstevel@tonic-gate sp->s_mode = (0666 & ~(PTOU(pp)->u_cmask)); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate int 213*7c478bd9Sstevel@tonic-gate hascttyperm(sess_t *sp, cred_t *cr, mode_t mode) 214*7c478bd9Sstevel@tonic-gate { 215*7c478bd9Sstevel@tonic-gate int shift = 0; 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate if (crgetuid(cr) != sp->s_uid) { 218*7c478bd9Sstevel@tonic-gate shift += 3; 219*7c478bd9Sstevel@tonic-gate if (!groupmember(sp->s_gid, cr)) 220*7c478bd9Sstevel@tonic-gate shift += 3; 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate mode &= ~(sp->s_mode << shift); 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate if (mode == 0) 226*7c478bd9Sstevel@tonic-gate return (1); 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate return (secpolicy_vnode_access(cr, sp->s_vp, sp->s_uid, mode) == 0); 229*7c478bd9Sstevel@tonic-gate } 230