Some misspelling corrections. fs/ptyfs/ptyfs.h | 2 + fs/ptyfs/ptyfs_vfsops.c | 63 ++++++++++++++++++++++++++++++++++++++++++------ fs/ptyfs/ptyfs_vnops.c | 25 ++++++++++++++++++- kern/tty_bsdpty.c | 11 +++++++- kern/tty_ptm.c | 45 ++++++++++++++++------------------ kern/tty_pty.c | 4 +-- sys/pty.h | 4 +-- 7 files changed, 117 insertions(+), 37 deletions(-)
Ilya.
Index: fs/ptyfs/ptyfs.h =================================================================== RCS file: /cvsil/nbcur/src/sys/fs/ptyfs/ptyfs.h,v retrieving revision 1.6 diff -u -p -r1.6 ptyfs.h --- fs/ptyfs/ptyfs.h 24 Mar 2014 20:48:08 -0000 1.6 +++ fs/ptyfs/ptyfs.h 4 Apr 2014 10:37:57 -0000 @@ -106,6 +106,8 @@ struct ptyfsnode { }; struct ptyfsmount { + LIST_ENTRY(ptyfsmount) pmnt_le; + struct mount *pmnt_mp; gid_t pmnt_gid; mode_t pmnt_mode; int pmnt_flags; Index: fs/ptyfs/ptyfs_vfsops.c =================================================================== RCS file: /cvsil/nbcur/src/sys/fs/ptyfs/ptyfs_vfsops.c,v retrieving revision 1.13 diff -u -p -r1.13 ptyfs_vfsops.c --- fs/ptyfs/ptyfs_vfsops.c 28 Mar 2014 10:53:57 -0000 1.13 +++ fs/ptyfs/ptyfs_vfsops.c 4 Apr 2014 10:37:57 -0000 @@ -77,6 +77,7 @@ static int ptyfs__allocvp(struct mount * static int ptyfs__makename(struct mount *, struct lwp *, char *, size_t, dev_t, char); static void ptyfs__getvattr(struct mount *, struct lwp *, struct vattr *); +static int ptyfs__getmp(struct lwp *, struct mount **); /* * ptm glue: When we mount, we make ptm point to us. @@ -84,13 +85,37 @@ static void ptyfs__getvattr(struct mount struct ptm_pty *ptyfs_save_ptm; static int ptyfs_count; +static LIST_HEAD(, ptyfsmount) ptyfs_head; + struct ptm_pty ptm_ptyfspty = { ptyfs__allocvp, ptyfs__makename, ptyfs__getvattr, - NULL + ptyfs__getmp, }; +static int +ptyfs__getmp(struct lwp *l, struct mount **mpp) +{ + struct cwdinfo *cwdi = l->l_proc->p_cwdi; + struct mount *mp; + struct ptyfsmount *pmnt; + + LIST_FOREACH(pmnt, &ptyfs_head, pmnt_le) { + mp = pmnt->pmnt_mp; + if (cwdi->cwdi_rdir == NULL) + goto ok; + + if (vn_isunder(mp->mnt_vnodecovered, cwdi->cwdi_rdir, l)) + goto ok; + } + *mpp = NULL; + return EOPNOTSUPP; +ok: + *mpp = mp; + return 0; +} + static const char * ptyfs__getpath(struct lwp *l, const struct mount *mp) { @@ -137,6 +162,18 @@ ptyfs__makename(struct mount *mp, struct len = snprintf(tbuf, bufsiz, "/dev/null"); break; case 't': + /* + * We support traditional ptys, so we can get here, + * if pty had been opened before PTYFS was mounted, + * or was opened through /dev/ptyXX devices. + * Return it only outside chroot for more security . + */ + if (l->l_proc->p_cwdi->cwdi_rdir == NULL + && ptyfs_save_ptm != NULL + && ptyfs_used_get(PTYFSptc, minor(dev), mp, 0) == NULL) + return (*ptyfs_save_ptm->makename)(mp, l, + tbuf, bufsiz, dev, ms); + np = ptyfs__getpath(l, mp); if (np == NULL) return EOPNOTSUPP; @@ -189,6 +226,7 @@ void ptyfs_init(void) { + LIST_INIT(&ptyfs_head); malloc_type_attach(M_PTYFSMNT); malloc_type_attach(M_PTYFSTMP); ptyfs_hashinit(); @@ -218,7 +256,7 @@ ptyfs_mount(struct mount *mp, const char { struct lwp *l = curlwp; int error = 0; - struct ptyfsmount *pmnt; + struct ptyfsmount *pmnt, *pmnt_next; struct ptyfs_args *args = data; if (*data_len != sizeof *args && *data_len != OSIZE) @@ -274,12 +312,17 @@ ptyfs_mount(struct mount *mp, const char return error; } - /* Point pty access to us */ - if (ptyfs_count == 0) { - ptm_ptyfspty.arg = mp; + pmnt->pmnt_mp = mp; + if (ptyfs_count++ == 0) { + LIST_INSERT_HEAD(&ptyfs_head, pmnt, pmnt_le); + /* Point pty access to us */ ptyfs_save_ptm = pty_sethandler(&ptm_ptyfspty); + } else { + pmnt_next = LIST_FIRST(&ptyfs_head); + while(LIST_NEXT(pmnt_next, pmnt_le) != NULL) + pmnt_next = LIST_NEXT(pmnt_next, pmnt_le); + LIST_INSERT_AFTER(pmnt_next, pmnt, pmnt_le); } - ptyfs_count++; return 0; } @@ -296,6 +339,7 @@ ptyfs_unmount(struct mount *mp, int mntf { int error; int flags = 0; + struct ptyfsmount *pmnt; if (mntflags & MNT_FORCE) flags |= FORCECLOSE; @@ -308,8 +352,13 @@ ptyfs_unmount(struct mount *mp, int mntf /* Restore where pty access was pointing */ (void)pty_sethandler(ptyfs_save_ptm); ptyfs_save_ptm = NULL; - ptm_ptyfspty.arg = NULL; } + LIST_FOREACH(pmnt, &ptyfs_head, pmnt_le) { + if (pmnt->pmnt_mp == mp) { + LIST_REMOVE(pmnt, pmnt_le); + break; + } + } /* * Finally, throw away the ptyfsmount structure Index: fs/ptyfs/ptyfs_vnops.c =================================================================== RCS file: /cvsil/nbcur/src/sys/fs/ptyfs/ptyfs_vnops.c,v retrieving revision 1.5 diff -u -p -r1.5 ptyfs_vnops.c --- fs/ptyfs/ptyfs_vnops.c 28 Mar 2014 10:53:58 -0000 1.5 +++ fs/ptyfs/ptyfs_vnops.c 4 Apr 2014 10:37:57 -0000 @@ -141,6 +141,7 @@ int ptyfs_readdir (void *); #define ptyfs_readlink genfs_eopnotsupp #define ptyfs_abortop genfs_abortop int ptyfs_reclaim (void *); +int ptyfs_inactive (void *); #define ptyfs_lock genfs_lock #define ptyfs_unlock genfs_unlock #define ptyfs_bmap genfs_badop @@ -192,7 +193,7 @@ const struct vnodeopv_entry_desc ptyfs_v { &vop_readdir_desc, ptyfs_readdir }, /* readdir */ { &vop_readlink_desc, ptyfs_readlink }, /* readlink */ { &vop_abortop_desc, ptyfs_abortop }, /* abortop */ - { &vop_inactive_desc, spec_inactive }, /* inactive */ + { &vop_inactive_desc, ptyfs_inactive }, /* inactive */ { &vop_reclaim_desc, ptyfs_reclaim }, /* reclaim */ { &vop_lock_desc, ptyfs_lock }, /* lock */ { &vop_unlock_desc, ptyfs_unlock }, /* unlock */ @@ -225,6 +226,28 @@ ptyfs_reclaim(void *v) return ptyfs_freevp(ap->a_vp); } +int +ptyfs_inactive(void *v) +{ + struct vop_inactive_args /* { + struct vnode *a_vp; + bool *a_recycle; + } */ *ap = v; + struct vnode *vp = ap->a_vp; + struct ptyfsnode *ptyfs = VTOPTYFS(vp); + + switch (ptyfs->ptyfs_type) { + case PTYFSpts: + case PTYFSptc: + /* Emulate file deletion for call reclaim(). */ + *ap->a_recycle = true; + break; + default: + break; + } + return spec_inactive(v); +} + /* * Return POSIX pathconf information applicable to special devices. */ Index: kern/tty_bsdpty.c =================================================================== RCS file: /cvsil/nbcur/src/sys/kern/tty_bsdpty.c,v retrieving revision 1.5 diff -u -p -r1.5 tty_bsdpty.c --- kern/tty_bsdpty.c 28 Mar 2014 10:53:58 -0000 1.5 +++ kern/tty_bsdpty.c 4 Apr 2014 10:37:58 -0000 @@ -74,12 +74,13 @@ static int pty_makename(struct mount *, static int pty_allocvp(struct mount *, struct lwp *, struct vnode **, dev_t, char); static void pty_getvattr(struct mount *, struct lwp *, struct vattr *); +static int pty__getmp(struct lwp *, struct mount **); struct ptm_pty ptm_bsdpty = { pty_allocvp, pty_makename, pty_getvattr, - NULL + pty__getmp, }; static int @@ -152,5 +153,13 @@ pty_getvattr(struct mount *mp, struct lw vattr->va_gid = TTY_GID; vattr->va_mode = TTY_PERM; } + +static int +pty__getmp(struct lwp *l __unused, struct mount **mpp) +{ + *mpp = 0; + return 0; +} + #endif /* COMPAT_BSDPTY */ #endif /* NO_DEV_PTM */ Index: kern/tty_ptm.c =================================================================== RCS file: /cvsil/nbcur/src/sys/kern/tty_ptm.c,v retrieving revision 1.7 diff -u -p -r1.7 tty_ptm.c --- kern/tty_ptm.c 28 Mar 2014 10:53:58 -0000 1.7 +++ kern/tty_ptm.c 4 Apr 2014 10:37:58 -0000 @@ -91,31 +91,12 @@ static int pty_alloc_slave(struct lwp *, void ptmattach(int); int -ptyfs_getmp(struct lwp *l, struct mount **mpp) { - struct cwdinfo *cwdi = l->l_proc->p_cwdi; - struct mount *mp; - +pty_getmp(struct lwp *l, struct mount **mpp) +{ if (ptm == NULL) return EOPNOTSUPP; - if (ptm->arg == NULL) { /* BSDPTY */ - *mpp = NULL; - return 0; - } - - mp = ptm->arg; /* PTYFS */ - - if (cwdi->cwdi_rdir == NULL) - goto ok; - - if (vn_isunder(mp->mnt_vnodecovered, cwdi->cwdi_rdir, l)) - goto ok; - - *mpp = NULL; - return EOPNOTSUPP; -ok: - *mpp = mp; - return 0; + return (*ptm->getmp)(l, mpp); } dev_t @@ -193,6 +174,22 @@ retry: error = EOPNOTSUPP; goto bad; } + /* + * XXX Since PTYFS has now multiple instance support, if we mounted + * more than one PTYFS we must check here the ptyfs_used_tbl, to find + * out if the ptyfsnode is under the appropriate mount and skip the + * node if not, because the pty could has been released, but + * ptyfs_reclaim didn't get a chance to release the corresponding + * node other mount point yet. + * + * It's important to have only one mount point's ptyfsnode for each + * appropriate device in ptyfs_used_tbl, else we will have a security + * problem, because every entry will have access to this device. + * + * Also we will not have not efficient vnode and memory usage. + * You can test this by changing a_recycle from true to false + * in ptyfs_inactive. + */ if ((error = (*ptm->allocvp)(mp, l, &vp, *dev, 'p')) != 0) { DPRINTF(("pty_allocvp %d\n", error)); goto bad; @@ -356,7 +353,7 @@ ptmopen(dev_t dev, int flag, int mode, s switch(minor(dev)) { case 0: /* /dev/ptmx */ case 2: /* /emul/linux/dev/ptmx */ - if ((error = ptyfs_getmp(l, &mp)) != 0) + if ((error = pty_getmp(l, &mp)) != 0) return error; if ((error = pty_alloc_master(l, &fd, &ttydev, mp)) != 0) return error; @@ -404,7 +401,7 @@ ptmioctl(dev_t dev, u_long cmd, void *da error = 0; switch (cmd) { case TIOCPTMGET: - if ((error = ptyfs_getmp(l, &mp)) != 0) + if ((error = pty_getmp(l, &mp)) != 0) return error; if ((error = pty_alloc_master(l, &cfd, &newdev, mp)) != 0) Index: kern/tty_pty.c =================================================================== RCS file: /cvsil/nbcur/src/sys/kern/tty_pty.c,v retrieving revision 1.4 diff -u -p -r1.4 tty_pty.c --- kern/tty_pty.c 31 Mar 2014 06:54:23 -0000 1.4 +++ kern/tty_pty.c 4 Apr 2014 10:37:58 -0000 @@ -1075,7 +1075,7 @@ ptyioctl(dev_t dev, u_long cmd, void *da #ifndef NO_DEV_PTM /* Allow getting the name from either the master or the slave */ if (cmd == TIOCPTSNAME) { - if ((error = ptyfs_getmp(l, &mp)) != 0) + if ((error = pty_getmp(l, &mp)) != 0) return error; return pty_fill_ptmget(l, dev, -1, -1, data, mp); } @@ -1086,7 +1086,7 @@ ptyioctl(dev_t dev, u_long cmd, void *da switch (cmd) { #ifndef NO_DEV_PTM case TIOCGRANTPT: - if ((error = ptyfs_getmp(l, &mp)) != 0) + if ((error = pty_getmp(l, &mp)) != 0) return error; return pty_grant_slave(l, dev, mp); #endif Index: sys/pty.h =================================================================== RCS file: /cvsil/nbcur/src/sys/sys/pty.h,v retrieving revision 1.4 diff -u -p -r1.4 pty.h --- sys/pty.h 28 Mar 2014 10:53:58 -0000 1.4 +++ sys/pty.h 4 Apr 2014 10:37:59 -0000 @@ -41,7 +41,7 @@ int pty_grant_slave(struct lwp *, dev_t, dev_t pty_makedev(char, int); int pty_vn_open(struct vnode *, struct lwp *); struct ptm_pty *pty_sethandler(struct ptm_pty *); -int ptyfs_getmp(struct lwp *, struct mount **); +int pty_getmp(struct lwp *, struct mount **); /* * Ptm_pty is used for switch ptm{x} driver between BSDPTY, PTYFS. @@ -53,7 +53,7 @@ struct ptm_pty { char); int (*makename)(struct mount *, struct lwp *, char *, size_t, dev_t, char); void (*getvattr)(struct mount *, struct lwp *, struct vattr *); - void *arg; + int (*getmp)(struct lwp *, struct mount **); }; #ifdef COMPAT_BSDPTY