Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 2 Jun 2008 09:31:52 +0200
From:      Ed Schouten <ed@80386.nl>
To:        freebsd-emulation@FreeBSD.org
Cc:        philip@FreeBSD.org
Subject:   Linux major/minor conversion not entirely correct
Message-ID:  <20080602073152.GO64397@hoeg.nl>

next in thread | raw e-mail | index | archive | help

--gS/sOEqITpbrYRmu
Content-Type: multipart/mixed; boundary="VjpKO6h983+pAmpQ"
Content-Disposition: inline


--VjpKO6h983+pAmpQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hello everyone,

The last couple of months I've been working on redesigning FreeBSD's TTY
layer. This is all going quite good. Too good, actually.

Last week I've been toying around with getting sshd working inside a
Linux jail, which seems to work quite nicely right now. I've made some
changes to our Linux compat layer that could already get (partially)
merged back to SVN.

The Linux compat layer generates fake major/minor numbers for certain
devices, because Linux still depends on that information a lot (yuck).
I've discovered that our Linux compat layer returns the same major/minor
pair for all nodes in /dev/pts, but doesn't do this consistently either.
We'd better push the conversion down into linux_driver_get_major_minor(),
to make sure the numbers always get converted. We should also make sure
we hand out unique numbers.

The patch also contains a change I made to support the new DTYPE_PTS
(pseudo-terminal master device). This part of the diff should be
ignored. I've just added it for completeness.

Does anyone mind if I commit this patch soonish?

--=20
 Ed Schouten <ed@80386.nl>
 WWW: http://80386.nl/

--VjpKO6h983+pAmpQ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="linux-tty.diff"
Content-Transfer-Encoding: quoted-printable

--- sys/compat/linux/linux_stats.c
+++ sys/compat/linux/linux_stats.c
@@ -44,6 +44,7 @@
 #include <sys/stat.h>
 #include <sys/syscallsubr.h>
 #include <sys/systm.h>
+#include <sys/tty.h>
 #include <sys/vnode.h>
 #include <sys/conf.h>
 #include <sys/fcntl.h>
@@ -109,8 +110,17 @@
 	if (fp->f_vnode !=3D NULL &&
 	    fp->f_vnode->v_un.vu_cdev !=3D NULL &&
 	    linux_driver_get_major_minor(fp->f_vnode->v_un.vu_cdev->si_name,
-					 &major, &minor) =3D=3D 0)
+					 &major, &minor) =3D=3D 0) {
 		buf->st_rdev =3D (major << 8 | minor);
+	} else if (fp->f_type =3D=3D DTYPE_PTS) {
+		struct tty *tp =3D fp->f_data;
+
+		/* Convert the numbers for the slave device */
+		if (linux_driver_get_major_minor(tp->t_dev->si_name,
+					 &major, &minor) =3D=3D 0) {
+			buf->st_rdev =3D (major << 8 | minor);
+		}
+	}
 	fdrop(fp, td);
 }
=20
@@ -178,19 +188,8 @@
 #endif
=20
 	error =3D kern_stat(td, path, UIO_SYSSPACE, &buf);
-	if (!error) {
-		if (strlen(path) > strlen("/dev/pts/") &&
-		    !strncmp(path, "/dev/pts/", strlen("/dev/pts/")) &&
-		    path[9] >=3D '0' && path[9] <=3D '9') {
-			/*
-			 * Linux checks major and minors of the slave device
-			 * to make sure it's a pty device, so let's make him
-			 * believe it is.
-			 */
-			buf.st_rdev =3D (136 << 8);
-		} else
-			translate_path_major_minor(td, path, &buf);
-	}
+	if (!error)
+		translate_path_major_minor(td, path, &buf);
 	LFREEPATH(path);
 	if (error)
 		return (error);
@@ -528,19 +527,8 @@
 #endif
=20
 	error =3D kern_stat(td, filename, UIO_SYSSPACE, &buf);
-	if (!error) {
-		if (strlen(filename) > strlen("/dev/pts/") &&
-		    !strncmp(filename, "/dev/pts/", strlen("/dev/pts/")) &&
-		    filename[9] >=3D '0' && filename[9] <=3D '9') {
-			/*
-			 * Linux checks major and minors of the slave device
-			 * to make sure it's a pty deivce, so let's make him
-			 * believe it is.
-			 */
-			buf.st_rdev =3D (136 << 8);
-		} else
-			translate_path_major_minor(td, filename, &buf);
-	}
+	if (!error)
+		translate_path_major_minor(td, filename, &buf);
 	LFREEPATH(filename);
 	if (error)
 		return (error);
--- sys/compat/linux/linux_util.c
+++ sys/compat/linux/linux_util.c
@@ -130,6 +130,22 @@
=20
 	if (node =3D=3D NULL || major =3D=3D NULL || minor =3D=3D NULL)
 		return 1;
+
+	if (strlen(node) > strlen("pts/") &&
+	    strncmp(node, "pts/", strlen("pts/")) =3D=3D 0) {
+		unsigned long devno;
+
+		/*
+		 * Linux checks major and minors of the slave device
+		 * to make sure it's a pty device, so let's make him
+		 * believe it is.
+		 */
+		devno =3D strtoul(node + strlen("pts/"), NULL, 10);
+		*major =3D 136 + (devno / 256);
+		*minor =3D devno % 256;
+		return 0;
+	}
+
 	TAILQ_FOREACH(de, &devices, list) {
 		if (strcmp(node, de->entry.bsd_device_name) =3D=3D 0) {
 			*major =3D de->entry.linux_major;

--VjpKO6h983+pAmpQ--

--gS/sOEqITpbrYRmu
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (FreeBSD)

iEYEARECAAYFAkhDoegACgkQ52SDGA2eCwVZYgCfXv5mDo114WQ15Kz3ShZKj5SW
TIAAniMIkaeRX65zfmmhGWTVKYiVw/UO
=c1nt
-----END PGP SIGNATURE-----

--gS/sOEqITpbrYRmu--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080602073152.GO64397>