During h2k22 there was some discussion around how vmd(8) manages vms and the vmm(4) device's role. While looking into something related, I found vmd opens /dev/vmm in each subprocess during the initial fork+execve dance.
The only vmd process that needs /dev/vmm is the vmm process. The diff below changes it so that *only* the parent process opens /dev/vmm and then uses fd passing to send it to the vmm process once fork+exec'd. This adds a new imsg type specific to this handoff. The other processes don't end up with the vmm pledge, so there's no reason they need open file descriptors to the vmm device. OK? diff refs/heads/master refs/heads/vmd-vmm-open commit - adc9c11636d08981539860c611938338c714d31e commit + 1bb17c1c2d6cd28c231fa2eb6f8494e5498bb1a3 blob - bd0d8580ffc25d905e5f20c1de5044397ddf313d blob + 41e4b7b5852c7523a7b1c0e3a73591638a9c9e56 --- usr.sbin/vmd/vmd.c +++ usr.sbin/vmd/vmd.c @@ -847,8 +847,8 @@ main(int argc, char **argv) proc_priv->p_pw = &proc_privpw; /* initialized to all 0 */ proc_priv->p_chroot = ps->ps_pw->pw_dir; /* from VMD_USER */ - /* Open /dev/vmm */ - if (env->vmd_noaction == 0) { + /* Open /dev/vmm early. */ + if (env->vmd_noaction == 0 && proc_id == PROC_PARENT) { env->vmd_fd = open(VMM_NODE, O_RDWR); if (env->vmd_fd == -1) fatal("%s", VMM_NODE); @@ -971,6 +971,10 @@ vmd_configure(void) exit(0); } + /* Send VMM device fd to vmm proc. */ + proc_compose_imsg(&env->vmd_ps, PROC_VMM, -1, + IMSG_VMDOP_RECEIVE_VMM_FD, -1, env->vmd_fd, NULL, 0); + /* Send shared global configuration to all children */ if (config_setconfig(env) == -1) return (-1); blob - c27d03df7336a2c8ede22ec0d83b74d327fb3244 blob + 2ca4aa336bf68b0d8bf8183e92c9d0ef99d5411e --- usr.sbin/vmd/vmd.h +++ usr.sbin/vmd/vmd.h @@ -108,6 +108,7 @@ enum imsg_type { IMSG_VMDOP_GET_INFO_VM_DATA, IMSG_VMDOP_GET_INFO_VM_END_DATA, IMSG_VMDOP_LOAD, + IMSG_VMDOP_RECEIVE_VMM_FD, IMSG_VMDOP_RELOAD, IMSG_VMDOP_PRIV_IFDESCR, IMSG_VMDOP_PRIV_IFADD, blob - 6c2bdbd12a3ee11aa88055200e11e0f2a0ff667f blob + 2f82a241c1c1672770529ef98f9b748714512704 --- usr.sbin/vmd/vmm.c +++ usr.sbin/vmd/vmm.c @@ -94,9 +94,6 @@ vmm_run(struct privsep *ps, struct privsep_proc *p, vo */ if (pledge("stdio vmm sendfd recvfd proc", NULL) == -1) fatal("pledge"); - - /* Get and terminate all running VMs */ - get_info_vm(ps, NULL, 1); } int @@ -315,6 +312,14 @@ vmm_dispatch_parent(int fd, struct privsep_proc *p, st imsg->hdr.type, imsg->hdr.peerid, imsg->hdr.pid, imsg->fd, &var, sizeof(var)); break; + case IMSG_VMDOP_RECEIVE_VMM_FD: + if (env->vmd_fd > -1) + fatalx("already received vmm fd"); + env->vmd_fd = imsg->fd; + + /* Get and terminate all running VMs */ + get_info_vm(ps, NULL, 1); + break; default: return (-1); }