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>