diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-04-20 17:48:31 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-04-20 17:48:31 +0000 |
commit | d6ebd360288d294ae750a4db56ce1d439a9dcd08 (patch) | |
tree | a55b6a5876ddf7a6f9a7cf25f972be4fdb1c938a | |
parent | 202ebe010de214b98ca6dd7a8af50db3f27998e1 (diff) |
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
-rw-r--r-- | lib/libutil/openpty.3 | 53 | ||||
-rw-r--r-- | lib/libutil/pty.c | 54 | ||||
-rw-r--r-- | lib/libutil/shlib_version | 2 | ||||
-rw-r--r-- | lib/libutil/util.h | 6 |
4 files changed, 96 insertions, 19 deletions
diff --git a/lib/libutil/openpty.3 b/lib/libutil/openpty.3 index a49e533a82f..3d89cbc55d3 100644 --- a/lib/libutil/openpty.3 +++ b/lib/libutil/openpty.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: openpty.3,v 1.17 2015/08/28 19:54:06 kettenis Exp $ +.\" $OpenBSD: openpty.3,v 1.18 2017/04/20 17:48:30 nicm Exp $ .\" Copyright (c) 1995 .\" The Regents of the University of California. All rights reserved. .\" @@ -30,7 +30,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd $Mdocdate: August 28 2015 $ +.Dd $Mdocdate: April 20 2017 $ .Dt OPENPTY 3 .Os .Sh NAME @@ -42,11 +42,17 @@ .In termios.h .In util.h .Ft int +.Fn getptmfd "void" +.Ft int .Fn openpty "int *amaster" "int *aslave" "char *name" "struct termios *termp" "struct winsize *winp" .Ft int +.Fn fdopenpty "int ptmfd" "int *amaster" "int *aslave" "char *name" "struct termios *termp" "struct winsize *winp" +.Ft int .Fn login_tty "int fd" .Ft pid_t .Fn forkpty "int *amaster" "char *name" "struct termios *termp" "struct winsize *winp" +.Ft pid_t +.Fn fdforkpty "int ptmfd" "int *amaster" "char *name" "struct termios *termp" "struct winsize *winp" .Sh DESCRIPTION The .Fn openpty , @@ -90,6 +96,22 @@ uses of that device are revoked (see for details). .Pp The +.Fn fdopenpty +and +.Fn fdforkpty +functions work like +.Fn openpty +and +.Fn forkpty +but expect a +.Pa /dev/ptm +file descriptor +.Fa ptmfd +obtained from the +.Fn getptmfd +function. +.Pp +The .Fn login_tty function prepares for a login on the tty .Fa fd @@ -151,25 +173,42 @@ slave pseudo terminals pseudo terminal management device .El .Sh ERRORS +.Fn getptmfd +may fail and set +.Va errno +for any of the errors specified for the routine +.Xr open 2 . +.Pp .Fn openpty +and +.Fn fdopenpty will fail if: .Bl -tag -width Er .It Bq Er ENOENT There are no available ttys. .El .Pp -.Fn login_tty +.Fn fdopenpty +and +.Fn fdforkpty will fail if -.Fn ioctl -fails to set -.Fa fd -to the controlling terminal of the current process. +.Fn getptmfd +fails. .Fn forkpty +and +.Fn fdforkpty will fail if either .Fn openpty or .Fn fork fails. +.Pp +.Fn login_tty +will fail if +.Fn ioctl +fails to set +.Fa fd +to the controlling terminal of the current process. .Sh SEE ALSO .Xr fork 2 , .Xr revoke 2 , 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 @@ -44,24 +44,41 @@ #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) { @@ -82,10 +99,27 @@ 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: diff --git a/lib/libutil/shlib_version b/lib/libutil/shlib_version index eb2c603aec0..7b5f7ac578e 100644 --- a/lib/libutil/shlib_version +++ b/lib/libutil/shlib_version @@ -1,2 +1,2 @@ major=12 -minor=1 +minor=2 diff --git a/lib/libutil/util.h b/lib/libutil/util.h index 469e003d587..15bf32db3a7 100644 --- a/lib/libutil/util.h +++ b/lib/libutil/util.h @@ -1,4 +1,4 @@ -/* $OpenBSD: util.h,v 1.34 2013/06/03 21:07:02 tedu Exp $ */ +/* $OpenBSD: util.h,v 1.35 2017/04/20 17:48:30 nicm Exp $ */ /* $NetBSD: util.h,v 1.2 1996/05/16 07:00:22 thorpej Exp $ */ /*- @@ -98,9 +98,13 @@ void pw_prompt(void); void pw_copy(int, int, const struct passwd *, const struct passwd *); int pw_scan(char *, struct passwd *, int *); void pw_error(const char *, int, int); +int getptmfd(void); int openpty(int *, int *, char *, struct termios *, struct winsize *); +int fdopenpty(int, int *, int *, char *, struct termios *, + struct winsize *); int opendisk(const char *, int, char *, size_t, int); pid_t forkpty(int *, char *, struct termios *, struct winsize *); +pid_t fdforkpty(int, int *, char *, struct termios *, struct winsize *); int getmaxpartitions(void); int getrawpartition(void); void login_fbtab(const char *, uid_t, gid_t); |