xref: /openbsd/usr.sbin/vmd/config.c (revision 07e1a8ca)
1 /*	$OpenBSD: config.c,v 1.56 2018/11/24 04:51:55 ori Exp $	*/
2 
3 /*
4  * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/time.h>
22 #include <sys/uio.h>
23 #include <sys/stat.h>
24 #include <sys/socket.h>
25 
26 #include <net/if.h>
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <termios.h>
31 #include <unistd.h>
32 #include <limits.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <util.h>
36 #include <errno.h>
37 #include <imsg.h>
38 
39 #include "proc.h"
40 #include "vmd.h"
41 
42 /* Supported bridge types */
43 const char *vmd_descsw[] = { "switch", "bridge", NULL };
44 
45 static int	 config_init_localprefix(struct vmd_config *);
46 
47 static int
48 config_init_localprefix(struct vmd_config *cfg)
49 {
50 	struct sockaddr_in6	*sin6;
51 
52 	if (host(VMD_DHCP_PREFIX, &cfg->cfg_localprefix) == -1)
53 		return (-1);
54 
55 	/* IPv6 is disabled by default */
56 	cfg->cfg_flags &= ~VMD_CFG_INET6;
57 
58 	/* Generate random IPv6 prefix only once */
59 	if (cfg->cfg_flags & VMD_CFG_AUTOINET6)
60 		return (0);
61 	if (host(VMD_ULA_PREFIX, &cfg->cfg_localprefix6) == -1)
62 		return (-1);
63 	/* Randomize the 56 bits "Global ID" and "Subnet ID" */
64 	sin6 = ss2sin6(&cfg->cfg_localprefix6.ss);
65 	arc4random_buf(&sin6->sin6_addr.s6_addr[1], 7);
66 	cfg->cfg_flags |= VMD_CFG_AUTOINET6;
67 
68 	return (0);
69 }
70 
71 int
72 config_init(struct vmd *env)
73 {
74 	struct privsep		*ps = &env->vmd_ps;
75 	unsigned int		 what;
76 
77 	/* Global configuration */
78 	ps->ps_what[PROC_PARENT] = CONFIG_ALL;
79 	ps->ps_what[PROC_VMM] = CONFIG_VMS;
80 
81 	/* Local prefix */
82 	if (config_init_localprefix(&env->vmd_cfg) == -1)
83 		return (-1);
84 
85 	/* Other configuration */
86 	what = ps->ps_what[privsep_process];
87 	if (what & CONFIG_VMS) {
88 		if ((env->vmd_vms = calloc(1, sizeof(*env->vmd_vms))) == NULL)
89 			return (-1);
90 		TAILQ_INIT(env->vmd_vms);
91 	}
92 	if (what & CONFIG_SWITCHES) {
93 		if ((env->vmd_switches = calloc(1,
94 		    sizeof(*env->vmd_switches))) == NULL)
95 			return (-1);
96 		TAILQ_INIT(env->vmd_switches);
97 	}
98 	if (what & CONFIG_USERS) {
99 		if ((env->vmd_users = calloc(1,
100 		    sizeof(*env->vmd_users))) == NULL)
101 			return (-1);
102 		TAILQ_INIT(env->vmd_users);
103 	}
104 
105 	return (0);
106 }
107 
108 void
109 config_purge(struct vmd *env, unsigned int reset)
110 {
111 	struct privsep		*ps = &env->vmd_ps;
112 	struct vmd_vm		*vm;
113 	struct vmd_switch	*vsw;
114 	unsigned int		 what;
115 
116 	DPRINTF("%s: %s purging vms and switches",
117 	    __func__, ps->ps_title[privsep_process]);
118 
119 	/* Reset global configuration (prefix was verified before) */
120 	config_init_localprefix(&env->vmd_cfg);
121 
122 	/* Reset other configuration */
123 	what = ps->ps_what[privsep_process] & reset;
124 	if (what & CONFIG_VMS && env->vmd_vms != NULL) {
125 		while ((vm = TAILQ_FIRST(env->vmd_vms)) != NULL) {
126 			vm_remove(vm, __func__);
127 		}
128 		env->vmd_nvm = 0;
129 	}
130 	if (what & CONFIG_SWITCHES && env->vmd_switches != NULL) {
131 		while ((vsw = TAILQ_FIRST(env->vmd_switches)) != NULL)
132 			switch_remove(vsw);
133 		env->vmd_nswitches = 0;
134 	}
135 }
136 
137 int
138 config_setconfig(struct vmd *env)
139 {
140 	struct privsep	*ps = &env->vmd_ps;
141 	unsigned int	 id;
142 
143 	DPRINTF("%s: setting config", __func__);
144 
145 	for (id = 0; id < PROC_MAX; id++) {
146 		if (id == privsep_process)
147 			continue;
148 		proc_compose(ps, id, IMSG_VMDOP_CONFIG, &env->vmd_cfg,
149 		    sizeof(env->vmd_cfg));
150 	}
151 
152 	return (0);
153 }
154 
155 int
156 config_getconfig(struct vmd *env, struct imsg *imsg)
157 {
158 	struct privsep	*ps = &env->vmd_ps;
159 
160 	log_debug("%s: %s retrieving config",
161 	    __func__, ps->ps_title[privsep_process]);
162 
163 	IMSG_SIZE_CHECK(imsg, &env->vmd_cfg);
164 	memcpy(&env->vmd_cfg, imsg->data, sizeof(env->vmd_cfg));
165 
166 	return (0);
167 }
168 
169 int
170 config_setreset(struct vmd *env, unsigned int reset)
171 {
172 	struct privsep	*ps = &env->vmd_ps;
173 	unsigned int	 id;
174 
175 	DPRINTF("%s: resetting state", __func__);
176 
177 	for (id = 0; id < PROC_MAX; id++) {
178 		if ((reset & ps->ps_what[id]) == 0 ||
179 		    id == privsep_process)
180 			continue;
181 		proc_compose(ps, id, IMSG_CTL_RESET, &reset, sizeof(reset));
182 	}
183 
184 	return (0);
185 }
186 
187 int
188 config_getreset(struct vmd *env, struct imsg *imsg)
189 {
190 	unsigned int	 mode;
191 
192 	IMSG_SIZE_CHECK(imsg, &mode);
193 	memcpy(&mode, imsg->data, sizeof(mode));
194 
195 	log_debug("%s: %s resetting state",
196 	    __func__, env->vmd_ps.ps_title[privsep_process]);
197 
198 	config_purge(env, mode);
199 
200 	return (0);
201 }
202 
203 int
204 config_setvm(struct privsep *ps, struct vmd_vm *vm, uint32_t peerid, uid_t uid)
205 {
206 	int diskfds[VMM_MAX_DISKS_PER_VM][VM_MAX_BASE_PER_DISK];
207 	struct vmd_if		*vif;
208 	struct vmop_create_params *vmc = &vm->vm_params;
209 	struct vm_create_params	*vcp = &vmc->vmc_params;
210 	unsigned int		 i, j;
211 	int			 fd = -1, vmboot = 0;
212 	int			 kernfd = -1;
213 	int			*tapfds = NULL;
214 	int			 cdromfd = -1;
215 	int			 saved_errno = 0;
216 	int			 n = 0, aflags, oflags;
217 	char			 ifname[IF_NAMESIZE], *s;
218 	char			 path[PATH_MAX];
219 	char			 base[PATH_MAX];
220 	unsigned int		 unit;
221 	struct timeval		 tv, rate, since_last;
222 
223 	errno = 0;
224 
225 	if (vm->vm_running) {
226 		log_warnx("%s: vm is already running", __func__);
227 		errno = EALREADY;
228 		return (-1);
229 	}
230 
231 	/* increase the user reference counter and check user limits */
232 	if (vm->vm_user != NULL && user_get(vm->vm_user->usr_id.uid) != NULL) {
233 		user_inc(vcp, vm->vm_user, 1);
234 		if (user_checklimit(vm->vm_user, vcp) == -1) {
235 			errno = EPERM;
236 			goto fail;
237 		}
238 	}
239 
240 	/*
241 	 * Rate-limit the VM so that it cannot restart in a loop:
242 	 * if the VM restarts after less than VM_START_RATE_SEC seconds,
243 	 * we increment the limit counter.  After VM_START_RATE_LIMIT
244 	 * of suchs fast reboots the VM is stopped.
245 	 */
246 	getmonotime(&tv);
247 	if (vm->vm_start_tv.tv_sec) {
248 		timersub(&tv, &vm->vm_start_tv, &since_last);
249 
250 		rate.tv_sec = VM_START_RATE_SEC;
251 		rate.tv_usec = 0;
252 		if (timercmp(&since_last, &rate, <))
253 			vm->vm_start_limit++;
254 		else {
255 			/* Reset counter */
256 			vm->vm_start_limit = 0;
257 		}
258 
259 		log_debug("%s: vm %u restarted after %lld.%ld seconds,"
260 		    " limit %d/%d", __func__, vcp->vcp_id, since_last.tv_sec,
261 		    since_last.tv_usec, vm->vm_start_limit,
262 		    VM_START_RATE_LIMIT);
263 
264 		if (vm->vm_start_limit >= VM_START_RATE_LIMIT) {
265 			log_warnx("%s: vm %u restarted too quickly",
266 			    __func__, vcp->vcp_id);
267 			errno = EPERM;
268 			goto fail;
269 		}
270 	}
271 	vm->vm_start_tv = tv;
272 
273 	for (i = 0; i < VMM_MAX_DISKS_PER_VM; i++)
274 		for (j = 0; j < VM_MAX_BASE_PER_DISK; j++)
275 			diskfds[i][j] = -1;
276 
277 	tapfds = reallocarray(NULL, vcp->vcp_nnics, sizeof(*tapfds));
278 	if (tapfds == NULL) {
279 		log_warn("%s: can't allocate tap fds", __func__);
280 		goto fail;
281 	}
282 	for (i = 0; i < vcp->vcp_nnics; i++)
283 		tapfds[i] = -1;
284 
285 	vm->vm_peerid = peerid;
286 	vm->vm_uid = uid;
287 
288 	if (!vm->vm_received) {
289 		if (strlen(vcp->vcp_kernel)) {
290 			/*
291 			 * Boot kernel from disk image if path matches the
292 			 * root disk.
293 			 */
294 			if (vcp->vcp_ndisks &&
295 			    strcmp(vcp->vcp_kernel, vcp->vcp_disks[0]) == 0)
296 				vmboot = 1;
297 			/* Open external kernel for child */
298 			else if ((kernfd =
299 			    open(vcp->vcp_kernel, O_RDONLY)) == -1) {
300 				log_warn("%s: can't open kernel or BIOS "
301 				    "boot image %s", __func__, vcp->vcp_kernel);
302 				goto fail;
303 			}
304 		}
305 
306 		/*
307 		 * Try to open the default BIOS image if no kernel/BIOS has been
308 		 * specified.  The BIOS is an external firmware file that is
309 		 * typically distributed separately due to an incompatible
310 		 * license.
311 		 */
312 		if (kernfd == -1 && !vmboot &&
313 		    (kernfd = open(VM_DEFAULT_BIOS, O_RDONLY)) == -1) {
314 			log_warn("can't open %s", VM_DEFAULT_BIOS);
315 			errno = VMD_BIOS_MISSING;
316 			goto fail;
317 		}
318 
319 		if (!vmboot && vm_checkaccess(kernfd,
320 		    vmc->vmc_checkaccess & VMOP_CREATE_KERNEL,
321 		    uid, R_OK) == -1) {
322 			log_warnx("vm \"%s\" no read access to kernel %s",
323 			    vcp->vcp_name, vcp->vcp_kernel);
324 			errno = EPERM;
325 			goto fail;
326 		}
327 	}
328 
329 	/* Open CDROM image for child */
330 	if (strlen(vcp->vcp_cdrom)) {
331 		/* Stat cdrom to ensure it is a regular file */
332 		if ((cdromfd =
333 		    open(vcp->vcp_cdrom, O_RDONLY)) == -1) {
334 			log_warn("can't open cdrom %s", vcp->vcp_cdrom);
335 			errno = VMD_CDROM_MISSING;
336 			goto fail;
337 		}
338 
339 		if (vm_checkaccess(cdromfd,
340 		    vmc->vmc_checkaccess & VMOP_CREATE_CDROM,
341 		    uid, R_OK) == -1) {
342 			log_warnx("vm \"%s\" no read access to cdrom %s",
343 			    vcp->vcp_name, vcp->vcp_cdrom);
344 			errno = EPERM;
345 			goto fail;
346 		}
347 	}
348 
349 	/* Open disk images for child */
350 	for (i = 0 ; i < vcp->vcp_ndisks; i++) {
351 		if (strlcpy(path, vcp->vcp_disks[i], sizeof(path))
352 		   >= sizeof(path))
353 			log_warnx("disk path %s too long", vcp->vcp_disks[i]);
354 		memset(vmc->vmc_diskbases, 0, sizeof(vmc->vmc_diskbases));
355 		oflags = O_RDWR|O_EXLOCK|O_NONBLOCK;
356 		aflags = R_OK|W_OK;
357 		for (j = 0; j < VM_MAX_BASE_PER_DISK; j++) {
358 			/* Stat disk[i] to ensure it is a regular file */
359 			if ((diskfds[i][j] = open(path, oflags)) == -1) {
360 				log_warn("can't open disk %s",
361 				    vcp->vcp_disks[i]);
362 				errno = VMD_DISK_MISSING;
363 				goto fail;
364 			}
365 
366 			if (vm_checkaccess(diskfds[i][j],
367 			    vmc->vmc_checkaccess & VMOP_CREATE_DISK,
368 			    uid, aflags) == -1) {
369 				log_warnx("vm \"%s\" unable to access "
370 				    "disk %s", vcp->vcp_name, path);
371 				errno = EPERM;
372 				goto fail;
373 			}
374 
375 			/*
376 			 * Clear the write and exclusive flags for base images.
377 			 * All writes should go to the top image, allowing them
378 			 * to be shared.
379 			 */
380 			oflags = O_RDONLY|O_NONBLOCK;
381 			aflags = R_OK;
382 			n = virtio_get_base(diskfds[i][j], base, sizeof(base),
383 			    vmc->vmc_disktypes[i], path);
384 			if (n == 0)
385 				break;
386 			if (n == -1) {
387 				log_warnx("vm \"%s\" unable to read "
388 				    "base %s for disk %s", vcp->vcp_name,
389 				    base, vcp->vcp_disks[i]);
390 				goto fail;
391 			}
392 			(void)strlcpy(path, base, sizeof(path));
393 		}
394 	}
395 
396 	/* Open network interfaces */
397 	for (i = 0 ; i < vcp->vcp_nnics; i++) {
398 		vif = &vm->vm_ifs[i];
399 
400 		/* Check if the user has requested a specific tap(4) */
401 		s = vmc->vmc_ifnames[i];
402 		if (*s != '\0' && strcmp("tap", s) != 0) {
403 			if (priv_getiftype(s, ifname, &unit) == -1 ||
404 			    strcmp(ifname, "tap") != 0) {
405 				log_warnx("%s: invalid tap name %s",
406 				    __func__, s);
407 				errno = EINVAL;
408 				goto fail;
409 			}
410 		} else
411 			s = NULL;
412 
413 		/*
414 		 * Either open the requested tap(4) device or get
415 		 * the next available one.
416 		 */
417 		if (s != NULL) {
418 			snprintf(path, PATH_MAX, "/dev/%s", s);
419 			tapfds[i] = open(path, O_RDWR | O_NONBLOCK);
420 		} else {
421 			tapfds[i] = opentap(ifname);
422 			s = ifname;
423 		}
424 		if (tapfds[i] == -1) {
425 			log_warn("%s: can't open tap %s", __func__, s);
426 			goto fail;
427 		}
428 		if ((vif->vif_name = strdup(s)) == NULL) {
429 			log_warn("%s: can't save tap %s", __func__, s);
430 			goto fail;
431 		}
432 
433 		/* Check if the the interface is attached to a switch */
434 		s = vmc->vmc_ifswitch[i];
435 		if (*s != '\0') {
436 			if ((vif->vif_switch = strdup(s)) == NULL) {
437 				log_warn("%s: can't save switch %s",
438 				    __func__, s);
439 				goto fail;
440 			}
441 		}
442 
443 		/* Check if the the interface is assigned to a group */
444 		s = vmc->vmc_ifgroup[i];
445 		if (*s != '\0') {
446 			if ((vif->vif_group = strdup(s)) == NULL) {
447 				log_warn("%s: can't save group %s",
448 				    __func__, s);
449 				goto fail;
450 			}
451 		}
452 
453 		/* non-default rdomain (requires VMIFF_RDOMAIN below) */
454 		vif->vif_rdomain = vmc->vmc_ifrdomain[i];
455 
456 		/* Set the interface status */
457 		vif->vif_flags =
458 		    vmc->vmc_ifflags[i] & (VMIFF_UP|VMIFF_OPTMASK);
459 	}
460 
461 	/* Open TTY */
462 	if (vm->vm_ttyname == NULL) {
463 		if (vm_opentty(vm) == -1) {
464 			log_warn("%s: can't open tty %s", __func__,
465 			    vm->vm_ttyname == NULL ? "" : vm->vm_ttyname);
466 			goto fail;
467 		}
468 	}
469 	if ((fd = dup(vm->vm_tty)) == -1) {
470 		log_warn("%s: can't re-open tty %s", __func__, vm->vm_ttyname);
471 		goto fail;
472 	}
473 
474 	/* Send VM information */
475 	if (vm->vm_received)
476 		proc_compose_imsg(ps, PROC_VMM, -1,
477 		    IMSG_VMDOP_RECEIVE_VM_REQUEST, vm->vm_vmid, fd,  vmc,
478 		    sizeof(struct vmop_create_params));
479 	else
480 		proc_compose_imsg(ps, PROC_VMM, -1,
481 		    IMSG_VMDOP_START_VM_REQUEST, vm->vm_vmid, kernfd,
482 		    vmc, sizeof(*vmc));
483 
484 	if (strlen(vcp->vcp_cdrom))
485 		proc_compose_imsg(ps, PROC_VMM, -1,
486 		    IMSG_VMDOP_START_VM_CDROM, vm->vm_vmid, cdromfd,
487 		    NULL, 0);
488 
489 	for (i = 0; i < vcp->vcp_ndisks; i++) {
490 		for (j = 0; j < VM_MAX_BASE_PER_DISK; j++) {
491 			if (diskfds[i][j] == -1)
492 				break;
493 			proc_compose_imsg(ps, PROC_VMM, -1,
494 			    IMSG_VMDOP_START_VM_DISK, vm->vm_vmid,
495 			    diskfds[i][j], &i, sizeof(i));
496 		}
497 	}
498 	for (i = 0; i < vcp->vcp_nnics; i++) {
499 		proc_compose_imsg(ps, PROC_VMM, -1,
500 		    IMSG_VMDOP_START_VM_IF, vm->vm_vmid, tapfds[i],
501 		    &i, sizeof(i));
502 	}
503 
504 	if (!vm->vm_received)
505 		proc_compose_imsg(ps, PROC_VMM, -1,
506 		    IMSG_VMDOP_START_VM_END, vm->vm_vmid, fd,  NULL, 0);
507 
508 	free(tapfds);
509 
510 	vm->vm_running = 1;
511 	return (0);
512 
513  fail:
514 	saved_errno = errno;
515 	log_warnx("failed to start vm %s", vcp->vcp_name);
516 
517 	if (kernfd != -1)
518 		close(kernfd);
519 	if (cdromfd != -1)
520 		close(cdromfd);
521 	for (i = 0; i < vcp->vcp_ndisks; i++)
522 		for (j = 0; j < VM_MAX_BASE_PER_DISK; j++)
523 			if (diskfds[i][j] != -1)
524 				close(diskfds[i][j]);
525 	if (tapfds != NULL) {
526 		for (i = 0; i < vcp->vcp_nnics; i++)
527 			close(tapfds[i]);
528 		free(tapfds);
529 	}
530 
531 	if (vm->vm_from_config) {
532 		vm_stop(vm, 0, __func__);
533 	} else {
534 		vm_remove(vm, __func__);
535 	}
536 	errno = saved_errno;
537 	if (errno == 0)
538 		errno = EINVAL;
539 	return (-1);
540 }
541 
542 int
543 config_getvm(struct privsep *ps, struct imsg *imsg)
544 {
545 	struct vmop_create_params	 vmc;
546 	struct vmd_vm			*vm;
547 
548 	IMSG_SIZE_CHECK(imsg, &vmc);
549 	memcpy(&vmc, imsg->data, sizeof(vmc));
550 
551 	errno = 0;
552 	if (vm_register(ps, &vmc, &vm, imsg->hdr.peerid, 0) == -1)
553 		goto fail;
554 
555 	/* If the fd is -1, the kernel will be searched on the disk */
556 	vm->vm_kernel = imsg->fd;
557 	vm->vm_running = 1;
558 	vm->vm_peerid = (uint32_t)-1;
559 
560 	return (0);
561 
562  fail:
563 	if (imsg->fd != -1) {
564 		close(imsg->fd);
565 		imsg->fd = -1;
566 	}
567 
568 	vm_remove(vm, __func__);
569 	if (errno == 0)
570 		errno = EINVAL;
571 
572 	return (-1);
573 }
574 
575 int
576 config_getdisk(struct privsep *ps, struct imsg *imsg)
577 {
578 	struct vmd_vm	*vm;
579 	unsigned int	 n, idx;
580 
581 	errno = 0;
582 	if ((vm = vm_getbyvmid(imsg->hdr.peerid)) == NULL) {
583 		errno = ENOENT;
584 		return (-1);
585 	}
586 
587 	IMSG_SIZE_CHECK(imsg, &n);
588 	memcpy(&n, imsg->data, sizeof(n));
589 
590 	if (n >= vm->vm_params.vmc_params.vcp_ndisks || imsg->fd == -1) {
591 		log_warnx("invalid disk id");
592 		errno = EINVAL;
593 		return (-1);
594 	}
595 	idx = vm->vm_params.vmc_diskbases[n]++;
596 	if (idx >= VM_MAX_BASE_PER_DISK) {
597 		log_warnx("too many bases for disk");
598 		errno = EINVAL;
599 		return (-1);
600 	}
601 	vm->vm_disks[n][idx] = imsg->fd;
602 	return (0);
603 }
604 
605 int
606 config_getif(struct privsep *ps, struct imsg *imsg)
607 {
608 	struct vmd_vm	*vm;
609 	unsigned int	 n;
610 
611 	errno = 0;
612 	if ((vm = vm_getbyvmid(imsg->hdr.peerid)) == NULL) {
613 		errno = ENOENT;
614 		return (-1);
615 	}
616 
617 	IMSG_SIZE_CHECK(imsg, &n);
618 	memcpy(&n, imsg->data, sizeof(n));
619 	if (n >= vm->vm_params.vmc_params.vcp_nnics ||
620 	    vm->vm_ifs[n].vif_fd != -1 || imsg->fd == -1) {
621 		log_warnx("invalid interface id");
622 		goto fail;
623 	}
624 	vm->vm_ifs[n].vif_fd = imsg->fd;
625 	return (0);
626  fail:
627 	if (imsg->fd != -1)
628 		close(imsg->fd);
629 	errno = EINVAL;
630 	return (-1);
631 }
632 
633 int
634 config_getcdrom(struct privsep *ps, struct imsg *imsg)
635 {
636 	struct vmd_vm	*vm;
637 
638 	errno = 0;
639 	if ((vm = vm_getbyvmid(imsg->hdr.peerid)) == NULL) {
640 		errno = ENOENT;
641 		return (-1);
642 	}
643 
644 	if (imsg->fd == -1) {
645 		log_warnx("invalid cdrom id");
646 		goto fail;
647 	}
648 
649 	vm->vm_cdrom = imsg->fd;
650 	return (0);
651  fail:
652 	if (imsg->fd != -1)
653 		close(imsg->fd);
654 	errno = EINVAL;
655 	return (-1);
656 }
657