1 /*
2 * qemu_namespace.c: QEMU domain namespace helpers
3 *
4 * Copyright (C) 2006-2020 Red Hat, Inc.
5 * Copyright (C) 2006 Daniel P. Berrange
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library 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 GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <http://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23
24 #ifdef __linux__
25 # include <sys/sysmacros.h>
26 #endif
27 #if defined(WITH_SYS_MOUNT_H)
28 # include <sys/mount.h>
29 #endif
30 #ifdef WITH_SELINUX
31 # include <selinux/selinux.h>
32 #endif
33
34 #include "qemu_namespace.h"
35 #include "qemu_domain.h"
36 #include "qemu_cgroup.h"
37 #include "qemu_security.h"
38 #include "qemu_hostdev.h"
39 #include "viralloc.h"
40 #include "virlog.h"
41 #include "virstring.h"
42 #include "virdevmapper.h"
43 #include "virglibutil.h"
44
45 #define VIR_FROM_THIS VIR_FROM_QEMU
46
47 VIR_LOG_INIT("qemu.qemu_domain");
48
49
50 VIR_ENUM_IMPL(qemuDomainNamespace,
51 QEMU_DOMAIN_NS_LAST,
52 "mount",
53 );
54
55
56 /**
57 * qemuDomainGetPreservedMountPath:
58 * @cfg: driver configuration data
59 * @vm: domain object
60 * @mountpoint: mount point path to convert
61 *
62 * For given @mountpoint return new path where the mount point
63 * should be moved temporarily whilst building the namespace.
64 *
65 * Returns: allocated string on success which the caller must free,
66 * NULL on failure.
67 */
68 static char *
qemuDomainGetPreservedMountPath(virQEMUDriverConfig * cfg,virDomainObj * vm,const char * mountpoint)69 qemuDomainGetPreservedMountPath(virQEMUDriverConfig *cfg,
70 virDomainObj *vm,
71 const char *mountpoint)
72 {
73 char *path = NULL;
74 char *tmp;
75 const char *suffix = mountpoint + strlen(QEMU_DEVPREFIX);
76 g_autofree char *domname = virDomainDefGetShortName(vm->def);
77 size_t off;
78
79 if (!domname)
80 return NULL;
81
82 if (STREQ(mountpoint, "/dev"))
83 suffix = "dev";
84
85 path = g_strdup_printf("%s/%s.%s", cfg->stateDir, domname, suffix);
86
87 /* Now consider that @mountpoint is "/dev/blah/blah2".
88 * @suffix then points to "blah/blah2". However, caller
89 * expects all the @paths to be the same depth. The
90 * caller doesn't always do `mkdir -p` but sometimes bare
91 * `touch`. Therefore fix all the suffixes. */
92 off = strlen(path) - strlen(suffix);
93
94 tmp = path + off;
95 while (*tmp) {
96 if (*tmp == '/')
97 *tmp = '.';
98 tmp++;
99 }
100
101 return path;
102 }
103
104
105 /**
106 * qemuDomainGetPreservedMounts:
107 *
108 * Process list of mounted filesystems and:
109 * a) save all FSs mounted under /dev to @devPath
110 * b) generate backup path for all the entries in a)
111 *
112 * Any of the return pointers can be NULL. Both arrays are NULL-terminated.
113 *
114 * Returns 0 on success, -1 otherwise (with error reported)
115 */
116 static int
qemuDomainGetPreservedMounts(virQEMUDriverConfig * cfg,virDomainObj * vm,char *** devPath,char *** devSavePath,size_t * ndevPath)117 qemuDomainGetPreservedMounts(virQEMUDriverConfig *cfg,
118 virDomainObj *vm,
119 char ***devPath,
120 char ***devSavePath,
121 size_t *ndevPath)
122 {
123 g_auto(GStrv) mounts = NULL;
124 size_t nmounts = 0;
125 g_auto(GStrv) paths = NULL;
126 g_auto(GStrv) savePaths = NULL;
127 size_t i;
128
129 if (ndevPath)
130 *ndevPath = 0;
131
132 if (virFileGetMountSubtree(QEMU_PROC_MOUNTS, "/dev", &mounts, &nmounts) < 0)
133 return -1;
134
135 if (nmounts == 0)
136 return 0;
137
138 /* There can be nested mount points. For instance
139 * /dev/shm/blah can be a mount point and /dev/shm too. It
140 * doesn't make much sense to return the former path because
141 * caller preserves the latter (and with that the former
142 * too). Therefore prune nested mount points.
143 * NB mounts[0] is "/dev". Should we start the outer loop
144 * from the beginning of the array all we'd be left with is
145 * just the first element. Think about it.
146 */
147 for (i = 1; i < nmounts; i++) {
148 size_t j = i + 1;
149
150 while (j < nmounts) {
151 char *c = STRSKIP(mounts[j], mounts[i]);
152
153 if (c && (*c == '/' || *c == '\0')) {
154 VIR_DEBUG("Dropping path %s because of %s", mounts[j], mounts[i]);
155 VIR_DELETE_ELEMENT(mounts, j, nmounts);
156 } else {
157 j++;
158 }
159 }
160 }
161
162 /* mounts may not be NULL-terminated at this point, but we convert it into
163 * 'paths' which is NULL-terminated */
164
165 paths = g_new0(char *, nmounts + 1);
166
167 for (i = 0; i < nmounts; i++)
168 paths[i] = g_steal_pointer(&mounts[i]);
169
170 if (devSavePath) {
171 savePaths = g_new0(char *, nmounts + 1);
172
173 for (i = 0; i < nmounts; i++) {
174 if (!(savePaths[i] = qemuDomainGetPreservedMountPath(cfg, vm, paths[i])))
175 return -1;
176 }
177 }
178
179 if (devPath)
180 *devPath = g_steal_pointer(&paths);
181
182 if (devSavePath)
183 *devSavePath = g_steal_pointer(&savePaths);
184
185 if (ndevPath)
186 *ndevPath = nmounts;
187
188 return 0;
189 }
190
191
192 static int
qemuDomainPopulateDevices(virQEMUDriverConfig * cfg,GSList ** paths)193 qemuDomainPopulateDevices(virQEMUDriverConfig *cfg,
194 GSList **paths)
195 {
196 const char *const *devices = (const char *const *) cfg->cgroupDeviceACL;
197 size_t i;
198
199 if (!devices)
200 devices = defaultDeviceACL;
201
202 for (i = 0; devices[i]; i++) {
203 *paths = g_slist_prepend(*paths, g_strdup(devices[i]));
204 }
205
206 return 0;
207 }
208
209
210 static int
qemuDomainSetupDev(virSecurityManager * mgr,virDomainObj * vm,const char * path)211 qemuDomainSetupDev(virSecurityManager *mgr,
212 virDomainObj *vm,
213 const char *path)
214 {
215 g_autofree char *mount_options = NULL;
216 g_autofree char *opts = NULL;
217
218 VIR_DEBUG("Setting up /dev/ for domain %s", vm->def->name);
219
220 mount_options = qemuSecurityGetMountOptions(mgr, vm->def);
221
222 if (!mount_options)
223 mount_options = g_strdup("");
224
225 /*
226 * tmpfs is limited to 64kb, since we only have device nodes in there
227 * and don't want to DOS the entire OS RAM usage
228 */
229 opts = g_strdup_printf("mode=755,size=65536%s", mount_options);
230
231 if (virFileSetupDev(path, opts) < 0)
232 return -1;
233
234 return 0;
235 }
236
237
238 static int
qemuDomainSetupDisk(virStorageSource * src,GSList ** paths)239 qemuDomainSetupDisk(virStorageSource *src,
240 GSList **paths)
241 {
242 virStorageSource *next;
243 bool hasNVMe = false;
244
245 for (next = src; virStorageSourceIsBacking(next); next = next->backingStore) {
246 g_autofree char *tmpPath = NULL;
247
248 if (next->type == VIR_STORAGE_TYPE_NVME) {
249 hasNVMe = true;
250
251 if (!(tmpPath = virPCIDeviceAddressGetIOMMUGroupDev(&next->nvme->pciAddr)))
252 return -1;
253 } else {
254 GSList *targetPaths;
255
256 if (virStorageSourceIsEmpty(next) ||
257 !virStorageSourceIsLocalStorage(next)) {
258 /* Not creating device. Just continue. */
259 continue;
260 }
261
262 tmpPath = g_strdup(next->path);
263
264 if (virDevMapperGetTargets(next->path, &targetPaths) < 0 &&
265 errno != ENOSYS) {
266 virReportSystemError(errno,
267 _("Unable to get devmapper targets for %s"),
268 next->path);
269 return -1;
270 }
271
272 if (targetPaths)
273 *paths = g_slist_concat(g_slist_reverse(targetPaths), *paths);
274 }
275
276 *paths = g_slist_prepend(*paths, g_steal_pointer(&tmpPath));
277 }
278
279 /* qemu-pr-helper might require access to /dev/mapper/control. */
280 if (src->pr)
281 *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEVICE_MAPPER_CONTROL_PATH));
282
283 if (hasNVMe)
284 *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_VFIO));
285
286 return 0;
287 }
288
289
290 static int
qemuDomainSetupAllDisks(virDomainObj * vm,GSList ** paths)291 qemuDomainSetupAllDisks(virDomainObj *vm,
292 GSList **paths)
293 {
294 size_t i;
295
296 VIR_DEBUG("Setting up disks");
297
298 for (i = 0; i < vm->def->ndisks; i++) {
299 if (qemuDomainSetupDisk(vm->def->disks[i]->src,
300 paths) < 0)
301 return -1;
302 }
303
304 VIR_DEBUG("Setup all disks");
305 return 0;
306 }
307
308
309 static int
qemuDomainSetupHostdev(virDomainObj * vm,virDomainHostdevDef * hostdev,bool hotplug,GSList ** paths)310 qemuDomainSetupHostdev(virDomainObj *vm,
311 virDomainHostdevDef *hostdev,
312 bool hotplug,
313 GSList **paths)
314 {
315 g_autofree char *path = NULL;
316
317 if (qemuDomainGetHostdevPath(hostdev, &path, NULL) < 0)
318 return -1;
319
320 if (path)
321 *paths = g_slist_prepend(*paths, g_steal_pointer(&path));
322
323 if (qemuHostdevNeedsVFIO(hostdev) &&
324 (!hotplug || !qemuDomainNeedsVFIO(vm->def)))
325 *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_VFIO));
326
327 return 0;
328 }
329
330
331 static int
qemuDomainSetupAllHostdevs(virDomainObj * vm,GSList ** paths)332 qemuDomainSetupAllHostdevs(virDomainObj *vm,
333 GSList **paths)
334 {
335 size_t i;
336
337 VIR_DEBUG("Setting up hostdevs");
338 for (i = 0; i < vm->def->nhostdevs; i++) {
339 if (qemuDomainSetupHostdev(vm,
340 vm->def->hostdevs[i],
341 false,
342 paths) < 0)
343 return -1;
344 }
345 VIR_DEBUG("Setup all hostdevs");
346 return 0;
347 }
348
349
350 static int
qemuDomainSetupMemory(virDomainMemoryDef * mem,GSList ** paths)351 qemuDomainSetupMemory(virDomainMemoryDef *mem,
352 GSList **paths)
353 {
354 if (mem->model != VIR_DOMAIN_MEMORY_MODEL_NVDIMM &&
355 mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM)
356 return 0;
357
358 *paths = g_slist_prepend(*paths, g_strdup(mem->nvdimmPath));
359
360 return 0;
361 }
362
363
364 static int
qemuDomainSetupAllMemories(virDomainObj * vm,GSList ** paths)365 qemuDomainSetupAllMemories(virDomainObj *vm,
366 GSList **paths)
367 {
368 size_t i;
369
370 VIR_DEBUG("Setting up memories");
371 for (i = 0; i < vm->def->nmems; i++) {
372 if (qemuDomainSetupMemory(vm->def->mems[i],
373 paths) < 0)
374 return -1;
375 }
376 VIR_DEBUG("Setup all memories");
377 return 0;
378 }
379
380
381 static int
qemuDomainSetupChardev(virDomainDef * def G_GNUC_UNUSED,virDomainChrDef * dev,void * opaque)382 qemuDomainSetupChardev(virDomainDef *def G_GNUC_UNUSED,
383 virDomainChrDef *dev,
384 void *opaque)
385 {
386 GSList **paths = opaque;
387 const char *path = NULL;
388
389 if (!(path = virDomainChrSourceDefGetPath(dev->source)))
390 return 0;
391
392 /* Socket created by qemu. It doesn't exist upfront. */
393 if (dev->source->type == VIR_DOMAIN_CHR_TYPE_UNIX &&
394 dev->source->data.nix.listen)
395 return 0;
396
397 *paths = g_slist_prepend(*paths, g_strdup(path));
398 return 0;
399 }
400
401
402 static int
qemuDomainSetupAllChardevs(virDomainObj * vm,GSList ** paths)403 qemuDomainSetupAllChardevs(virDomainObj *vm,
404 GSList **paths)
405 {
406 VIR_DEBUG("Setting up chardevs");
407
408 if (virDomainChrDefForeach(vm->def,
409 true,
410 qemuDomainSetupChardev,
411 paths) < 0)
412 return -1;
413
414 VIR_DEBUG("Setup all chardevs");
415 return 0;
416 }
417
418
419 static int
qemuDomainSetupTPM(virDomainTPMDef * dev,GSList ** paths)420 qemuDomainSetupTPM(virDomainTPMDef *dev,
421 GSList **paths)
422 {
423 switch (dev->type) {
424 case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
425 *paths = g_slist_prepend(*paths, g_strdup(dev->data.passthrough.source->data.file.path));
426 break;
427
428 case VIR_DOMAIN_TPM_TYPE_EMULATOR:
429 case VIR_DOMAIN_TPM_TYPE_LAST:
430 /* nada */
431 break;
432 }
433
434 return 0;
435 }
436
437
438 static int
qemuDomainSetupAllTPMs(virDomainObj * vm,GSList ** paths)439 qemuDomainSetupAllTPMs(virDomainObj *vm,
440 GSList **paths)
441 {
442 size_t i;
443
444 VIR_DEBUG("Setting up TPMs");
445
446 for (i = 0; i < vm->def->ntpms; i++) {
447 if (qemuDomainSetupTPM(vm->def->tpms[i], paths) < 0)
448 return -1;
449 }
450
451 VIR_DEBUG("Setup all TPMs");
452 return 0;
453 }
454
455
456 static int
qemuDomainSetupGraphics(virDomainGraphicsDef * gfx,GSList ** paths)457 qemuDomainSetupGraphics(virDomainGraphicsDef *gfx,
458 GSList **paths)
459 {
460 const char *rendernode = virDomainGraphicsGetRenderNode(gfx);
461
462 if (!rendernode)
463 return 0;
464
465 *paths = g_slist_prepend(*paths, g_strdup(rendernode));
466 return 0;
467 }
468
469
470 static int
qemuDomainSetupAllGraphics(virDomainObj * vm,GSList ** paths)471 qemuDomainSetupAllGraphics(virDomainObj *vm,
472 GSList **paths)
473 {
474 size_t i;
475
476 VIR_DEBUG("Setting up graphics");
477 for (i = 0; i < vm->def->ngraphics; i++) {
478 if (qemuDomainSetupGraphics(vm->def->graphics[i],
479 paths) < 0)
480 return -1;
481 }
482
483 VIR_DEBUG("Setup all graphics");
484 return 0;
485 }
486
487
488 static int
qemuDomainSetupInput(virDomainInputDef * input,GSList ** paths)489 qemuDomainSetupInput(virDomainInputDef *input,
490 GSList **paths)
491 {
492 const char *path = virDomainInputDefGetPath(input);
493
494 if (!path)
495 return 0;
496
497 *paths = g_slist_prepend(*paths, g_strdup(path));
498
499 return 0;
500 }
501
502
503 static int
qemuDomainSetupAllInputs(virDomainObj * vm,GSList ** paths)504 qemuDomainSetupAllInputs(virDomainObj *vm,
505 GSList **paths)
506 {
507 size_t i;
508
509 VIR_DEBUG("Setting up inputs");
510 for (i = 0; i < vm->def->ninputs; i++) {
511 if (qemuDomainSetupInput(vm->def->inputs[i],
512 paths) < 0)
513 return -1;
514 }
515 VIR_DEBUG("Setup all inputs");
516 return 0;
517 }
518
519
520 static int
qemuDomainSetupRNG(virDomainRNGDef * rng,GSList ** paths)521 qemuDomainSetupRNG(virDomainRNGDef *rng,
522 GSList **paths)
523 {
524 switch ((virDomainRNGBackend) rng->backend) {
525 case VIR_DOMAIN_RNG_BACKEND_RANDOM:
526 *paths = g_slist_prepend(*paths, g_strdup(rng->source.file));
527 break;
528
529 case VIR_DOMAIN_RNG_BACKEND_EGD:
530 case VIR_DOMAIN_RNG_BACKEND_BUILTIN:
531 case VIR_DOMAIN_RNG_BACKEND_LAST:
532 /* nada */
533 break;
534 }
535
536 return 0;
537 }
538
539
540 static int
qemuDomainSetupAllRNGs(virDomainObj * vm,GSList ** paths)541 qemuDomainSetupAllRNGs(virDomainObj *vm,
542 GSList **paths)
543 {
544 size_t i;
545
546 VIR_DEBUG("Setting up RNGs");
547 for (i = 0; i < vm->def->nrngs; i++) {
548 if (qemuDomainSetupRNG(vm->def->rngs[i],
549 paths) < 0)
550 return -1;
551 }
552
553 VIR_DEBUG("Setup all RNGs");
554 return 0;
555 }
556
557
558 static int
qemuDomainSetupLoader(virDomainObj * vm,GSList ** paths)559 qemuDomainSetupLoader(virDomainObj *vm,
560 GSList **paths)
561 {
562 virDomainLoaderDef *loader = vm->def->os.loader;
563
564 VIR_DEBUG("Setting up loader");
565
566 if (loader) {
567 switch ((virDomainLoader) loader->type) {
568 case VIR_DOMAIN_LOADER_TYPE_ROM:
569 *paths = g_slist_prepend(*paths, g_strdup(loader->path));
570 break;
571
572 case VIR_DOMAIN_LOADER_TYPE_PFLASH:
573 *paths = g_slist_prepend(*paths, g_strdup(loader->path));
574
575 if (loader->nvram)
576 *paths = g_slist_prepend(*paths, g_strdup(loader->nvram));
577 break;
578
579 case VIR_DOMAIN_LOADER_TYPE_NONE:
580 case VIR_DOMAIN_LOADER_TYPE_LAST:
581 break;
582 }
583 }
584
585 VIR_DEBUG("Setup loader");
586 return 0;
587 }
588
589
590 static int
qemuDomainSetupLaunchSecurity(virDomainObj * vm,GSList ** paths)591 qemuDomainSetupLaunchSecurity(virDomainObj *vm,
592 GSList **paths)
593 {
594 virDomainSecDef *sec = vm->def->sec;
595
596 if (!sec)
597 return 0;
598
599 switch ((virDomainLaunchSecurity) sec->sectype) {
600 case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
601 VIR_DEBUG("Setting up launch security for SEV");
602
603 *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_SEV));
604
605 VIR_DEBUG("Set up launch security for SEV");
606 break;
607 case VIR_DOMAIN_LAUNCH_SECURITY_PV:
608 break;
609 case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
610 case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
611 virReportEnumRangeError(virDomainLaunchSecurity, sec->sectype);
612 return -1;
613 }
614
615 return 0;
616 }
617
618
619 static int
620 qemuNamespaceMknodPaths(virDomainObj *vm,
621 GSList *paths,
622 bool *created);
623
624
625 int
qemuDomainBuildNamespace(virQEMUDriverConfig * cfg,virDomainObj * vm)626 qemuDomainBuildNamespace(virQEMUDriverConfig *cfg,
627 virDomainObj *vm)
628 {
629 g_autoptr(virGSListString) paths = NULL;
630
631 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT)) {
632 VIR_DEBUG("namespaces disabled for domain %s", vm->def->name);
633 return 0;
634 }
635
636 if (qemuDomainPopulateDevices(cfg, &paths) < 0)
637 return -1;
638
639 if (qemuDomainSetupAllDisks(vm, &paths) < 0)
640 return -1;
641
642 if (qemuDomainSetupAllHostdevs(vm, &paths) < 0)
643 return -1;
644
645 if (qemuDomainSetupAllMemories(vm, &paths) < 0)
646 return -1;
647
648 if (qemuDomainSetupAllChardevs(vm, &paths) < 0)
649 return -1;
650
651 if (qemuDomainSetupAllTPMs(vm, &paths) < 0)
652 return -1;
653
654 if (qemuDomainSetupAllGraphics(vm, &paths) < 0)
655 return -1;
656
657 if (qemuDomainSetupAllInputs(vm, &paths) < 0)
658 return -1;
659
660 if (qemuDomainSetupAllRNGs(vm, &paths) < 0)
661 return -1;
662
663 if (qemuDomainSetupLoader(vm, &paths) < 0)
664 return -1;
665
666 if (qemuDomainSetupLaunchSecurity(vm, &paths) < 0)
667 return -1;
668
669 if (qemuNamespaceMknodPaths(vm, paths, NULL) < 0)
670 return -1;
671
672 return 0;
673 }
674
675
676 int
qemuDomainUnshareNamespace(virQEMUDriverConfig * cfg,virSecurityManager * mgr,virDomainObj * vm)677 qemuDomainUnshareNamespace(virQEMUDriverConfig *cfg,
678 virSecurityManager *mgr,
679 virDomainObj *vm)
680 {
681 const char *devPath = NULL;
682 g_auto(GStrv) devMountsPath = NULL;
683 g_auto(GStrv) devMountsSavePath = NULL;
684 size_t ndevMountsPath = 0, i;
685 int ret = -1;
686
687 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT)) {
688 ret = 0;
689 goto cleanup;
690 }
691
692 if (qemuDomainGetPreservedMounts(cfg, vm,
693 &devMountsPath, &devMountsSavePath,
694 &ndevMountsPath) < 0)
695 goto cleanup;
696
697 for (i = 0; i < ndevMountsPath; i++) {
698 if (STREQ(devMountsPath[i], "/dev")) {
699 devPath = devMountsSavePath[i];
700 break;
701 }
702 }
703
704 if (!devPath) {
705 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
706 _("Unable to find any /dev mount"));
707 goto cleanup;
708 }
709
710 if (virProcessSetupPrivateMountNS() < 0)
711 goto cleanup;
712
713 if (qemuDomainSetupDev(mgr, vm, devPath) < 0)
714 goto cleanup;
715
716 /* Save some mount points because we want to share them with the host */
717 for (i = 0; i < ndevMountsPath; i++) {
718 struct stat sb;
719
720 if (devMountsSavePath[i] == devPath)
721 continue;
722
723 if (stat(devMountsPath[i], &sb) < 0) {
724 virReportSystemError(errno,
725 _("Unable to stat: %s"),
726 devMountsPath[i]);
727 goto cleanup;
728 }
729
730 /* At this point, devMountsPath is either:
731 * a file (regular or special), or
732 * a directory. */
733 if ((S_ISDIR(sb.st_mode) && g_mkdir_with_parents(devMountsSavePath[i], 0777) < 0) ||
734 (!S_ISDIR(sb.st_mode) && virFileTouch(devMountsSavePath[i], sb.st_mode) < 0)) {
735 virReportSystemError(errno,
736 _("Failed to create %s"),
737 devMountsSavePath[i]);
738 goto cleanup;
739 }
740
741 if (virFileMoveMount(devMountsPath[i], devMountsSavePath[i]) < 0)
742 goto cleanup;
743 }
744
745 if (virFileMoveMount(devPath, "/dev") < 0)
746 goto cleanup;
747
748 for (i = 0; i < ndevMountsPath; i++) {
749 struct stat sb;
750
751 if (devMountsSavePath[i] == devPath)
752 continue;
753
754 if (stat(devMountsSavePath[i], &sb) < 0) {
755 virReportSystemError(errno,
756 _("Unable to stat: %s"),
757 devMountsSavePath[i]);
758 goto cleanup;
759 }
760
761 if (S_ISDIR(sb.st_mode)) {
762 if (g_mkdir_with_parents(devMountsPath[i], 0777) < 0) {
763 virReportSystemError(errno, _("Cannot create %s"),
764 devMountsPath[i]);
765 goto cleanup;
766 }
767 } else {
768 if (virFileMakeParentPath(devMountsPath[i]) < 0 ||
769 virFileTouch(devMountsPath[i], sb.st_mode) < 0) {
770 virReportSystemError(errno, _("Cannot create %s"),
771 devMountsPath[i]);
772 goto cleanup;
773 }
774 }
775
776 if (virFileMoveMount(devMountsSavePath[i], devMountsPath[i]) < 0)
777 goto cleanup;
778 }
779
780 ret = 0;
781 cleanup:
782 for (i = 0; i < ndevMountsPath; i++) {
783 #if defined(__linux__)
784 umount(devMountsSavePath[i]);
785 #endif /* defined(__linux__) */
786 /* The path can be either a regular file or a dir. */
787 if (virFileIsDir(devMountsSavePath[i]))
788 virFileDeleteTree(devMountsSavePath[i]);
789 else
790 unlink(devMountsSavePath[i]);
791 }
792 return ret;
793 }
794
795
796 bool
qemuDomainNamespaceEnabled(virDomainObj * vm,qemuDomainNamespace ns)797 qemuDomainNamespaceEnabled(virDomainObj *vm,
798 qemuDomainNamespace ns)
799 {
800 qemuDomainObjPrivate *priv = vm->privateData;
801
802 return priv->namespaces &&
803 virBitmapIsBitSet(priv->namespaces, ns);
804 }
805
806
807 int
qemuDomainEnableNamespace(virDomainObj * vm,qemuDomainNamespace ns)808 qemuDomainEnableNamespace(virDomainObj *vm,
809 qemuDomainNamespace ns)
810 {
811 qemuDomainObjPrivate *priv = vm->privateData;
812
813 if (!priv->namespaces)
814 priv->namespaces = virBitmapNew(QEMU_DOMAIN_NS_LAST);
815
816 if (virBitmapSetBit(priv->namespaces, ns) < 0) {
817 virReportError(VIR_ERR_INTERNAL_ERROR,
818 _("Unable to enable namespace: %s"),
819 qemuDomainNamespaceTypeToString(ns));
820 return -1;
821 }
822
823 return 0;
824 }
825
826
827 static void
qemuDomainDisableNamespace(virDomainObj * vm,qemuDomainNamespace ns)828 qemuDomainDisableNamespace(virDomainObj *vm,
829 qemuDomainNamespace ns)
830 {
831 qemuDomainObjPrivate *priv = vm->privateData;
832
833 if (priv->namespaces) {
834 ignore_value(virBitmapClearBit(priv->namespaces, ns));
835 if (virBitmapIsAllClear(priv->namespaces)) {
836 virBitmapFree(priv->namespaces);
837 priv->namespaces = NULL;
838 }
839 }
840 }
841
842
843 void
qemuDomainDestroyNamespace(virQEMUDriver * driver G_GNUC_UNUSED,virDomainObj * vm)844 qemuDomainDestroyNamespace(virQEMUDriver *driver G_GNUC_UNUSED,
845 virDomainObj *vm)
846 {
847 if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
848 qemuDomainDisableNamespace(vm, QEMU_DOMAIN_NS_MOUNT);
849 }
850
851
852 bool
qemuDomainNamespaceAvailable(qemuDomainNamespace ns G_GNUC_UNUSED)853 qemuDomainNamespaceAvailable(qemuDomainNamespace ns G_GNUC_UNUSED)
854 {
855 #if !defined(__linux__)
856 /* Namespaces are Linux specific. */
857 return false;
858
859 #else /* defined(__linux__) */
860
861 switch (ns) {
862 case QEMU_DOMAIN_NS_MOUNT:
863 # if !defined(WITH_LIBACL) || !defined(WITH_SELINUX)
864 /* We can't create the exact copy of paths if either of
865 * these is not available. */
866 return false;
867 # else
868 if (virProcessNamespaceAvailable(VIR_PROCESS_NAMESPACE_MNT) < 0)
869 return false;
870 # endif
871 break;
872 case QEMU_DOMAIN_NS_LAST:
873 break;
874 }
875
876 return true;
877 #endif /* defined(__linux__) */
878 }
879
880
881 typedef struct _qemuNamespaceMknodItem qemuNamespaceMknodItem;
882 struct _qemuNamespaceMknodItem {
883 char *file;
884 char *target;
885 bool bindmounted;
886 GStatBuf sb;
887 void *acl;
888 char *tcon;
889 };
890
891 typedef struct _qemuNamespaceMknodData qemuNamespaceMknodData;
892 struct _qemuNamespaceMknodData {
893 virQEMUDriver *driver;
894 virDomainObj *vm;
895 qemuNamespaceMknodItem *items;
896 size_t nitems;
897 };
898
899
900 static void
qemuNamespaceMknodItemClear(qemuNamespaceMknodItem * item)901 qemuNamespaceMknodItemClear(qemuNamespaceMknodItem *item)
902 {
903 VIR_FREE(item->file);
904 VIR_FREE(item->target);
905 virFileFreeACLs(&item->acl);
906 #ifdef WITH_SELINUX
907 freecon(item->tcon);
908 #endif
909 }
910
911
912 G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(qemuNamespaceMknodItem, qemuNamespaceMknodItemClear);
913
914 static void
qemuNamespaceMknodDataClear(qemuNamespaceMknodData * data)915 qemuNamespaceMknodDataClear(qemuNamespaceMknodData *data)
916 {
917 size_t i;
918
919 for (i = 0; i < data->nitems; i++) {
920 qemuNamespaceMknodItem *item = &data->items[i];
921
922 qemuNamespaceMknodItemClear(item);
923 }
924
925 VIR_FREE(data->items);
926 }
927
928
929 /* Our way of creating devices is highly linux specific */
930 #if defined(__linux__)
931 static int
qemuNamespaceMknodOne(qemuNamespaceMknodItem * data)932 qemuNamespaceMknodOne(qemuNamespaceMknodItem *data)
933 {
934 int ret = -1;
935 bool delDevice = false;
936 bool isLink = S_ISLNK(data->sb.st_mode);
937 bool isDev = S_ISCHR(data->sb.st_mode) || S_ISBLK(data->sb.st_mode);
938 bool isReg = S_ISREG(data->sb.st_mode) || S_ISFIFO(data->sb.st_mode) || S_ISSOCK(data->sb.st_mode);
939 bool isDir = S_ISDIR(data->sb.st_mode);
940 bool exists = false;
941
942 if (virFileExists(data->file))
943 exists = true;
944
945 if (virFileMakeParentPath(data->file) < 0) {
946 virReportSystemError(errno,
947 _("Unable to create %s"), data->file);
948 goto cleanup;
949 }
950
951 if (isLink) {
952 VIR_DEBUG("Creating symlink %s -> %s", data->file, data->target);
953
954 /* First, unlink the symlink target. Symlinks change and
955 * therefore we have no guarantees that pre-existing
956 * symlink is still valid. */
957 if (unlink(data->file) < 0 &&
958 errno != ENOENT) {
959 virReportSystemError(errno,
960 _("Unable to remove symlink %s"),
961 data->file);
962 goto cleanup;
963 }
964
965 if (symlink(data->target, data->file) < 0) {
966 virReportSystemError(errno,
967 _("Unable to create symlink %s (pointing to %s)"),
968 data->file, data->target);
969 goto cleanup;
970 } else {
971 delDevice = true;
972 }
973 } else if (isDev) {
974 VIR_DEBUG("Creating dev %s (%d,%d)",
975 data->file, major(data->sb.st_rdev), minor(data->sb.st_rdev));
976 unlink(data->file);
977 if (mknod(data->file, data->sb.st_mode, data->sb.st_rdev) < 0) {
978 virReportSystemError(errno,
979 _("Unable to create device %s"),
980 data->file);
981 goto cleanup;
982 } else {
983 delDevice = true;
984 }
985 } else if (isReg || isDir) {
986 /* We are not cleaning up disks on virDomainDetachDevice
987 * because disk might be still in use by different disk
988 * as its backing chain. This might however clash here.
989 * Therefore do the cleanup here. */
990 if (umount(data->file) < 0 &&
991 errno != ENOENT && errno != EINVAL) {
992 virReportSystemError(errno,
993 _("Unable to umount %s"),
994 data->file);
995 goto cleanup;
996 }
997 if ((isReg && virFileTouch(data->file, data->sb.st_mode) < 0) ||
998 (isDir && g_mkdir_with_parents(data->file, data->sb.st_mode) < 0))
999 goto cleanup;
1000 delDevice = true;
1001 /* Just create the file here so that code below sets
1002 * proper owner and mode. Move the mount only after that. */
1003 } else {
1004 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
1005 _("unsupported device type %s 0%o"),
1006 data->file, data->sb.st_mode);
1007 goto cleanup;
1008 }
1009
1010 if (lchown(data->file, data->sb.st_uid, data->sb.st_gid) < 0) {
1011 virReportSystemError(errno,
1012 _("Failed to chown device %s"),
1013 data->file);
1014 goto cleanup;
1015 }
1016
1017 /* Symlinks don't have mode */
1018 if (!isLink &&
1019 chmod(data->file, data->sb.st_mode) < 0) {
1020 virReportSystemError(errno,
1021 _("Failed to set permissions for device %s"),
1022 data->file);
1023 goto cleanup;
1024 }
1025
1026 /* Symlinks don't have ACLs. */
1027 if (!isLink &&
1028 virFileSetACLs(data->file, data->acl) < 0 &&
1029 errno != ENOTSUP) {
1030 virReportSystemError(errno,
1031 _("Unable to set ACLs on %s"), data->file);
1032 goto cleanup;
1033 }
1034
1035 # ifdef WITH_SELINUX
1036 if (data->tcon &&
1037 lsetfilecon_raw(data->file, (const char *)data->tcon) < 0) {
1038 VIR_WARNINGS_NO_WLOGICALOP_EQUAL_EXPR
1039 if (errno != EOPNOTSUPP && errno != ENOTSUP) {
1040 VIR_WARNINGS_RESET
1041 virReportSystemError(errno,
1042 _("Unable to set SELinux label on %s"),
1043 data->file);
1044 goto cleanup;
1045 }
1046 }
1047 # endif
1048
1049 /* Finish mount process started earlier. */
1050 if ((isReg || isDir) &&
1051 virFileMoveMount(data->target, data->file) < 0)
1052 goto cleanup;
1053
1054 ret = exists;
1055 cleanup:
1056 if (ret < 0 && delDevice) {
1057 if (isDir)
1058 virFileDeleteTree(data->file);
1059 else
1060 unlink(data->file);
1061 }
1062 return ret;
1063 }
1064
1065
1066 static bool
qemuNamespaceMknodItemNeedsBindMount(mode_t st_mode)1067 qemuNamespaceMknodItemNeedsBindMount(mode_t st_mode)
1068 {
1069 /* A block device S_ISBLK() or a chardev S_ISCHR() is intentionally not
1070 * handled. We want to mknod() it instead of passing in through bind
1071 * mounting. */
1072 return S_ISREG(st_mode) || S_ISFIFO(st_mode) ||
1073 S_ISSOCK(st_mode) || S_ISDIR(st_mode);
1074 }
1075
1076
1077 static int
qemuNamespaceMknodHelper(pid_t pid G_GNUC_UNUSED,void * opaque)1078 qemuNamespaceMknodHelper(pid_t pid G_GNUC_UNUSED,
1079 void *opaque)
1080 {
1081 qemuNamespaceMknodData *data = opaque;
1082 size_t i;
1083 int ret = -1;
1084 bool exists = false;
1085
1086 qemuSecurityPostFork(data->driver->securityManager);
1087
1088 for (i = 0; i < data->nitems; i++) {
1089 int rc = 0;
1090
1091 if ((rc = qemuNamespaceMknodOne(&data->items[i])) < 0)
1092 goto cleanup;
1093
1094 if (rc > 0)
1095 exists = true;
1096 }
1097
1098 ret = exists;
1099 cleanup:
1100 qemuNamespaceMknodDataClear(data);
1101 return ret;
1102 }
1103
1104
1105 static int
qemuNamespaceMknodItemInit(qemuNamespaceMknodItem * item,virQEMUDriverConfig * cfg,virDomainObj * vm,const char * file)1106 qemuNamespaceMknodItemInit(qemuNamespaceMknodItem *item,
1107 virQEMUDriverConfig *cfg,
1108 virDomainObj *vm,
1109 const char *file)
1110 {
1111 g_autofree char *target = NULL;
1112 bool isLink;
1113 bool needsBindMount;
1114
1115 item->file = g_strdup(file);
1116
1117 if (g_lstat(file, &item->sb) < 0) {
1118 if (errno == ENOENT)
1119 return -2;
1120
1121 virReportSystemError(errno,
1122 _("Unable to access %s"), file);
1123 return -1;
1124 }
1125
1126 isLink = S_ISLNK(item->sb.st_mode);
1127 needsBindMount = qemuNamespaceMknodItemNeedsBindMount(item->sb.st_mode);
1128
1129 if (needsBindMount && STRPREFIX(file, QEMU_DEVPREFIX)) {
1130 if (!(target = qemuDomainGetPreservedMountPath(cfg, vm, file)))
1131 return -1;
1132
1133 item->target = g_steal_pointer(&target);
1134 } else if (isLink) {
1135 g_autoptr(GError) gerr = NULL;
1136
1137 if (!(target = g_file_read_link(file, &gerr))) {
1138 virReportError(VIR_ERR_SYSTEM_ERROR,
1139 _("failed to resolve symlink %s: %s"), file, gerr->message);
1140 return -1;
1141 }
1142
1143 if (!g_path_is_absolute(target)) {
1144 g_autofree char *fileTmp = g_strdup(file);
1145 char *c = NULL;
1146 char *tmp = NULL;
1147
1148 if ((c = strrchr(fileTmp, '/')))
1149 *(c + 1) = '\0';
1150
1151 tmp = g_strdup_printf("%s%s", fileTmp, target);
1152 VIR_FREE(target);
1153 target = g_steal_pointer(&tmp);
1154 }
1155
1156 item->target = g_steal_pointer(&target);
1157 }
1158
1159 /* Symlinks don't have ACLs. */
1160 if (!isLink &&
1161 virFileGetACLs(file, &item->acl) < 0 &&
1162 errno != ENOTSUP) {
1163 virReportSystemError(errno,
1164 _("Unable to get ACLs on %s"), file);
1165 return -1;
1166 }
1167
1168 # ifdef WITH_SELINUX
1169 if (lgetfilecon_raw(file, &item->tcon) < 0 &&
1170 (errno != ENOTSUP && errno != ENODATA)) {
1171 virReportSystemError(errno,
1172 _("Unable to get SELinux label from %s"), file);
1173 return -1;
1174 }
1175 # endif
1176
1177 return 0;
1178 }
1179
1180
1181 static int
qemuNamespacePrepareOneItem(qemuNamespaceMknodData * data,virQEMUDriverConfig * cfg,virDomainObj * vm,const char * file,GStrv devMountsPath)1182 qemuNamespacePrepareOneItem(qemuNamespaceMknodData *data,
1183 virQEMUDriverConfig *cfg,
1184 virDomainObj *vm,
1185 const char *file,
1186 GStrv devMountsPath)
1187 {
1188 long ttl = sysconf(_SC_SYMLOOP_MAX);
1189 g_autofree char *next = g_strdup(file);
1190
1191 while (1) {
1192 g_auto(qemuNamespaceMknodItem) item = { 0 };
1193 bool isLink;
1194 int rc;
1195
1196 rc = qemuNamespaceMknodItemInit(&item, cfg, vm, next);
1197 if (rc == -2) {
1198 /* @file doesn't exist. We can break here. */
1199 break;
1200 } else if (rc < 0) {
1201 /* Some other (critical) error. */
1202 return -1;
1203 }
1204
1205 isLink = S_ISLNK(item.sb.st_mode);
1206 g_free(next);
1207 next = g_strdup(item.target);
1208
1209 if (STRPREFIX(item.file, QEMU_DEVPREFIX)) {
1210 GStrv n;
1211 bool found = false;
1212
1213 for (n = devMountsPath; n && *n; n++) {
1214 if (STREQ(*n, "/dev"))
1215 continue;
1216 if (STRPREFIX(item.file, *n)) {
1217 found = true;
1218 break;
1219 }
1220 }
1221
1222 if (!found)
1223 VIR_APPEND_ELEMENT(data->items, data->nitems, item);
1224 }
1225
1226 if (!isLink)
1227 break;
1228
1229 if (ttl-- == 0) {
1230 virReportSystemError(ELOOP,
1231 _("Too many levels of symbolic links: %s"),
1232 next);
1233 return -1;
1234 }
1235 }
1236
1237 return 0;
1238 }
1239
1240
1241 static int
qemuNamespaceMknodPaths(virDomainObj * vm,GSList * paths,bool * created)1242 qemuNamespaceMknodPaths(virDomainObj *vm,
1243 GSList *paths,
1244 bool *created)
1245 {
1246 qemuDomainObjPrivate *priv = vm->privateData;
1247 virQEMUDriver *driver = priv->driver;
1248 g_autoptr(virQEMUDriverConfig) cfg = NULL;
1249 g_auto(GStrv) devMountsPath = NULL;
1250 qemuNamespaceMknodData data = { 0 };
1251 size_t i;
1252 int ret = -1;
1253 GSList *next;
1254
1255 if (!paths)
1256 return 0;
1257
1258 cfg = virQEMUDriverGetConfig(driver);
1259 if (qemuDomainGetPreservedMounts(cfg, vm, &devMountsPath, NULL, NULL) < 0)
1260 return -1;
1261
1262 data.driver = driver;
1263 data.vm = vm;
1264
1265 for (next = paths; next; next = next->next) {
1266 const char *path = next->data;
1267
1268 if (qemuNamespacePrepareOneItem(&data, cfg, vm, path, devMountsPath) < 0)
1269 goto cleanup;
1270 }
1271
1272 for (i = 0; i < data.nitems; i++) {
1273 qemuNamespaceMknodItem *item = &data.items[i];
1274 if (item->target &&
1275 qemuNamespaceMknodItemNeedsBindMount(item->sb.st_mode)) {
1276 if (virFileBindMountDevice(item->file, item->target) < 0)
1277 goto cleanup;
1278 item->bindmounted = true;
1279 }
1280 }
1281
1282 if (qemuSecurityPreFork(driver->securityManager) < 0)
1283 goto cleanup;
1284
1285 ret = virProcessRunInMountNamespace(vm->pid, qemuNamespaceMknodHelper,
1286 &data);
1287 qemuSecurityPostFork(driver->securityManager);
1288
1289 if (ret == 0 && created != NULL)
1290 *created = true;
1291
1292 cleanup:
1293 for (i = 0; i < data.nitems; i++) {
1294 if (data.items[i].bindmounted &&
1295 umount(data.items[i].target) < 0) {
1296 VIR_WARN("Unable to unmount %s", data.items[i].target);
1297 }
1298 }
1299 qemuNamespaceMknodDataClear(&data);
1300 return ret;
1301 }
1302
1303
1304 #else /* !defined(__linux__) */
1305
1306
1307 static int
qemuNamespaceMknodPaths(virDomainObj * vm G_GNUC_UNUSED,GSList * paths G_GNUC_UNUSED,bool * created G_GNUC_UNUSED)1308 qemuNamespaceMknodPaths(virDomainObj *vm G_GNUC_UNUSED,
1309 GSList *paths G_GNUC_UNUSED,
1310 bool *created G_GNUC_UNUSED)
1311 {
1312 virReportSystemError(ENOSYS, "%s",
1313 _("Namespaces are not supported on this platform."));
1314 return -1;
1315 }
1316
1317
1318 #endif /* !defined(__linux__) */
1319
1320
1321 static int
qemuNamespaceUnlinkHelper(pid_t pid G_GNUC_UNUSED,void * opaque)1322 qemuNamespaceUnlinkHelper(pid_t pid G_GNUC_UNUSED,
1323 void *opaque)
1324 {
1325 g_autoptr(virGSListString) paths = opaque;
1326 GSList *next;
1327
1328 for (next = paths; next; next = next->next) {
1329 const char *path = next->data;
1330
1331 VIR_DEBUG("Unlinking %s", path);
1332 if (unlink(path) < 0 && errno != ENOENT) {
1333 virReportSystemError(errno,
1334 _("Unable to remove device %s"), path);
1335 return -1;
1336 }
1337 }
1338
1339 return 0;
1340 }
1341
1342
1343 static int
qemuNamespaceUnlinkPaths(virDomainObj * vm,GSList * paths)1344 qemuNamespaceUnlinkPaths(virDomainObj *vm,
1345 GSList *paths)
1346 {
1347 qemuDomainObjPrivate *priv = vm->privateData;
1348 virQEMUDriver *driver = priv->driver;
1349 g_autoptr(virQEMUDriverConfig) cfg = NULL;
1350 g_auto(GStrv) devMountsPath = NULL;
1351 g_autoptr(virGSListString) unlinkPaths = NULL;
1352 GSList *next;
1353
1354 if (!paths)
1355 return 0;
1356
1357 cfg = virQEMUDriverGetConfig(driver);
1358
1359 if (qemuDomainGetPreservedMounts(cfg, vm, &devMountsPath, NULL, NULL) < 0)
1360 return -1;
1361
1362 for (next = paths; next; next = next->next) {
1363 const char *path = next->data;
1364
1365 if (STRPREFIX(path, QEMU_DEVPREFIX)) {
1366 GStrv mount;
1367 bool inSubmount = false;
1368
1369 for (mount = devMountsPath; *mount; mount++) {
1370 if (STREQ(*mount, "/dev"))
1371 continue;
1372
1373 if (STRPREFIX(path, *mount)) {
1374 inSubmount = true;
1375 break;
1376 }
1377 }
1378
1379 if (!inSubmount)
1380 unlinkPaths = g_slist_prepend(unlinkPaths, g_strdup(path));
1381 }
1382 }
1383
1384 if (unlinkPaths &&
1385 virProcessRunInMountNamespace(vm->pid,
1386 qemuNamespaceUnlinkHelper,
1387 unlinkPaths) < 0)
1388 return -1;
1389
1390 return 0;
1391 }
1392
1393
1394 int
qemuDomainNamespaceSetupDisk(virDomainObj * vm,virStorageSource * src,bool * created)1395 qemuDomainNamespaceSetupDisk(virDomainObj *vm,
1396 virStorageSource *src,
1397 bool *created)
1398 {
1399 g_autoptr(virGSListString) paths = NULL;
1400
1401 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1402 return 0;
1403
1404 if (qemuDomainSetupDisk(src, &paths) < 0)
1405 return -1;
1406
1407 if (qemuNamespaceMknodPaths(vm, paths, created) < 0)
1408 return -1;
1409
1410 return 0;
1411 }
1412
1413
1414 int
qemuDomainNamespaceTeardownDisk(virDomainObj * vm G_GNUC_UNUSED,virStorageSource * src G_GNUC_UNUSED)1415 qemuDomainNamespaceTeardownDisk(virDomainObj *vm G_GNUC_UNUSED,
1416 virStorageSource *src G_GNUC_UNUSED)
1417 {
1418 /* While in hotplug case we create the whole backing chain,
1419 * here we must limit ourselves. The disk we want to remove
1420 * might be a part of backing chain of another disk.
1421 * If you are reading these lines and have some spare time
1422 * you can come up with and algorithm that checks for that.
1423 * I don't, therefore: */
1424 return 0;
1425 }
1426
1427
1428 /**
1429 * qemuDomainNamespaceSetupHostdev:
1430 * @vm: domain object
1431 * @hostdev: hostdev to create in @vm's namespace
1432 *
1433 * For given @hostdev, create its devfs representation (if it has one) in
1434 * domain namespace. Note, @hostdev must not be in @vm's definition.
1435 *
1436 * Returns: 0 on success,
1437 * -1 otherwise.
1438 */
1439 int
qemuDomainNamespaceSetupHostdev(virDomainObj * vm,virDomainHostdevDef * hostdev,bool * created)1440 qemuDomainNamespaceSetupHostdev(virDomainObj *vm,
1441 virDomainHostdevDef *hostdev,
1442 bool *created)
1443 {
1444 g_autoptr(virGSListString) paths = NULL;
1445
1446 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1447 return 0;
1448
1449 if (qemuDomainSetupHostdev(vm,
1450 hostdev,
1451 true,
1452 &paths) < 0)
1453 return -1;
1454
1455 if (qemuNamespaceMknodPaths(vm, paths, created) < 0)
1456 return -1;
1457
1458 return 0;
1459 }
1460
1461
1462 /**
1463 * qemuDomainNamespaceTeardownHostdev:
1464 * @vm: domain object
1465 * @hostdev: hostdev to remove in @vm's namespace
1466 *
1467 * For given @hostdev, remove its devfs representation (if it has one) in
1468 * domain namespace. Note, @hostdev must not be in @vm's definition.
1469 *
1470 * Returns: 0 on success,
1471 * -1 otherwise.
1472 */
1473 int
qemuDomainNamespaceTeardownHostdev(virDomainObj * vm,virDomainHostdevDef * hostdev)1474 qemuDomainNamespaceTeardownHostdev(virDomainObj *vm,
1475 virDomainHostdevDef *hostdev)
1476 {
1477 g_autoptr(virGSListString) paths = NULL;
1478
1479 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1480 return 0;
1481
1482 if (qemuDomainSetupHostdev(vm,
1483 hostdev,
1484 true,
1485 &paths) < 0)
1486 return -1;
1487
1488 if (qemuNamespaceUnlinkPaths(vm, paths) < 0)
1489 return -1;
1490
1491 return 0;
1492 }
1493
1494
1495 int
qemuDomainNamespaceSetupMemory(virDomainObj * vm,virDomainMemoryDef * mem,bool * created)1496 qemuDomainNamespaceSetupMemory(virDomainObj *vm,
1497 virDomainMemoryDef *mem,
1498 bool *created)
1499 {
1500 g_autoptr(virGSListString) paths = NULL;
1501
1502 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1503 return 0;
1504
1505 if (qemuDomainSetupMemory(mem, &paths) < 0)
1506 return -1;
1507
1508 if (qemuNamespaceMknodPaths(vm, paths, created) < 0)
1509 return -1;
1510
1511 return 0;
1512 }
1513
1514
1515 int
qemuDomainNamespaceTeardownMemory(virDomainObj * vm,virDomainMemoryDef * mem)1516 qemuDomainNamespaceTeardownMemory(virDomainObj *vm,
1517 virDomainMemoryDef *mem)
1518 {
1519 g_autoptr(virGSListString) paths = NULL;
1520
1521 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1522 return 0;
1523
1524 if (qemuDomainSetupMemory(mem, &paths) < 0)
1525 return -1;
1526
1527 if (qemuNamespaceUnlinkPaths(vm, paths) < 0)
1528 return -1;
1529
1530 return 0;
1531 }
1532
1533
1534 int
qemuDomainNamespaceSetupChardev(virDomainObj * vm,virDomainChrDef * chr,bool * created)1535 qemuDomainNamespaceSetupChardev(virDomainObj *vm,
1536 virDomainChrDef *chr,
1537 bool *created)
1538 {
1539 g_autoptr(virGSListString) paths = NULL;
1540
1541 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1542 return 0;
1543
1544 if (qemuDomainSetupChardev(vm->def, chr, &paths) < 0)
1545 return -1;
1546
1547 if (qemuNamespaceMknodPaths(vm, paths, created) < 0)
1548 return -1;
1549
1550 return 0;
1551 }
1552
1553
1554 int
qemuDomainNamespaceTeardownChardev(virDomainObj * vm,virDomainChrDef * chr)1555 qemuDomainNamespaceTeardownChardev(virDomainObj *vm,
1556 virDomainChrDef *chr)
1557 {
1558 g_autoptr(virGSListString) paths = NULL;
1559
1560 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1561 return 0;
1562
1563 if (qemuDomainSetupChardev(vm->def, chr, &paths) < 0)
1564 return -1;
1565
1566 if (qemuNamespaceUnlinkPaths(vm, paths) < 0)
1567 return -1;
1568
1569 return 0;
1570 }
1571
1572
1573 int
qemuDomainNamespaceSetupRNG(virDomainObj * vm,virDomainRNGDef * rng,bool * created)1574 qemuDomainNamespaceSetupRNG(virDomainObj *vm,
1575 virDomainRNGDef *rng,
1576 bool *created)
1577 {
1578 g_autoptr(virGSListString) paths = NULL;
1579
1580 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1581 return 0;
1582
1583 if (qemuDomainSetupRNG(rng, &paths) < 0)
1584 return -1;
1585
1586 if (qemuNamespaceMknodPaths(vm, paths, created) < 0)
1587 return -1;
1588
1589 return 0;
1590 }
1591
1592
1593 int
qemuDomainNamespaceTeardownRNG(virDomainObj * vm,virDomainRNGDef * rng)1594 qemuDomainNamespaceTeardownRNG(virDomainObj *vm,
1595 virDomainRNGDef *rng)
1596 {
1597 g_autoptr(virGSListString) paths = NULL;
1598
1599 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1600 return 0;
1601
1602 if (qemuDomainSetupRNG(rng, &paths) < 0)
1603 return -1;
1604
1605 if (qemuNamespaceUnlinkPaths(vm, paths) < 0)
1606 return -1;
1607
1608 return 0;
1609 }
1610
1611
1612 int
qemuDomainNamespaceSetupInput(virDomainObj * vm,virDomainInputDef * input,bool * created)1613 qemuDomainNamespaceSetupInput(virDomainObj *vm,
1614 virDomainInputDef *input,
1615 bool *created)
1616 {
1617 g_autoptr(virGSListString) paths = NULL;
1618 int ret = 0;
1619
1620 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1621 return 0;
1622
1623 if (qemuDomainSetupInput(input, &paths) < 0)
1624 return -1;
1625
1626 if ((ret = qemuNamespaceMknodPaths(vm, paths, created)) < 0)
1627 return -1;
1628
1629 return 0;
1630 }
1631
1632
1633 int
qemuDomainNamespaceTeardownInput(virDomainObj * vm,virDomainInputDef * input)1634 qemuDomainNamespaceTeardownInput(virDomainObj *vm,
1635 virDomainInputDef *input)
1636 {
1637 g_autoptr(virGSListString) paths = NULL;
1638
1639 if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
1640 return 0;
1641
1642 if (qemuDomainSetupInput(input, &paths) < 0)
1643 return -1;
1644
1645 if (qemuNamespaceUnlinkPaths(vm, paths) < 0)
1646 return -1;
1647
1648 return 0;
1649 }
1650