From c2a62bf3db04acca153f21fa3dd7148f75564929 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 20 Apr 2017 17:48:30 +0000 Subject: Add getptmfd(), fdopenpty(), fdforkpty() functions. These allow programs to separate the open(/dev/ptm) from the ioctl(PTMGET) for privilege separation or pledge(). Based on a diff from reyk@. ok deraadt millert --- lib/libutil/pty.c | 54 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 10 deletions(-) (limited to 'lib/libutil/pty.c') diff --git a/lib/libutil/pty.c b/lib/libutil/pty.c index 2a19de81ca5..c796acb5041 100644 --- a/lib/libutil/pty.c +++ b/lib/libutil/pty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pty.c,v 1.20 2016/08/30 14:44:45 guenther Exp $ */ +/* $OpenBSD: pty.c,v 1.21 2017/04/20 17:48:30 nicm Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -43,25 +43,42 @@ #include "util.h" +int +getptmfd(void) +{ + return (open(PATH_PTMDEV, O_RDWR|O_CLOEXEC)); +} + int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) { - int master, slave, fd; + int ptmfd; + + if ((ptmfd = getptmfd()) == -1) + return (-1); + if (fdopenpty(ptmfd, amaster, aslave, name, termp, winp) == -1) { + close(ptmfd); + return (-1); + } + close(ptmfd); + return (0); +} + +int +fdopenpty(int ptmfd, int *amaster, int *aslave, char *name, + struct termios *termp, struct winsize *winp) +{ + int master, slave; struct ptmget ptm; /* * Use /dev/ptm and the PTMGET ioctl to get a properly set up and * owned pty/tty pair. */ - fd = open(PATH_PTMDEV, O_RDWR|O_CLOEXEC); - if (fd == -1) + if (ioctl(ptmfd, PTMGET, &ptm) == -1) return (-1); - if ((ioctl(fd, PTMGET, &ptm) == -1)) { - close(fd); - return (-1); - } - close(fd); + master = ptm.cfd; slave = ptm.sfd; if (name) { @@ -81,11 +98,28 @@ openpty(int *amaster, int *aslave, char *name, struct termios *termp, pid_t forkpty(int *amaster, char *name, struct termios *termp, struct winsize *winp) +{ + int ptmfd; + pid_t pid; + + if ((ptmfd = getptmfd()) == -1) + return (-1); + if ((pid = fdforkpty(ptmfd, amaster, name, termp, winp)) == -1) { + close(ptmfd); + return (-1); + } + close(ptmfd); + return (pid); +} + +pid_t +fdforkpty(int ptmfd, int *amaster, char *name, struct termios *termp, + struct winsize *winp) { int master, slave; pid_t pid; - if (openpty(&master, &slave, name, termp, winp) == -1) + if (fdopenpty(ptmfd, &master, &slave, name, termp, winp) == -1) return (-1); switch (pid = fork()) { case -1: -- cgit v1.2.3-59-g8ed1b