Recent major number changes on ptys break grantpt() and friends in lib/libc/stdlib/grantpt.c

From: Richard Todd <rmtodd_at_ichotolot.servalan.com>
Date: Wed, 02 Mar 2005 19:39:09 -0600
Last night I upgraded my system to the then-current -CURRENT (upgrading from
-CURRENT as of a couple weeks ago), installing new kernel and world.  Soon
after, I discovered that a Perl script of mine I use to pry statistics out of
my Netgear router (telneting to the router under a pseudo-tty with p5-Expect
and p5-IO-Tty) was giving me the following error messages:

IO::Tty::pty_allocate(nonfatal): grantpt(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, <STDIN> line 1.
IO::Tty::pty_allocate(nonfatal): unlockpt(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, <STDIN> line 1.
IO::Tty::open_slave(nonfatal): ptsname(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, <STDIN> line 1.
pty_allocate(nonfatal): openpty(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, <STDIN> line 1.
IO::Tty::pty_allocate(nonfatal): grantpt(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, <STDIN> line 1.
IO::Tty::pty_allocate(nonfatal): unlockpt(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, <STDIN> line 1.

Further investigation with simplifed test cases revealed that yes indeed, calls
by the p5-IO-Tty module to the grantpt()/unlockpt()/ptsname() were failing.
Looking at the code for these functions, it's easy to see why.  These functions
all check to see if the fd they're passed is a valid pty by fstat()ing the fd,
looking at the device number, and checking it is a pseudoterminal device 
node with the ISPTM macro as follows:

#define PTM_MAJOR	6	/* pseudo tty master major */
#define PTS_MAJOR	5	/* pseudo tty slave major */
#define PTM_PREFIX	"pty"	/* pseudo tty master naming convention */
#define PTS_PREFIX	"tty"	/* pseudo tty slave naming convention */

/*
 * The following are range values for pseudo TTY devices.  Pseudo TTYs have a
 * name of /dev/[pt]ty[p-sP-S][0-9a-v], yielding 256 combinations per major.
 */
#define PT_MAX		256
#define	PT_DEV1		"pqrsPQRS"
#define PT_DEV2		"0123456789abcdefghijklmnopqrstuv"

/*
 * grantpt(3) support utility.
 */
#define _PATH_PTCHOWN	"/usr/libexec/pt_chown"

/*
 * ISPTM(x) returns 0 for struct stat x if x is not a pty master.
 * The bounds checking may be unnecessary but it does eliminate doubt.
 */
#define ISPTM(x)	(S_ISCHR((x).st_mode) && 			\
			 major((x).st_rdev) == PTM_MAJOR &&		\
			 minor((x).st_rdev) >= 0 &&			\
			 minor((x).st_rdev) < PT_MAX)


Yep.  The pty master/slave major numbers are hardwired into grantpt.c, and
now that pty major device numbers are dynamically allocated, the actual
device numbers on a running system don't match what's in the above #define:
crw-rw-rw-  1 root    wheel  216,   0 Mar  2 01:50 /dev/ptyp0
crw--w----  1 rmtodd  tty    215,   0 Mar  2 01:51 /dev/ttyp0

I managed to work around the immediate problem and stop my script from 
complaining by bludgeoning the p5-IO-Tty Makefile.PL with a blunt instrument
to make it think this system didn't support grantpt() etc. (causing the module
to fall back to other methods of dealing with ptys).  The proper fix for
grantpt.c is less clear, though.  Changing it to figure the proper pty 
major number by stating a known pty node (say, /dev/ptyp0) would work, but from
what I understand that's going to break when phk commits his forthcoming
patch which will make the whole concept of major numbers go away. Any ideas?
Received on Thu Mar 03 2005 - 01:16:10 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:29 UTC