Hello! This patch introduces subject. Some code refactoring, because we have more stronger ptm - ptyfs binding. BSD pty compatibility improvement.
Main explanation you can see in comments inside. Also I am not sure about, how, correctly release unused vnode and return it for system and call reclaim. Before anybody call for it getnewvnode. fs/ptyfs/ptyfs.h | 21 +++++++++++++++++++++ fs/ptyfs/ptyfs_subr.c | 2 -- fs/ptyfs/ptyfs_vfsops.c | 37 +++++++++++++++++++++++++++++-------- fs/ptyfs/ptyfs_vnops.c | 26 ++++++++++++++++++++++++-- kern/tty_bsdpty.c | 4 ++-- kern/tty_ptm.c | 31 +++++++++++++++++++++++-------- sys/pty.h | 21 --------------------- 7 files changed, 99 insertions(+), 43 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 1 Apr 2014 19:00:15 -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; @@ -113,6 +115,25 @@ struct ptyfsmount { #define VFSTOPTY(mp) ((struct ptyfsmount *)(mp)->mnt_data) +LIST_HEAD(ptyfs_lhmp, ptyfsmount); + +/* + * Ptm_pty is used for switch ptm{x} driver between BSDPTY, PTYFS. + * Functions' argument (struct mount *) is used only PTYFS, + * in the case BSDPTY can be NULL, and arg must be NULL. + */ +struct ptm_pty { + int (*allocvp)(struct mount *, struct lwp *, struct vnode **, dev_t, + char); + int (*makename)(struct mount *, struct lwp *, char *, size_t, dev_t, char); + void (*getvattr)(struct mount *, struct lwp *, struct vattr *); + struct ptyfs_lhmp *arg; +}; + +dev_t pty_makedev(char, int); +int pty_vn_open(struct vnode *, struct lwp *); +struct ptm_pty *pty_sethandler(struct ptm_pty *); + #endif /* _KERNEL */ struct ptyfs_args { Index: fs/ptyfs/ptyfs_subr.c =================================================================== RCS file: /cvsil/nbcur/src/sys/fs/ptyfs/ptyfs_subr.c,v retrieving revision 1.6 diff -u -p -r1.6 ptyfs_subr.c --- fs/ptyfs/ptyfs_subr.c 28 Mar 2014 10:53:57 -0000 1.6 +++ fs/ptyfs/ptyfs_subr.c 1 Apr 2014 19:00:15 -0000 @@ -86,8 +86,6 @@ __KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c #include <sys/namei.h> #include <sys/filedesc.h> #include <sys/select.h> -#include <sys/tty.h> -#include <sys/pty.h> #include <sys/kauth.h> #include <sys/lwp.h> 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 1 Apr 2014 19:00:15 -0000 @@ -54,8 +54,6 @@ __KERNEL_RCSID(0, "$NetBSD: ptyfs_vfsops #include <sys/syslog.h> #include <sys/select.h> #include <sys/filedesc.h> -#include <sys/tty.h> -#include <sys/pty.h> #include <sys/kauth.h> #include <sys/module.h> @@ -83,12 +81,13 @@ static void ptyfs__getvattr(struct mount */ struct ptm_pty *ptyfs_save_ptm; static int ptyfs_count; +static struct ptyfs_lhmp mph; struct ptm_pty ptm_ptyfspty = { ptyfs__allocvp, ptyfs__makename, ptyfs__getvattr, - NULL + &mph }; static const char * @@ -130,6 +129,7 @@ ptyfs__makename(struct mount *mp, struct { size_t len; const char *np; + struct cwdinfo *cwdi = l->l_proc->p_cwdi; switch (ms) { case 'p': @@ -137,6 +137,15 @@ 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 (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; @@ -188,7 +197,7 @@ ptyfs__getvattr(struct mount *mp, struct void ptyfs_init(void) { - + LIST_INIT(ptm_ptyfspty.arg); malloc_type_attach(M_PTYFSMNT); malloc_type_attach(M_PTYFSTMP); ptyfs_hashinit(); @@ -218,7 +227,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,10 +283,16 @@ ptyfs_mount(struct mount *mp, const char return error; } - /* Point pty access to us */ + pmnt->pmnt_mp = mp; if (ptyfs_count == 0) { - ptm_ptyfspty.arg = mp; + LIST_INSERT_HEAD(ptm_ptyfspty.arg, pmnt, pmnt_le); + /* Point pty access to us */ ptyfs_save_ptm = pty_sethandler(&ptm_ptyfspty); + } else { + pmnt_next = LIST_FIRST(ptm_ptyfspty.arg); + 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 +311,7 @@ ptyfs_unmount(struct mount *mp, int mntf { int error; int flags = 0; + struct ptyfsmount *pmnt; if (mntflags & MNT_FORCE) flags |= FORCECLOSE; @@ -308,7 +324,12 @@ 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, ptm_ptyfspty.arg, pmnt_le) { + if (pmnt->pmnt_mp == mp) { + LIST_REMOVE(pmnt, pmnt_le); + break; + } } /* 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 1 Apr 2014 19:00:15 -0000 @@ -94,7 +94,6 @@ __KERNEL_RCSID(0, "$NetBSD: ptyfs_vnops. #include <sys/resourcevar.h> #include <sys/stat.h> #include <sys/conf.h> -#include <sys/tty.h> #include <sys/pty.h> #include <sys/kauth.h> @@ -140,6 +139,7 @@ int ptyfs_kqfilter (void *); int ptyfs_readdir (void *); #define ptyfs_readlink genfs_eopnotsupp #define ptyfs_abortop genfs_abortop +int ptyfs_inactive (void *); int ptyfs_reclaim (void *); #define ptyfs_lock genfs_lock #define ptyfs_unlock genfs_unlock @@ -192,7 +192,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 +225,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 1 Apr 2014 19:00:15 -0000 @@ -39,7 +39,6 @@ __KERNEL_RCSID(0, "$NetBSD: tty_bsdpty.c #include <sys/systm.h> #include <sys/ioctl.h> #include <sys/lwp.h> -#include <sys/tty.h> #include <sys/stat.h> #include <sys/file.h> #include <sys/uio.h> @@ -50,9 +49,10 @@ __KERNEL_RCSID(0, "$NetBSD: tty_bsdpty.c #include <sys/filedesc.h> #include <sys/conf.h> #include <sys/poll.h> -#include <sys/pty.h> #include <sys/kauth.h> +#include <fs/ptyfs/ptyfs.h> + /* * pts == /dev/tty[pqrs]? * ptc == /dev/pty[pqrs]? 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 1 Apr 2014 19:00:15 -0000 @@ -38,7 +38,6 @@ __KERNEL_RCSID(0, "$NetBSD: tty_ptm.c,v #include <sys/systm.h> #include <sys/ioctl.h> #include <sys/proc.h> -#include <sys/tty.h> #include <sys/stat.h> #include <sys/file.h> #include <sys/uio.h> @@ -53,6 +52,7 @@ __KERNEL_RCSID(0, "$NetBSD: tty_ptm.c,v #include <sys/pty.h> #include <sys/kauth.h> +#include <fs/ptyfs/ptyfs.h> #include <miscfs/specfs/specdev.h> #ifdef COMPAT_60 @@ -94,6 +94,7 @@ int ptyfs_getmp(struct lwp *l, struct mount **mpp) { struct cwdinfo *cwdi = l->l_proc->p_cwdi; struct mount *mp; + struct ptyfsmount *pmnt; if (ptm == NULL) return EOPNOTSUPP; @@ -103,14 +104,14 @@ ptyfs_getmp(struct lwp *l, struct mount 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; + LIST_FOREACH(pmnt, ptm->arg, pmnt_le) { /* PTYFS */ + 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: @@ -193,6 +194,19 @@ retry: error = EOPNOTSUPP; goto bad; } + /* + * XXX Since PTYFS has multiple instance support. If we have mounted it more than + * one time, maybe, we must check here ptyfs_used_tbl, on the subject of occupancy + * appropriate ptyfsnode and skip this dev number in this case, because, + * pty could has been released, but ptyfs_reclaim hasn't released appropriate + * ptyfsnode, from other mount point yet. + * It's important have only one mount point's ptyfsnode for appropriate device in + * ptyfs_used_tbl, else we will have security problem, because every entry + * will have access to this device. + * Also we can have not effective vnode use and memory leak in ptyfs_free_tbl, + * where we will accumulate more and more ptyfsnode for the same device. + * See ptyfs_free_get. + */ if ((error = (*ptm->allocvp)(mp, l, &vp, *dev, 'p')) != 0) { DPRINTF(("pty_allocvp %d\n", error)); goto bad; @@ -340,6 +354,7 @@ ptmattach(int n) if ((ptc_major = cdevsw_lookup_major(&ptc_cdevsw)) == -1) panic("ptmattach: Can't find pty master in cdevsw"); #ifdef COMPAT_BSDPTY + extern struct ptm_pty ptm_bsdpty; ptm = &ptm_bsdpty; #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 1 Apr 2014 19:00:15 -0000 @@ -38,28 +38,7 @@ int pty_check(int); void ptmattach(int); int pty_fill_ptmget(struct lwp *, dev_t, int, int, void *, struct mount *); int pty_grant_slave(struct lwp *, dev_t, struct mount *); -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 **); - -/* - * Ptm_pty is used for switch ptm{x} driver between BSDPTY, PTYFS. - * Functions' argument (struct mount *) is used only PTYFS, - * in the case BSDPTY can be NULL, and arg must be NULL. - */ -struct ptm_pty { - int (*allocvp)(struct mount *, struct lwp *, struct vnode **, dev_t, - char); - int (*makename)(struct mount *, struct lwp *, char *, size_t, dev_t, char); - void (*getvattr)(struct mount *, struct lwp *, struct vattr *); - void *arg; -}; - -#ifdef COMPAT_BSDPTY -extern struct ptm_pty ptm_bsdpty; -#endif - #endif /* NO_DEV_PTM */ extern int npty;