On Wed, Jan 25, 2017 at 12:41:26AM -0700, Theo de Raadt wrote: > > On Wed, Jan 25, 2017 at 12:33:36AM -0700, Theo de Raadt wrote: > > > > 2. vmd calls openpty() in the pledged parent whenever a new VM is > > > > started - effectively doing ioctls on post-pledge fds. I will > > > > probably solve this by opening the pty in the non-pledged "priv" > > > > process, and do some additional passing, but then I'll also have to > > > > give up its chroot to access /dev/. > > > > > > > > vmd: ioctl 40287401 post-pledge fd 12 > > > > vmd(51681): syscall 54 "tty" > > > > > > How about opening PATH_PTMDEV early and keeping it open in a > > > properly protected process; then create pty pairs as required. > > > > Oh, yes, I should have looked at openpty() in libutil first :) > > That makes sense, I will try it. > > But please don't become too attached to the proposed semantics. > It's a proposal, we need to learn if it actually helps or hinders > privsep programs become better.
ok, no problem, it is a very simple thing in vmd. so, just as a proposal, the attached diff makes it work with vmd and the chroot-friendly version of openpty might be useful for libutil. Reyk Index: lib/libutil/openpty.3 =================================================================== RCS file: /cvs/src/lib/libutil/openpty.3,v retrieving revision 1.17 diff -u -p -u -p -r1.17 openpty.3 --- lib/libutil/openpty.3 28 Aug 2015 19:54:06 -0000 1.17 +++ lib/libutil/openpty.3 25 Jan 2017 08:40:46 -0000 @@ -44,6 +44,8 @@ .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" @@ -88,6 +90,15 @@ the caller, permissions are set to corre uses of that device are revoked (see .Xr revoke 2 for details). +.Pp +The +.Fn fdopenpty +function works like +.Fn openpty +but expects a pre-opened +.Pa /dev/ptm +file descriptor +.Fa ptmfd . .Pp The .Fn login_tty Index: lib/libutil/pty.c =================================================================== RCS file: /cvs/src/lib/libutil/pty.c,v retrieving revision 1.20 diff -u -p -u -p -r1.20 pty.c --- lib/libutil/pty.c 30 Aug 2016 14:44:45 -0000 1.20 +++ lib/libutil/pty.c 25 Jan 2017 08:40:46 -0000 @@ -57,11 +57,30 @@ openpty(int *amaster, int *aslave, char fd = open(PATH_PTMDEV, O_RDWR|O_CLOEXEC); if (fd == -1) return (-1); - if ((ioctl(fd, PTMGET, &ptm) == -1)) { + + if (fdopenpty(fd, amaster, aslave, name, termp, winp) == -1) { close(fd); return (-1); } close(fd); + + 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. + */ + if ((ioctl(ptmfd, PTMGET, &ptm) == -1)) + return (-1); + master = ptm.cfd; slave = ptm.sfd; if (name) { Index: lib/libutil/util.h =================================================================== RCS file: /cvs/src/lib/libutil/util.h,v retrieving revision 1.34 diff -u -p -u -p -r1.34 util.h --- lib/libutil/util.h 3 Jun 2013 21:07:02 -0000 1.34 +++ lib/libutil/util.h 25 Jan 2017 08:40:46 -0000 @@ -99,6 +99,7 @@ void pw_copy(int, int, const struct pass int pw_scan(char *, struct passwd *, int *); void pw_error(const char *, int, int); 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 *); int getmaxpartitions(void); Index: usr.sbin/vmd/config.c =================================================================== RCS file: /cvs/src/usr.sbin/vmd/config.c,v retrieving revision 1.23 diff -u -p -u -p -r1.23 config.c --- usr.sbin/vmd/config.c 17 Jan 2017 21:51:01 -0000 1.23 +++ usr.sbin/vmd/config.c 25 Jan 2017 08:40:46 -0000 @@ -34,6 +34,7 @@ #include <util.h> #include <errno.h> #include <imsg.h> +#include <util.h> #include "proc.h" #include "vmd.h" @@ -122,6 +123,7 @@ config_getreset(struct vmd *env, struct int config_setvm(struct privsep *ps, struct vmd_vm *vm, uint32_t peerid) { + struct vmd *env = ps->ps_env; struct vmd_if *vif; struct vmop_create_params *vmc = &vm->vm_params; struct vm_create_params *vcp = &vmc->vmc_params; @@ -241,7 +243,8 @@ config_setvm(struct privsep *ps, struct /* Open TTY */ if (vm->vm_ttyname == NULL) { - if (openpty(&vm->vm_tty, &ttys_fd, ptyname, NULL, NULL) == -1 || + if (fdopenpty(env->vmd_ptmfd, + &vm->vm_tty, &ttys_fd, ptyname, NULL, NULL) == -1 || (vm->vm_ttyname = strdup(ptyname)) == NULL) { log_warn("%s: can't open tty %s", __func__, ptyname); goto fail; Index: usr.sbin/vmd/vmd.c =================================================================== RCS file: /cvs/src/usr.sbin/vmd/vmd.c,v retrieving revision 1.50 diff -u -p -u -p -r1.50 vmd.c --- usr.sbin/vmd/vmd.c 13 Jan 2017 19:21:16 -0000 1.50 +++ usr.sbin/vmd/vmd.c 25 Jan 2017 08:40:46 -0000 @@ -20,6 +20,7 @@ #include <sys/queue.h> #include <sys/wait.h> #include <sys/cdefs.h> +#include <sys/tty.h> #include <stdio.h> #include <stdlib.h> @@ -483,6 +484,9 @@ vmd_configure(void) { struct vmd_vm *vm; struct vmd_switch *vsw; + + if ((env->vmd_ptmfd = open(PATH_PTMDEV, O_RDWR|O_CLOEXEC)) == -1) + fatal("open %s", PATH_PTMDEV); /* * pledge in the parent process: Index: usr.sbin/vmd/vmd.h =================================================================== RCS file: /cvs/src/usr.sbin/vmd/vmd.h,v retrieving revision 1.43 diff -u -p -u -p -r1.43 vmd.h --- usr.sbin/vmd/vmd.h 13 Jan 2017 19:21:16 -0000 1.43 +++ usr.sbin/vmd/vmd.h 25 Jan 2017 08:40:46 -0000 @@ -185,6 +185,7 @@ struct vmd { struct switchlist *vmd_switches; int vmd_fd; + int vmd_ptmfd; }; /* vmd.c */