From owner-svn-src-head@FreeBSD.ORG Sat Dec 19 18:42:13 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3C8051065670; Sat, 19 Dec 2009 18:42:13 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2B65D8FC0A; Sat, 19 Dec 2009 18:42:13 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nBJIgDi6040511; Sat, 19 Dec 2009 18:42:13 GMT (envelope-from ed@svn.freebsd.org) Received: (from ed@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nBJIgDgP040506; Sat, 19 Dec 2009 18:42:13 GMT (envelope-from ed@svn.freebsd.org) Message-Id: <200912191842.nBJIgDgP040506@svn.freebsd.org> From: Ed Schouten Date: Sat, 19 Dec 2009 18:42:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r200732 - in head/sys: fs/devfs kern sys X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Dec 2009 18:42:13 -0000 Author: ed Date: Sat Dec 19 18:42:12 2009 New Revision: 200732 URL: http://svn.freebsd.org/changeset/base/200732 Log: Let access overriding to TTYs depend on the cdev_priv, not the vnode. Basically this commit changes two things, which improves access to TTYs in exceptional conditions. Basically the problem was that when you ran jexec(8) to attach to a jail, you couldn't use /dev/tty (well, also the node of the actual TTY, e.g. /dev/pts/X). This is very inconvenient if you want to attach to screens quickly, use ssh(1), etc. The fixes: - Cache the cdev_priv of the controlling TTY in struct session. Change devfs_access() to compare against the cdev_priv instead of the vnode. This allows you to bypass UNIX permissions, even across different mounts of devfs. - Extend devfs_prison_check() to unconditionally expose the device node of the controlling TTY, even if normal prison nesting rules normally don't allow this. This actually allows you to interact with this device node. To be honest, I'm not really happy with this solution. We now have to store three pointers to a controlling TTY (s_ttyp, s_ttyvp, s_ttydp). In an ideal world, we should just get rid of the latter two and only use s_ttyp, but this makes certian pieces of code very impractical (e.g. devfs, kern_exit.c). Reported by: Many people Modified: head/sys/fs/devfs/devfs_vnops.c head/sys/kern/kern_exit.c head/sys/kern/kern_proc.c head/sys/sys/proc.h Modified: head/sys/fs/devfs/devfs_vnops.c ============================================================================== --- head/sys/fs/devfs/devfs_vnops.c Sat Dec 19 16:36:57 2009 (r200731) +++ head/sys/fs/devfs/devfs_vnops.c Sat Dec 19 18:42:12 2009 (r200732) @@ -436,14 +436,14 @@ devfs_access(struct vop_access_args *ap) error = vaccess(vp->v_type, de->de_mode, de->de_uid, de->de_gid, ap->a_accmode, ap->a_cred, NULL); - if (!error) - return (error); + if (error == 0) + return (0); if (error != EACCES) return (error); /* We do, however, allow access to the controlling terminal */ if (!(ap->a_td->td_proc->p_flag & P_CONTROLT)) return (error); - if (ap->a_td->td_proc->p_session->s_ttyvp == de->de_vnode) + if (ap->a_td->td_proc->p_session->s_ttydp == de->de_cdp) return (0); return (error); } @@ -474,6 +474,7 @@ devfs_close(struct vop_close_args *ap) VI_LOCK(vp); if (count_dev(dev) == 2 && (vp->v_iflag & VI_DOOMED) == 0) { td->td_proc->p_session->s_ttyvp = NULL; + td->td_proc->p_session->s_ttydp = NULL; oldvp = vp; } VI_UNLOCK(vp); @@ -675,6 +676,7 @@ devfs_ioctl_f(struct file *fp, u_long co VREF(vp); SESS_LOCK(td->td_proc->p_session); td->td_proc->p_session->s_ttyvp = vp; + td->td_proc->p_session->s_ttydp = cdev2priv(dev); SESS_UNLOCK(td->td_proc->p_session); sx_sunlock(&proctree_lock); @@ -708,10 +710,11 @@ devfs_kqfilter_f(struct file *fp, struct } static inline int -devfs_prison_check(struct devfs_dirent *de, struct ucred *tcr) +devfs_prison_check(struct devfs_dirent *de, struct thread *td) { struct cdev_priv *cdp; struct ucred *dcr; + int error; cdp = de->de_cdp; if (cdp == NULL) @@ -720,7 +723,15 @@ devfs_prison_check(struct devfs_dirent * if (dcr == NULL) return (0); - return (prison_check(tcr, dcr)); + error = prison_check(td->td_ucred, dcr); + if (error == 0) + return (0); + /* We do, however, allow access to the controlling terminal */ + if (!(td->td_proc->p_flag & P_CONTROLT)) + return (error); + if (td->td_proc->p_session->s_ttydp == cdp) + return (0); + return (error); } static int @@ -848,7 +859,7 @@ devfs_lookupx(struct vop_lookup_args *ap return (ENOENT); } - if (devfs_prison_check(de, td->td_ucred)) + if (devfs_prison_check(de, td)) return (ENOENT); if ((cnp->cn_nameiop == DELETE) && (flags & ISLASTCN)) { @@ -1126,7 +1137,7 @@ devfs_readdir(struct vop_readdir_args *a KASSERT(dd->de_cdp != (void *)0xdeadc0de, ("%s %d\n", __func__, __LINE__)); if (dd->de_flags & DE_WHITEOUT) continue; - if (devfs_prison_check(dd, ap->a_cred)) + if (devfs_prison_check(dd, uio->uio_td)) continue; if (dd->de_dirent->d_type == DT_DIR) de = dd->de_dir; Modified: head/sys/kern/kern_exit.c ============================================================================== --- head/sys/kern/kern_exit.c Sat Dec 19 16:36:57 2009 (r200731) +++ head/sys/kern/kern_exit.c Sat Dec 19 18:42:12 2009 (r200732) @@ -316,6 +316,7 @@ exit1(struct thread *td, int rv) ttyvp = sp->s_ttyvp; tp = sp->s_ttyp; sp->s_ttyvp = NULL; + sp->s_ttydp = NULL; sp->s_leader = NULL; SESS_UNLOCK(sp); Modified: head/sys/kern/kern_proc.c ============================================================================== --- head/sys/kern/kern_proc.c Sat Dec 19 16:36:57 2009 (r200731) +++ head/sys/kern/kern_proc.c Sat Dec 19 18:42:12 2009 (r200732) @@ -358,6 +358,7 @@ enterpgrp(p, pgid, pgrp, sess) sess->s_sid = p->p_pid; refcount_init(&sess->s_count, 1); sess->s_ttyvp = NULL; + sess->s_ttydp = NULL; sess->s_ttyp = NULL; bcopy(p->p_session->s_login, sess->s_login, sizeof(sess->s_login)); Modified: head/sys/sys/proc.h ============================================================================== --- head/sys/sys/proc.h Sat Dec 19 16:36:57 2009 (r200731) +++ head/sys/sys/proc.h Sat Dec 19 18:42:12 2009 (r200732) @@ -77,6 +77,7 @@ struct session { u_int s_count; /* Ref cnt; pgrps in session - atomic. */ struct proc *s_leader; /* (m + e) Session leader. */ struct vnode *s_ttyvp; /* (m) Vnode of controlling tty. */ + struct cdev_priv *s_ttydp; /* (m) Device of controlling tty. */ struct tty *s_ttyp; /* (e) Controlling tty. */ pid_t s_sid; /* (c) Session ID. */ /* (m) Setlogin() name: */