summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2017-04-20 17:48:31 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2017-04-20 17:48:31 +0000
commitd6ebd360288d294ae750a4db56ce1d439a9dcd08 (patch)
treea55b6a5876ddf7a6f9a7cf25f972be4fdb1c938a
parent202ebe010de214b98ca6dd7a8af50db3f27998e1 (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.353
-rw-r--r--lib/libutil/pty.c54
-rw-r--r--lib/libutil/shlib_version2
-rw-r--r--lib/libutil/util.h6
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);