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 */