standards/58676: grantpt(3) alters storage used by ptsname(3)

Ryan Younce ryany at pobox.com
Wed Oct 29 01:10:20 PST 2003


>Number:         58676
>Category:       standards
>Synopsis:       grantpt(3) alters storage used by ptsname(3)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-standards
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Oct 29 01:10:18 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     Ryan Younce
>Release:        FreeBSD 5.1-RELEASE
>Organization:
>Environment:
FreeBSD kara 5.1-RELEASE FreeBSD 5.1-RELEASE #3: Mon Oct  6 22:31:51 GMT 2003     root at kara:/usr/src/sys/i386/compile/KARA  i386

>Description:

	The ptsname(3) function is allowed by POSIX to hold the returned
	slave PTY name in static storage that may be overwritten by
	subsequent calls to ptsname() (which it does).

	In the current implementation, however, grantpt(3) calls ptsname()
	to obtain the name of the slave device.  Hence, a call to grantpt()
	will alter the object returned by a previous ptsname() if grantpt()
	is called with a different descriptor than the one used in the
	last call to ptsname().  This is incorrect; POSIX makes no mention
	that the returned object of ptsname() may be modified by subsequent
	calls to grantpt().

>How-To-Repeat:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
	char *slave;
	int fd1, fd2;

	fd1 = posix_openpt(0);
	fd2 = posix_openpt(0);

	slave = ptsname(fd1);
	printf("fd1 slave name (before grantpt(fd2)):  '%s'\n", slave);

	/* call grantpt(3) on fd2 */
	grantpt(fd2);

	/* print out slave again, which should not have changed */
	printf("fd1 slave name (after grantpt(fd2)):   '%s'\n", slave);

	return 0;
}

>Fix:

Moved the code that obtains the name of the PTY slave from the master's
descriptor into a separate (internal) function, derive_slave(), that is
called by both grantpt() and ptsname().

(As a side, the manual page should be updated to reflect that ptsname()
holds its return in static storage that may be overwritten by subsequent
calls to ptsname().)

The following are patches to both files.

Index: grantpt.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdlib/grantpt.c,v
retrieving revision 1.2
diff -u -r1.2 grantpt.c
--- grantpt.c	4 Jan 2003 08:10:55 -0000	1.2
+++ grantpt.c	27 Oct 2003 06:21:45 -0000
@@ -81,6 +81,27 @@
 			 minor((x).st_rdev) >= 0 &&			\
 			 minor((x).st_rdev) < PT_MAX)
 
+static char *
+derive_slave(int fildes, char *slave)
+{
+	struct stat sbuf;
+	char *retname = NULL;
+
+	if (_fstat(fildes, &sbuf) == 0) {
+		/* Ensure fildes is a master PTY device */
+		if (!ISPTM(sbuf))
+			errno = EINVAL;
+		else {
+			/* Translate fildes into path to counterpart slave. */
+			(void)sprintf(slave, _PATH_DEV PTS_PREFIX "%c%c",
+				      PT_DEV1[minor(sbuf.st_rdev) / 32],
+				      PT_DEV2[minor(sbuf.st_rdev) % 32]);
+			retname = slave;
+		}
+	}
+	return retname;
+}
+
 /*
  * grantpt():  grant ownership of a slave pseudo-terminal device to the
  *             current user.
@@ -92,14 +113,14 @@
 	int retval, serrno, status;
 	pid_t pid, spid;
 	gid_t gid;
-	char *slave;
+	char slave[] = _PATH_DEV PTS_PREFIX "XY";
 	sigset_t oblock, nblock;
 	struct group *grp;
 
 	retval = -1;
 	serrno = errno;
 
-	if ((slave = ptsname(fildes)) != NULL) {
+	if (derive_slave(fildes, slave) != NULL) {
 		/*
 		 * Block SIGCHLD.
 		 */
@@ -217,23 +238,7 @@
 ptsname(int fildes)
 {
 	static char slave[] = _PATH_DEV PTS_PREFIX "XY";
-	char *retval;
-	struct stat sbuf;
-
-	retval = NULL;
-
-	if (_fstat(fildes, &sbuf) == 0) {
-		if (!ISPTM(sbuf))
-			errno = EINVAL;
-		else {
-			(void)sprintf(slave, _PATH_DEV PTS_PREFIX "%c%c",
-				      PT_DEV1[minor(sbuf.st_rdev) / 32],
-				      PT_DEV2[minor(sbuf.st_rdev) % 32]);
-			retval = slave;
-		}
-	}
-
-	return (retval);
+	return derive_slave(fildes, slave);
 }
 
 /*
Index: grantpt.3
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdlib/grantpt.3,v
retrieving revision 1.3
diff -u -r1.3 grantpt.3
--- grantpt.3	14 Sep 2003 13:41:57 -0000	1.3
+++ grantpt.3	27 Oct 2003 06:21:45 -0000
@@ -211,6 +211,14 @@
 .Fn posix_openpt
 functions appeared in
 .Fx 5.0 .
+.Sh BUGS
+The function
+.Fn ptsname
+leaves its result in an internal static object and returns
+a pointer to that object.
+Subsequent calls to
+.Fn ptsname
+will modify the same object.
 .Sh NOTES
 The purpose of the
 .Fn unlockpt

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-standards mailing list