Subject: Re: unexpected behaviour of grantpt(3)
To: None <tech-kern@netbsd.org>
From: Christos Zoulas <christos@astron.com>
List: tech-kern
Date: 02/18/2006 20:15:27
In article <20060218145725.GA6466@silence.homedns.org>,
Klaus Heinz  <k.heinz.feb.sechs@onlinehome.de> wrote:
>Hi,
>
>today I was trying to understand why devel/p5-IO-Tty does not work correctly
>on my new NetBSD 3.0 system.
>
>The supplied test suite uses openpty(3) to get FDs for master and slave tty,
>then applies grantpt(), unlockpt() and ptsname() to the master FD.
>
>Using the master FD works but Perl is not able to access the slave FD,
>the error I see is EBADF. Reading through the man pages for those functions
>and comparing them to their counterpart on Linux (where this all works
>with openpt()) pointed me to the NOTES section of our grantpt(3):
>
>  NOTES
>     Setting the group to tty and revoking accesses by other file descriptors
>     are NetBSD extensions.  Calling grantpt() is equivalent to:
>		ioctl(fildes, TIOCGRANTPT, 0);
>
>If I understand this correctly, doing grantpt() after openpty()
>invalidates the FD for the slave we received from openpty().
>
>Consequently, acquiring a new slave FD (after grantpt()) works perfectly
>for this Perl module.
>
>Can anyone (Christos?) explain why NetBSD's grantpt() (or rather
>TIOCGRANTPT) implements this extension?
>Are there any other systems which act the same?

OpenBSD does. Anyway, not revoking all fd's accociated with the slave pty
is a huge security hole. grantpt() is supposed to change the ownership and
group of the pty so that only the user can access it. Then you are supposed
to use ptsname() to get the name of the slave and open() it.

>I could not find any previous discussion about this.
>
>After my research, I think the IO-Tty authors could not possibly have
>expected such behaviour in their code.

Well, 

The combination of using openpty() with grantpt(), unlockpt(), etc.
is non-portable. You are supposed to be using posix_openpt() instead.
http://www.opengroup.org/onlinepubs/000095399/functions/posix_openpt.html

openpty() uses /dev/ptm which already does the grantpt() on the slave.
So the slave given, has already been chowned/chgrped (granted) and there
is no need to do the grantpt() again.

posix_openpt() uses /dev/ptmx which only returns the master.

The IO-Tty authors are supposed to:

Go the POSIX pty way and do:

	1. use posix_openpt(), grantpt(), unlockpt(), open(ptsname())

or go the BSD4.4 way:

	2. use openpty()

Not doing combinations of both :-)

christos