On 01.04.2014 23:38, Ilya Zykov wrote:
> 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.
> 

XXX comments change.

 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          |   30 ++++++++++++++++++++++--------
 sys/pty.h               |   21 ---------------------
 7 files changed, 98 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	2 Apr 2014 06:28:40 -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	2 Apr 2014 06:28:40 -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	2 Apr 2014 06:28:40 -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	2 Apr 2014 06:28:40 -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	2 Apr 2014 06:28:40 -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	2 Apr 2014 06:28:40 -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,18 @@ 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 and memory use.
+	 * You can try this if you change true on false in ptyfs_inactive.
+	 */
 	if ((error = (*ptm->allocvp)(mp, l, &vp, *dev, 'p')) != 0) {
 		DPRINTF(("pty_allocvp %d\n", error));
 		goto bad;
@@ -340,6 +353,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	2 Apr 2014 06:28:42 -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;

Reply via email to