debuggers.hg

view tools/libxl/libxl_dm.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents b59f04eb8978
children ccfa0527893e
line source
1 /*
2 * Copyright (C) 2010 Citrix Ltd.
3 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
4 * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
5 * Author Gianni Tedesco <gianni.tedesco@citrix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 only. with the special
10 * exception on linking described in file LICENSE.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 */
18 #include "libxl_osdeps.h"
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <signal.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include "libxl_utils.h"
27 #include "libxl_internal.h"
28 #include "libxl.h"
29 #include "flexarray.h"
31 static const char *libxl_tapif_script(libxl__gc *gc)
32 {
33 #ifdef __linux__
34 return libxl__strdup(gc, "no");
35 #else
36 return libxl__sprintf(gc, "%s/qemu-ifup", libxl_xen_script_dir_path());
37 #endif
38 }
40 static char ** libxl_build_device_model_args_old(libxl__gc *gc,
41 libxl_device_model_info *info,
42 libxl_device_nic *vifs,
43 int num_vifs)
44 {
45 int i;
46 flexarray_t *dm_args;
47 dm_args = flexarray_make(16, 1);
49 if (!dm_args)
50 return NULL;
52 flexarray_vappend(dm_args, "qemu-dm", "-d", libxl__sprintf(gc, "%d", info->domid), NULL);
54 if (info->dom_name)
55 flexarray_vappend(dm_args, "-domain-name", info->dom_name, NULL);
57 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
58 flexarray_append(dm_args, "-vnc");
59 if (info->vncdisplay) {
60 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
61 flexarray_append(dm_args,
62 libxl__sprintf(gc, "%s:%d%s",
63 info->vnclisten,
64 info->vncdisplay,
65 info->vncpasswd ? ",password" : ""));
66 } else {
67 flexarray_append(dm_args, libxl__sprintf(gc, "127.0.0.1:%d", info->vncdisplay));
68 }
69 } else if (info->vnclisten) {
70 if (strchr(info->vnclisten, ':') != NULL) {
71 flexarray_append(dm_args, info->vnclisten);
72 } else {
73 flexarray_append(dm_args, libxl__sprintf(gc, "%s:0", info->vnclisten));
74 }
75 } else {
76 flexarray_append(dm_args, "127.0.0.1:0");
77 }
78 if (info->vncunused) {
79 flexarray_append(dm_args, "-vncunused");
80 }
81 }
82 if (info->sdl) {
83 flexarray_append(dm_args, "-sdl");
84 if (!info->opengl) {
85 flexarray_append(dm_args, "-disable-opengl");
86 }
87 }
88 if (info->keymap) {
89 flexarray_vappend(dm_args, "-k", info->keymap, NULL);
90 }
91 if (info->nographic && (!info->sdl && !info->vnc)) {
92 flexarray_append(dm_args, "-nographic");
93 }
94 if (info->serial) {
95 flexarray_vappend(dm_args, "-serial", info->serial, NULL);
96 }
97 if (info->type == XENFV) {
98 int ioemu_vifs = 0;
100 if (info->videoram) {
101 flexarray_vappend(dm_args, "-videoram", libxl__sprintf(gc, "%d", info->videoram), NULL);
102 }
103 if (info->stdvga) {
104 flexarray_append(dm_args, "-std-vga");
105 }
107 if (info->boot) {
108 flexarray_vappend(dm_args, "-boot", info->boot, NULL);
109 }
110 if (info->usb || info->usbdevice) {
111 flexarray_append(dm_args, "-usb");
112 if (info->usbdevice) {
113 flexarray_vappend(dm_args, "-usbdevice", info->usbdevice, NULL);
114 }
115 }
116 if (info->soundhw) {
117 flexarray_vappend(dm_args, "-soundhw", info->soundhw, NULL);
118 }
119 if (info->apic) {
120 flexarray_append(dm_args, "-acpi");
121 }
122 if (info->vcpus > 1) {
123 flexarray_vappend(dm_args, "-vcpus", libxl__sprintf(gc, "%d", info->vcpus), NULL);
124 }
125 if (info->vcpu_avail) {
126 flexarray_vappend(dm_args, "-vcpu_avail", libxl__sprintf(gc, "0x%x", info->vcpu_avail), NULL);
127 }
128 for (i = 0; i < num_vifs; i++) {
129 if (vifs[i].nictype == NICTYPE_IOEMU) {
130 char *smac = libxl__sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
131 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
132 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
133 char *ifname;
134 if (!vifs[i].ifname)
135 ifname = libxl__sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid);
136 else
137 ifname = vifs[i].ifname;
138 flexarray_vappend(dm_args,
139 "-net", libxl__sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s",
140 vifs[i].devid, smac, vifs[i].model),
141 "-net", libxl__sprintf(gc, "tap,vlan=%d,ifname=%s,bridge=%s,script=%s",
142 vifs[i].devid, ifname, vifs[i].bridge, libxl_tapif_script(gc)),
143 NULL);
144 ioemu_vifs++;
145 }
146 }
147 /* If we have no emulated nics, tell qemu not to create any */
148 if ( ioemu_vifs == 0 ) {
149 flexarray_vappend(dm_args, "-net", "none", NULL);
150 }
151 }
152 if (info->saved_state) {
153 flexarray_vappend(dm_args, "-loadvm", info->saved_state, NULL);
154 }
155 for (i = 0; info->extra && info->extra[i] != NULL; i++)
156 flexarray_append(dm_args, info->extra[i]);
157 flexarray_append(dm_args, "-M");
158 if (info->type == XENPV)
159 flexarray_append(dm_args, "xenpv");
160 else
161 flexarray_append(dm_args, "xenfv");
162 flexarray_append(dm_args, NULL);
163 return (char **) flexarray_contents(dm_args);
164 }
166 static char ** libxl_build_device_model_args_new(libxl__gc *gc,
167 libxl_device_model_info *info,
168 libxl_device_nic *vifs,
169 int num_vifs)
170 {
171 flexarray_t *dm_args;
172 libxl_device_disk *disks;
173 int nb, i;
175 dm_args = flexarray_make(16, 1);
176 if (!dm_args)
177 return NULL;
179 flexarray_vappend(dm_args, libxl__strdup(gc, info->device_model),
180 "-xen-domid", libxl__sprintf(gc, "%d", info->domid), NULL);
182 if (info->type == XENPV) {
183 flexarray_append(dm_args, "-xen-attach");
184 }
186 if (info->dom_name) {
187 flexarray_vappend(dm_args, "-name", info->dom_name, NULL);
188 }
189 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
190 int display = 0;
191 const char *listen = "127.0.0.1";
193 flexarray_append(dm_args, "-vnc");
195 if (info->vncdisplay) {
196 display = info->vncdisplay;
197 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
198 listen = info->vnclisten;
199 }
200 } else if (info->vnclisten) {
201 listen = info->vnclisten;
202 }
204 if (strchr(listen, ':') != NULL)
205 flexarray_append(dm_args,
206 libxl__sprintf(gc, "%s%s", listen,
207 info->vncunused ? ",to=99" : ""));
208 else
209 flexarray_append(dm_args,
210 libxl__sprintf(gc, "%s:%d%s", listen, display,
211 info->vncunused ? ",to=99" : ""));
212 }
213 if (info->sdl) {
214 flexarray_append(dm_args, "-sdl");
215 }
217 if (info->type == XENPV && !info->nographic) {
218 flexarray_vappend(dm_args, "-vga", "xenfb", NULL);
219 }
221 if (info->keymap) {
222 flexarray_vappend(dm_args, "-k", info->keymap, NULL);
223 }
224 if (info->nographic && (!info->sdl && !info->vnc)) {
225 flexarray_append(dm_args, "-nographic");
226 }
227 if (info->serial) {
228 flexarray_vappend(dm_args, "-serial", info->serial, NULL);
229 }
230 if (info->type == XENFV) {
231 int ioemu_vifs = 0;
233 if (info->stdvga) {
234 flexarray_vappend(dm_args, "-vga", "std", NULL);
235 }
237 if (info->boot) {
238 flexarray_vappend(dm_args, "-boot", libxl__sprintf(gc, "order=%s", info->boot), NULL);
239 }
240 if (info->usb || info->usbdevice) {
241 flexarray_append(dm_args, "-usb");
242 if (info->usbdevice) {
243 flexarray_vappend(dm_args, "-usbdevice", info->usbdevice, NULL);
244 }
245 }
246 if (info->soundhw) {
247 flexarray_vappend(dm_args, "-soundhw", info->soundhw, NULL);
248 }
249 if (!info->apic) {
250 flexarray_append(dm_args, "-no-acpi");
251 }
252 if (info->vcpus > 1) {
253 flexarray_append(dm_args, "-smp");
254 if (info->vcpu_avail)
255 flexarray_append(dm_args, libxl__sprintf(gc, "%d,maxcpus=%d", info->vcpus, info->vcpu_avail));
256 else
257 flexarray_append(dm_args, libxl__sprintf(gc, "%d", info->vcpus));
258 }
259 for (i = 0; i < num_vifs; i++) {
260 if (vifs[i].nictype == NICTYPE_IOEMU) {
261 char *smac = libxl__sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
262 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
263 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
264 char *ifname;
265 if (!vifs[i].ifname) {
266 ifname = libxl__sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid);
267 } else {
268 ifname = vifs[i].ifname;
269 }
270 flexarray_append(dm_args, "-net");
271 flexarray_append(dm_args, libxl__sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s",
272 vifs[i].devid, smac, vifs[i].model));
273 flexarray_append(dm_args, "-net");
274 flexarray_append(dm_args, libxl__sprintf(gc, "tap,vlan=%d,ifname=%s,script=%s",
275 vifs[i].devid, ifname, libxl_tapif_script(gc)));
276 ioemu_vifs++;
277 }
278 }
279 /* If we have no emulated nics, tell qemu not to create any */
280 if ( ioemu_vifs == 0 ) {
281 flexarray_append(dm_args, "-net");
282 flexarray_append(dm_args, "none");
283 }
284 }
285 if (info->saved_state) {
286 flexarray_append(dm_args, "-loadvm");
287 flexarray_append(dm_args, info->saved_state);
288 }
289 for (i = 0; info->extra && info->extra[i] != NULL; i++)
290 flexarray_append(dm_args, info->extra[i]);
291 flexarray_append(dm_args, "-M");
292 if (info->type == XENPV)
293 flexarray_append(dm_args, "xenpv");
294 else
295 flexarray_append(dm_args, "xenfv");
297 /* RAM Size */
298 flexarray_append(dm_args, "-m");
299 flexarray_append(dm_args, libxl__sprintf(gc, "%d", info->target_ram));
301 if (info->type == XENFV) {
302 disks = libxl_device_disk_list(libxl__gc_owner(gc), info->domid, &nb);
303 for (i; i < nb; i++) {
304 if (disks[i].is_cdrom) {
305 flexarray_append(dm_args, "-cdrom");
306 flexarray_append(dm_args, libxl__strdup(gc, disks[i].physpath));
307 } else {
308 flexarray_append(dm_args, libxl__sprintf(gc, "-%s", disks[i].virtpath));
309 flexarray_append(dm_args, libxl__strdup(gc, disks[i].physpath));
310 }
311 libxl_device_disk_destroy(&disks[i]);
312 }
313 free(disks);
314 }
315 flexarray_append(dm_args, NULL);
316 return (char **) flexarray_contents(dm_args);
317 }
319 static char ** libxl_build_device_model_args(libxl__gc *gc,
320 libxl_device_model_info *info,
321 libxl_device_nic *vifs,
322 int num_vifs)
323 {
324 libxl_ctx *ctx = libxl__gc_owner(gc);
325 int new_qemu;
327 new_qemu = libxl_check_device_model_version(ctx, info->device_model);
329 if (new_qemu == 1) {
330 return libxl_build_device_model_args_new(gc, info, vifs, num_vifs);
331 } else {
332 return libxl_build_device_model_args_old(gc, info, vifs, num_vifs);
333 }
334 }
336 static void dm_xenstore_record_pid(void *for_spawn, pid_t innerchild)
337 {
338 libxl__device_model_starting *starting = for_spawn;
339 struct xs_handle *xsh;
340 char *path = NULL, *pid = NULL;
341 int len;
343 if (asprintf(&path, "%s/%s", starting->dom_path, "image/device-model-pid") < 0)
344 goto out;
346 len = asprintf(&pid, "%d", innerchild);
347 if (len < 0)
348 goto out;
350 /* we mustn't use the parent's handle in the child */
351 xsh = xs_daemon_open();
353 xs_write(xsh, XBT_NULL, path, pid, len);
355 xs_daemon_close(xsh);
356 out:
357 free(path);
358 free(pid);
359 }
361 static int libxl_vfb_and_vkb_from_device_model_info(libxl_ctx *ctx,
362 libxl_device_model_info *info,
363 libxl_device_vfb *vfb,
364 libxl_device_vkb *vkb)
365 {
366 memset(vfb, 0x00, sizeof(libxl_device_vfb));
367 memset(vkb, 0x00, sizeof(libxl_device_vkb));
369 vfb->backend_domid = 0;
370 vfb->devid = 0;
371 vfb->vnc = info->vnc;
372 vfb->vnclisten = info->vnclisten;
373 vfb->vncdisplay = info->vncdisplay;
374 vfb->vncunused = info->vncunused;
375 vfb->vncpasswd = info->vncpasswd;
376 vfb->keymap = info->keymap;
377 vfb->sdl = info->sdl;
378 vfb->opengl = info->opengl;
380 vkb->backend_domid = 0;
381 vkb->devid = 0;
382 return 0;
383 }
385 static int libxl_write_dmargs(libxl_ctx *ctx, int domid, int guest_domid, char **args)
386 {
387 libxl__gc gc = LIBXL_INIT_GC(ctx);
388 int i;
389 char *vm_path;
390 char *dmargs, *path;
391 int dmargs_size;
392 struct xs_permissions roperm[2];
393 xs_transaction_t t;
395 roperm[0].id = 0;
396 roperm[0].perms = XS_PERM_NONE;
397 roperm[1].id = domid;
398 roperm[1].perms = XS_PERM_READ;
400 vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/vm", guest_domid));
402 i = 0;
403 dmargs_size = 0;
404 while (args[i] != NULL) {
405 dmargs_size = dmargs_size + strlen(args[i]) + 1;
406 i++;
407 }
408 dmargs_size++;
409 dmargs = (char *) malloc(dmargs_size);
410 i = 1;
411 dmargs[0] = '\0';
412 while (args[i] != NULL) {
413 if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) {
414 strcat(dmargs, " ");
415 strcat(dmargs, args[i]);
416 }
417 i++;
418 }
419 path = libxl__sprintf(&gc, "%s/image/dmargs", vm_path);
421 retry_transaction:
422 t = xs_transaction_start(ctx->xsh);
423 xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs));
424 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
425 xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm));
426 if (!xs_transaction_end(ctx->xsh, t, 0))
427 if (errno == EAGAIN)
428 goto retry_transaction;
429 free(dmargs);
430 libxl__free_all(&gc);
431 return 0;
432 }
434 static int libxl_create_stubdom(libxl_ctx *ctx,
435 libxl_device_model_info *info,
436 libxl_device_disk *disks, int num_disks,
437 libxl_device_nic *vifs, int num_vifs,
438 libxl_device_vfb *vfb,
439 libxl_device_vkb *vkb,
440 libxl__device_model_starting **starting_r)
441 {
442 libxl__gc gc = LIBXL_INIT_GC(ctx);
443 int i, num_console = STUBDOM_SPECIAL_CONSOLES, ret;
444 libxl_device_console *console;
445 libxl_domain_create_info c_info;
446 libxl_domain_build_info b_info;
447 libxl_domain_build_state state;
448 uint32_t domid;
449 char **args;
450 struct xs_permissions perm[2];
451 xs_transaction_t t;
452 libxl__device_model_starting *dm_starting = 0;
454 args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
455 if (!args) {
456 ret = ERROR_FAIL;
457 goto out;
458 }
460 memset(&c_info, 0x00, sizeof(libxl_domain_create_info));
461 c_info.hvm = 0;
462 c_info.name = libxl__sprintf(&gc, "%s-dm", libxl__domid_to_name(&gc, info->domid));
464 libxl_uuid_copy(&c_info.uuid, &info->uuid);
466 memset(&b_info, 0x00, sizeof(libxl_domain_build_info));
467 b_info.max_vcpus = 1;
468 b_info.max_memkb = 32 * 1024;
469 b_info.target_memkb = b_info.max_memkb;
470 b_info.kernel.path = libxl__abs_path(&gc, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path());
471 b_info.u.pv.cmdline = libxl__sprintf(&gc, " -d %d", info->domid);
472 b_info.u.pv.ramdisk.path = "";
473 b_info.u.pv.features = "";
474 b_info.hvm = 0;
476 ret = libxl__domain_make(ctx, &c_info, &domid);
477 if (ret)
478 goto out_free;
479 ret = libxl__domain_build(ctx, &b_info, domid, &state);
480 if (ret)
481 goto out_free;
483 libxl_write_dmargs(ctx, domid, info->domid, args);
484 libxl__xs_write(&gc, XBT_NULL,
485 libxl__sprintf(&gc, "%s/image/device-model-domid", libxl__xs_get_dompath(&gc, info->domid)),
486 "%d", domid);
487 libxl__xs_write(&gc, XBT_NULL,
488 libxl__sprintf(&gc, "%s/target", libxl__xs_get_dompath(&gc, domid)),
489 "%d", info->domid);
490 ret = xc_domain_set_target(ctx->xch, domid, info->domid);
491 if (ret<0) {
492 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting target domain %d -> %d", domid, info->domid);
493 ret = ERROR_FAIL;
494 goto out_free;
495 }
496 xs_set_target(ctx->xsh, domid, info->domid);
498 perm[0].id = domid;
499 perm[0].perms = XS_PERM_NONE;
500 perm[1].id = info->domid;
501 perm[1].perms = XS_PERM_READ;
502 retry_transaction:
503 t = xs_transaction_start(ctx->xsh);
504 xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid));
505 xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm));
506 xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs", domid));
507 xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm));
508 if (!xs_transaction_end(ctx->xsh, t, 0))
509 if (errno == EAGAIN)
510 goto retry_transaction;
512 for (i = 0; i < num_disks; i++) {
513 disks[i].domid = domid;
514 ret = libxl_device_disk_add(ctx, domid, &disks[i]);
515 if (ret)
516 goto out_free;
517 }
518 for (i = 0; i < num_vifs; i++) {
519 vifs[i].domid = domid;
520 ret = libxl_device_nic_add(ctx, domid, &vifs[i]);
521 if (ret)
522 goto out_free;
523 }
524 vfb->domid = domid;
525 ret = libxl_device_vfb_add(ctx, domid, vfb);
526 if (ret)
527 goto out_free;
528 vkb->domid = domid;
529 ret = libxl_device_vkb_add(ctx, domid, vkb);
530 if (ret)
531 goto out_free;
533 if (info->serial)
534 num_console++;
536 console = libxl__calloc(&gc, num_console, sizeof(libxl_device_console));
537 if (!console) {
538 ret = ERROR_NOMEM;
539 goto out_free;
540 }
542 for (i = 0; i < num_console; i++) {
543 console[i].devid = i;
544 console[i].consback = LIBXL_CONSBACK_IOEMU;
545 console[i].domid = domid;
546 /* STUBDOM_CONSOLE_LOGGING (console 0) is for minios logging
547 * STUBDOM_CONSOLE_SAVE (console 1) is for writing the save file
548 * STUBDOM_CONSOLE_RESTORE (console 2) is for reading the save file
549 */
550 switch (i) {
551 char *filename;
552 char *name;
553 case STUBDOM_CONSOLE_LOGGING:
554 name = libxl__sprintf(&gc, "qemu-dm-%s", libxl_domid_to_name(ctx, info->domid));
555 libxl_create_logfile(ctx, name, &filename);
556 console[i].output = libxl__sprintf(&gc, "file:%s", filename);
557 console[i].build_state = &state;
558 free(filename);
559 break;
560 case STUBDOM_CONSOLE_SAVE:
561 console[i].output = libxl__sprintf(&gc, "file:"SAVEFILE".%d", info->domid);
562 break;
563 case STUBDOM_CONSOLE_RESTORE:
564 if (info->saved_state)
565 console[i].output = libxl__sprintf(&gc, "pipe:%s", info->saved_state);
566 break;
567 default:
568 console[i].output = "pty";
569 break;
570 }
571 ret = libxl_device_console_add(ctx, domid, &console[i]);
572 if (ret)
573 goto out_free;
574 }
575 if (libxl__create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) {
576 ret = ERROR_FAIL;
577 goto out_free;
578 }
579 if (libxl__confirm_device_model_startup(ctx, dm_starting) < 0) {
580 ret = ERROR_FAIL;
581 goto out_free;
582 }
584 libxl_domain_unpause(ctx, domid);
586 if (starting_r) {
587 *starting_r = calloc(sizeof(libxl__device_model_starting), 1);
588 (*starting_r)->domid = info->domid;
589 (*starting_r)->dom_path = libxl__xs_get_dompath(&gc, info->domid);
590 (*starting_r)->for_spawn = NULL;
591 }
593 ret = 0;
595 out_free:
596 free(args);
597 out:
598 libxl__free_all(&gc);
599 return ret;
600 }
602 int libxl__create_device_model(libxl_ctx *ctx,
603 libxl_device_model_info *info,
604 libxl_device_disk *disks, int num_disks,
605 libxl_device_nic *vifs, int num_vifs,
606 libxl__device_model_starting **starting_r)
607 {
608 libxl__gc gc = LIBXL_INIT_GC(ctx);
609 char *path, *logfile;
610 int logfile_w, null;
611 int rc;
612 char **args;
613 libxl__device_model_starting buf_starting, *p;
614 xs_transaction_t t;
615 char *vm_path;
616 char **pass_stuff;
618 if (strstr(info->device_model, "stubdom-dm")) {
619 libxl_device_vfb vfb;
620 libxl_device_vkb vkb;
622 libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb);
623 rc = libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r);
624 goto out;
625 }
627 args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
628 if (!args) {
629 rc = ERROR_FAIL;
630 goto out;
631 }
633 path = libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid);
634 xs_mkdir(ctx->xsh, XBT_NULL, path);
635 libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/disable_pf", path), "%d", !info->xen_platform_pci);
637 libxl_create_logfile(ctx, libxl__sprintf(&gc, "qemu-dm-%s", info->dom_name), &logfile);
638 logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
639 free(logfile);
640 null = open("/dev/null", O_RDONLY);
642 if (starting_r) {
643 rc = ERROR_NOMEM;
644 *starting_r = calloc(sizeof(libxl__device_model_starting), 1);
645 if (!*starting_r)
646 goto out_close;
647 p = *starting_r;
648 p->for_spawn = calloc(sizeof(libxl__spawn_starting), 1);
649 } else {
650 p = &buf_starting;
651 p->for_spawn = NULL;
652 }
654 p->domid = info->domid;
655 p->dom_path = libxl__xs_get_dompath(&gc, info->domid);
656 if (!p->dom_path) {
657 rc = ERROR_FAIL;
658 goto out_close;
659 }
661 if (info->vncpasswd) {
662 retry_transaction:
663 /* Find uuid and the write the vnc password to xenstore for qemu. */
664 t = xs_transaction_start(ctx->xsh);
665 vm_path = libxl__xs_read(&gc,t,libxl__sprintf(&gc, "%s/vm", p->dom_path));
666 if (vm_path) {
667 /* Now write the vncpassword into it. */
668 pass_stuff = libxl__calloc(&gc, 3, sizeof(char *));
669 pass_stuff[0] = "vncpasswd";
670 pass_stuff[1] = info->vncpasswd;
671 libxl__xs_writev(&gc,t,vm_path,pass_stuff);
672 if (!xs_transaction_end(ctx->xsh, t, 0))
673 if (errno == EAGAIN)
674 goto retry_transaction;
675 }
676 }
678 rc = libxl__spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid);
679 if (rc < 0)
680 goto out_close;
681 if (!rc) { /* inner child */
682 libxl__exec(null, logfile_w, logfile_w,
683 libxl__abs_path(&gc, info->device_model, libxl_libexec_path()),
684 args);
685 }
687 rc = 0;
689 out_close:
690 close(null);
691 close(logfile_w);
692 free(args);
693 out:
694 libxl__free_all(&gc);
695 return rc;
696 }
698 static int detach_device_model(libxl_ctx *ctx,
699 libxl__device_model_starting *starting)
700 {
701 int rc;
702 rc = libxl__spawn_detach(ctx, starting->for_spawn);
703 if (starting->for_spawn)
704 free(starting->for_spawn);
705 free(starting);
706 return rc;
707 }
710 int libxl__confirm_device_model_startup(libxl_ctx *ctx,
711 libxl__device_model_starting *starting)
712 {
713 int problem = libxl__wait_for_device_model(ctx, starting->domid, "running", NULL, NULL);
714 int detach;
715 if ( !problem )
716 problem = libxl__spawn_check(ctx, starting->for_spawn);
717 detach = detach_device_model(ctx, starting);
718 return problem ? problem : detach;
719 }
721 int libxl__destroy_device_model(libxl_ctx *ctx, uint32_t domid)
722 {
723 libxl__gc gc = LIBXL_INIT_GC(ctx);
724 char *pid;
725 int ret;
727 pid = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid));
728 if (!pid) {
729 int stubdomid = libxl_get_stubdom_id(ctx, domid);
730 if (!stubdomid) {
731 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't find device model's pid");
732 ret = ERROR_INVAL;
733 goto out;
734 }
735 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device model is a stubdom, domid=%d\n", stubdomid);
736 ret = libxl_domain_destroy(ctx, stubdomid, 0);
737 if (ret)
738 goto out;
739 } else {
740 ret = kill(atoi(pid), SIGHUP);
741 if (ret < 0 && errno == ESRCH) {
742 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model already exited");
743 ret = 0;
744 } else if (ret == 0) {
745 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model signaled");
746 ret = 0;
747 } else {
748 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "failed to kill Device Model [%d]",
749 atoi(pid));
750 ret = ERROR_FAIL;
751 goto out;
752 }
753 }
754 xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", domid));
756 out:
757 libxl__free_all(&gc);
758 return ret;
759 }
761 static int libxl_build_xenpv_qemu_args(libxl__gc *gc,
762 uint32_t domid,
763 libxl_device_vfb *vfb,
764 libxl_device_model_info *info)
765 {
766 libxl_ctx *ctx = libxl__gc_owner(gc);
767 memset(info, 0x00, sizeof(libxl_device_model_info));
769 if (vfb != NULL) {
770 info->vnc = vfb->vnc;
771 if (vfb->vnclisten)
772 info->vnclisten = libxl__strdup(gc, vfb->vnclisten);
773 info->vncdisplay = vfb->vncdisplay;
774 info->vncunused = vfb->vncunused;
775 if (vfb->vncpasswd)
776 info->vncpasswd = vfb->vncpasswd;
777 if (vfb->keymap)
778 info->keymap = libxl__strdup(gc, vfb->keymap);
779 info->sdl = vfb->sdl;
780 info->opengl = vfb->opengl;
781 } else
782 info->nographic = 1;
783 info->domid = domid;
784 info->dom_name = libxl_domid_to_name(ctx, domid);
785 info->device_model = libxl__abs_path(gc, "qemu-dm", libxl_libexec_path());
786 info->type = XENPV;
787 return 0;
788 }
790 int libxl__need_xenpv_qemu(libxl_ctx *ctx,
791 int nr_consoles, libxl_device_console *consoles,
792 int nr_vfbs, libxl_device_vfb *vfbs,
793 int nr_disks, libxl_device_disk *disks)
794 {
795 int i, ret = 0;
796 libxl__gc gc = LIBXL_INIT_GC(ctx);
798 if (nr_consoles > 1) {
799 ret = 1;
800 goto out;
801 }
803 for (i = 0; i < nr_consoles; i++) {
804 if (consoles[i].consback == LIBXL_CONSBACK_IOEMU) {
805 ret = 1;
806 goto out;
807 }
808 }
810 if (nr_vfbs > 0) {
811 ret = 1;
812 goto out;
813 }
815 if (nr_disks > 0 && !libxl__blktap_enabled(&gc))
816 ret = 1;
818 out:
819 libxl__free_all(&gc);
820 return ret;
821 }
823 int libxl__create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb,
824 libxl__device_model_starting **starting_r)
825 {
826 libxl__gc gc = LIBXL_INIT_GC(ctx);
827 libxl_device_model_info info;
829 libxl_build_xenpv_qemu_args(&gc, domid, vfb, &info);
830 libxl__create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r);
831 libxl__free_all(&gc);
832 return 0;
833 }