summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-02-10 01:31:22 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-02-10 01:31:22 +0000
commit85848b86166719fe7164148608daa490bf9bfcdb (patch)
tree669ff49bb8253462e9b1fb75ac23bdbc1e344261 /lib
parent92344befec63515228572bc04de856dfae3b3c00 (diff)
Add the ptm device to pty(4). By opening /dev/ptm and using the PTMGET
ioctl(2), an unprivileged process may allocate a pty and have its owner and mode set appropriately. This means that programs such as xterm and screen no longer need to be setuid. Programs using the openpty() function require zero changes and will "just work". Designed by beck@ and deraadt@; changes by beck@ with cleanup (and a rewrite of the vnode bits) by art@ and tweaks/bugfixes by me. Tested by many.
Diffstat (limited to 'lib')
-rw-r--r--lib/libutil/openpty.325
-rw-r--r--lib/libutil/pty.c39
2 files changed, 60 insertions, 4 deletions
diff --git a/lib/libutil/openpty.3 b/lib/libutil/openpty.3
index 4794f7846c0..986912b6e05 100644
--- a/lib/libutil/openpty.3
+++ b/lib/libutil/openpty.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: openpty.3,v 1.11 2003/06/02 20:18:42 millert Exp $
+.\" $OpenBSD: openpty.3,v 1.12 2004/02/10 01:31:20 millert Exp $
.\" Copyright (c) 1995
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -78,6 +78,24 @@ is non-null, the window size of the slave will be set to the values in
.Fa winp .
.Pp
The
+.Fn openpty
+function works in the following way:
+first it attempts to allocate the pseudo-tty through the
+.Pa /dev/ptm
+device (see
+.Xr pty 4
+for details) and if that fails it searches for a free psuedo-tty by iterating
+through all existing pseudo-tty devices in
+.Pa /dev .
+When a free pseudo-tty is found, its ownership is changed to
+the UID of the caller, permissions are set to correct values,
+and all earlier uses of that device are revoked (see
+.Xr revoke 2
+for details).
+The first method can work for any user, the second method requires
+super-user privileges in most cases.
+.Pp
+The
.Fn login_tty
function prepares for a login on the tty
.Fa fd
@@ -132,6 +150,7 @@ returns the process ID of the child process.
.Sh FILES
.Bl -tag -width /dev/[pt]ty[pqrstuvwxyzPQRST][0123456789abcdef] -compact
.It Pa /dev/[pt]ty[pqrstuvwxyzPQRST][0123456789abcdef]
+.It Pa /dev/ptm
.El
.Sh ERRORS
.Fn openpty
@@ -154,4 +173,6 @@ or
.Fn fork
fails.
.Sh SEE ALSO
-.Xr fork 2
+.Xr fork 2 ,
+.Xr revoke 2 ,
+.Xr pty 4
diff --git a/lib/libutil/pty.c b/lib/libutil/pty.c
index 743daf70491..a8fa7671537 100644
--- a/lib/libutil/pty.c
+++ b/lib/libutil/pty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pty.c,v 1.10 2003/06/02 20:18:42 millert Exp $ */
+/* $OpenBSD: pty.c,v 1.11 2004/02/10 01:31:20 millert Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,7 +30,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/* from: static char sccsid[] = "@(#)pty.c 8.1 (Berkeley) 6/4/93"; */
-static const char rcsid[] = "$Id: pty.c,v 1.10 2003/06/02 20:18:42 millert Exp $";
+static const char rcsid[] = "$Id: pty.c,v 1.11 2004/02/10 01:31:20 millert Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
@@ -44,6 +44,7 @@ static const char rcsid[] = "$Id: pty.c,v 1.10 2003/06/02 20:18:42 millert Exp $
#include <stdio.h>
#include <string.h>
#include <grp.h>
+#include <sys/tty.h>
#include "util.h"
@@ -60,7 +61,41 @@ openpty(amaster, aslave, name, termp, winp)
register const char *cp1, *cp2;
register int master, slave, ttygid;
struct group *gr;
+ struct ptmget ptm;
+ int fd;
+ /* Try to use /dev/ptm and the PTMGET ioctl to get a properly set up
+ * and owned pty/tty pair. If this fails, (because we might not have
+ * the ptm device, etc.) fall back to using the traditional method
+ * of walking through the pty entries in /dev for the moment, until
+ * there is less chance of people being seriously boned by running
+ * kernels without /dev/ptm in them.
+ */
+
+ fd = open(PATH_PTMDEV, O_RDWR, 0);
+ if (fd == -1)
+ goto walkit;
+ if ((ioctl(fd, PTMGET, &ptm) == -1)) {
+ close(fd);
+ goto walkit;
+ }
+ close(fd);
+ master = ptm.cfd;
+ slave = ptm.sfd;
+ if (name) {
+ /*
+ * Manual page says "at least 16 characters".
+ */
+ strlcpy(name, ptm.sn, 16);
+ }
+ *amaster = master;
+ *aslave = slave;
+ if (termp)
+ (void) tcsetattr(slave, TCSAFLUSH, termp);
+ if (winp)
+ (void) ioctl(slave, TIOCSWINSZ, (char *)winp);
+ return (0);
+ walkit:
if ((gr = getgrnam("tty")) != NULL)
ttygid = gr->gr_gid;
else