The following diff is not really needed without just yet, but:
- openening /dev/ptm in advance might allow better pledge in the future
- customizing "openpty" will allow to do what we need next
Since openpty(4) is libutil and not libc, it should be fine not using it.

OK?

    Replace openpty(3) with local function that uses pre-opened /dev/ptm fd
    
    This allows more flexibility for upcoming changes and better pledge.
    We also didn't use half of the features of libutil's openpty function.
    Additionally, make sure that the ttys are closed correctly on shutdown.

diff --git usr.sbin/vmd/config.c usr.sbin/vmd/config.c
index f35a3b3..a16c143 100644
--- usr.sbin/vmd/config.c
+++ usr.sbin/vmd/config.c
@@ -126,10 +126,9 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, 
uint32_t peerid)
        struct vmop_create_params *vmc = &vm->vm_params;
        struct vm_create_params *vcp = &vmc->vmc_params;
        unsigned int             i;
-       int                      fd = -1, ttys_fd;
+       int                      fd = -1;
        int                      kernfd = -1, *diskfds = NULL, *tapfds = NULL;
        int                      saved_errno = 0;
-       char                     ptyname[VM_TTYNAME_MAX];
        char                     ifname[IF_NAMESIZE], *s;
        char                     path[PATH_MAX];
        unsigned int             unit;
@@ -241,12 +240,11 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, 
uint32_t peerid)
 
        /* Open TTY */
        if (vm->vm_ttyname == NULL) {
-               if (openpty(&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);
+               if (vm_opentty(vm) == -1) {
+                       log_warn("%s: can't open tty %s", __func__,
+                           vm->vm_ttyname == NULL ? "" : vm->vm_ttyname);
                        goto fail;
                }
-               close(ttys_fd);
        }
        if ((fd = dup(vm->vm_tty)) == -1) {
                log_warn("%s: can't re-open tty %s", __func__, vm->vm_ttyname);
diff --git usr.sbin/vmd/vmd.c usr.sbin/vmd/vmd.c
index a01e40f..ed678ee 100644
--- usr.sbin/vmd/vmd.c
+++ usr.sbin/vmd/vmd.c
@@ -20,6 +20,8 @@
 #include <sys/queue.h>
 #include <sys/wait.h>
 #include <sys/cdefs.h>
+#include <sys/tty.h>
+#include <sys/ioctl.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -33,7 +35,6 @@
 #include <syslog.h>
 #include <unistd.h>
 #include <ctype.h>
-#include <util.h>
 
 #include "proc.h"
 #include "vmd.h"
@@ -484,6 +485,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:
         * stdio - for malloc and basic I/O including events.
@@ -605,6 +609,12 @@ vmd_reload(unsigned int reset, const char *filename)
 void
 vmd_shutdown(void)
 {
+       struct vmd_vm *vm, *vm_next;
+
+       TAILQ_FOREACH_SAFE(vm, env->vmd_vms, vm_entry, vm_next) {
+               vm_remove(vm);
+       }
+
        proc_kill(&env->vmd_ps);
        free(env);
 
@@ -702,16 +712,8 @@ vm_stop(struct vmd_vm *vm, int keeptty)
                close(vm->vm_kernel);
                vm->vm_kernel = -1;
        }
-
-       if (keeptty)
-               return;
-
-       if (vm->vm_tty != -1) {
-               close(vm->vm_tty);
-               vm->vm_tty = -1;
-       }
-       free(vm->vm_ttyname);
-       vm->vm_ttyname = NULL;
+       if (!keeptty)
+               vm_closetty(vm);
 }
 
 void
@@ -769,6 +771,7 @@ vm_register(struct privsep *ps, struct vmop_create_params 
*vmc,
 
        memcpy(&vm->vm_params, vmc, sizeof(vm->vm_params));
        vm->vm_pid = -1;
+       vm->vm_tty = -1;
 
        for (i = 0; i < vcp->vcp_ndisks; i++)
                vm->vm_disks[i] = -1;
@@ -787,12 +790,45 @@ vm_register(struct privsep *ps, struct vmop_create_params 
*vmc,
 
        *ret_vm = vm;
        return (0);
-fail:
+ fail:
        if (errno == 0)
                errno = EINVAL;
        return (-1);
 }
 
+int
+vm_opentty(struct vmd_vm *vm)
+{
+       struct ptmget            ptm;
+
+       /*
+        * Open tty with pre-opened PTM fd
+        */
+       if ((ioctl(env->vmd_ptmfd, PTMGET, &ptm) == -1))
+               return (-1);
+
+       vm->vm_tty = ptm.cfd;
+       close(ptm.sfd);
+       if ((vm->vm_ttyname = strdup(ptm.sn)) == NULL)
+               goto fail;
+
+       return (0);
+ fail:
+       vm_closetty(vm);
+       return (-1);
+}
+
+void
+vm_closetty(struct vmd_vm *vm)
+{
+       if (vm->vm_tty != -1) {
+               close(vm->vm_tty);
+               vm->vm_tty = -1;
+       }
+       free(vm->vm_ttyname);
+       vm->vm_ttyname = NULL;
+}
+
 void
 switch_remove(struct vmd_switch *vsw)
 {
diff --git usr.sbin/vmd/vmd.h usr.sbin/vmd/vmd.h
index e371112..26d345c 100644
--- usr.sbin/vmd/vmd.h
+++ usr.sbin/vmd/vmd.h
@@ -185,6 +185,7 @@ struct vmd {
        struct switchlist       *vmd_switches;
 
        int                      vmd_fd;
+       int                      vmd_ptmfd;
 };
 
 /* vmd.c */
@@ -197,6 +198,8 @@ void         vm_stop(struct vmd_vm *, int);
 void    vm_remove(struct vmd_vm *);
 int     vm_register(struct privsep *, struct vmop_create_params *,
            struct vmd_vm **, uint32_t);
+int     vm_opentty(struct vmd_vm *);
+void    vm_closetty(struct vmd_vm *);
 void    switch_remove(struct vmd_switch *);
 struct vmd_switch *switch_getbyname(const char *);
 char   *get_string(uint8_t *, size_t);

Reply via email to