Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri,  1 Sep 2017 17:35:58 +0200
From: Christian Brauner <christian.brauner@...ntu.com>
To: musl@...ts.openwall.com
Cc: Christian Brauner <christian.brauner@...ntu.com>
Subject: [PATCH 1/1] openpty: use TIOCGPTPEER to open slave side fd

Newer kernels expose the ioctl TIOCGPTPEER [1] call to userspace which allows to
safely allocate a file descriptor for a pty slave based solely on the master
file descriptor. This allows us to avoid path-based operations and makes this
function a lot safer in the face of devpts mounts in different mount namespaces.

[1]: https://patchwork.kernel.org/patch/9760743/

Signed-off-by: Christian Brauner <christian.brauner@...ntu.com>
---
 src/misc/openpty.c | 34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/src/misc/openpty.c b/src/misc/openpty.c
index c1074060..9eab7a37 100644
--- a/src/misc/openpty.c
+++ b/src/misc/openpty.c
@@ -3,13 +3,14 @@
 #include <unistd.h>
 #include <pty.h>
 #include <stdio.h>
+#include <string.h>
 #include <pthread.h>
 
 /* Nonstandard, but vastly superior to the standard functions */
 
 int openpty(int *pm, int *ps, char *name, const struct termios *tio, const struct winsize *ws)
 {
-	int m, s, n=0, cs;
+	int m, s = -1, cs;
 	char buf[20];
 
 	m = open("/dev/ptmx", O_RDWR|O_NOCTTY);
@@ -17,13 +18,38 @@ int openpty(int *pm, int *ps, char *name, const struct termios *tio, const struc
 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
 
+	if (!name) name = buf;
+
+#ifdef TIOCGPTPEER
+	int ret;
+
+	/* Try to allocate slave fd solely based on the master fd in case the
+	 * kernel supports it.
+	 */
+	s = ioctl(m, TIOCGPTPEER, O_RDWR|O_NOCTTY);
+	if (s < 0)
+		goto fail;
+
+	/* Check the contents of the symlink in case devpts has been mounted in
+	 * a non-standard location.
+	 */
+	ret = ttyname_r(s, name, sizeof buf);
+	if (ret)
+		goto fail;
+
+	if (strncmp(name, "/dev/pts/", 9))
+		goto fail;
+#else
+	int n = 0;
+
 	if (ioctl(m, TIOCSPTLCK, &n) || ioctl (m, TIOCGPTN, &n))
 		goto fail;
 
-	if (!name) name = buf;
 	snprintf(name, sizeof buf, "/dev/pts/%d", n);
-	if ((s = open(name, O_RDWR|O_NOCTTY)) < 0)
+	s = open(name, O_RDWR|O_NOCTTY);
+	if (s < 0)
 		goto fail;
+#endif
 
 	if (tio) tcsetattr(s, TCSANOW, tio);
 	if (ws) ioctl(s, TIOCSWINSZ, ws);
@@ -35,6 +61,8 @@ int openpty(int *pm, int *ps, char *name, const struct termios *tio, const struc
 	return 0;
 fail:
 	close(m);
+	if (s >= 0)
+		close(s);
 	pthread_setcancelstate(cs, 0);
 	return -1;
 }
-- 
2.14.1

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.