CVE-2013-6456: Avoid unsafe use of /proc/$PID/root in LXC disk hotplug
[libvirt.git] / src / lxc / lxc_driver.c
1 /*
2  * Copyright (C) 2010-2013 Red Hat, Inc.
3  * Copyright IBM Corp. 2008
4  *
5  * lxc_driver.c: linux container driver functions
6  *
7  * Authors:
8  *  David L. Leskovec <dlesko at linux.vnet.ibm.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library.  If not, see
22  * <http://www.gnu.org/licenses/>.
23  */
24
25 #include <config.h>
26
27 #include <fcntl.h>
28 #include <sched.h>
29 #include <sys/utsname.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/stat.h>
34 #include <sys/un.h>
35 #include <sys/poll.h>
36 #include <unistd.h>
37 #include <wait.h>
38
39 #include "virerror.h"
40 #include "virlog.h"
41 #include "datatypes.h"
42 #include "lxc_cgroup.h"
43 #include "lxc_conf.h"
44 #include "lxc_container.h"
45 #include "lxc_domain.h"
46 #include "lxc_driver.h"
47 #include "lxc_process.h"
48 #include "viralloc.h"
49 #include "virnetdevbridge.h"
50 #include "virnetdevveth.h"
51 #include "nodeinfo.h"
52 #include "viruuid.h"
53 #include "virstatslinux.h"
54 #include "virhook.h"
55 #include "virfile.h"
56 #include "virpidfile.h"
57 #include "fdstream.h"
58 #include "domain_audit.h"
59 #include "domain_nwfilter.h"
60 #include "nwfilter_conf.h"
61 #include "network/bridge_driver.h"
62 #include "virinitctl.h"
63 #include "virnetdev.h"
64 #include "virnetdevtap.h"
65 #include "virnodesuspend.h"
66 #include "virprocess.h"
67 #include "virtime.h"
68 #include "virtypedparam.h"
69 #include "viruri.h"
70 #include "virstring.h"
71 #include "viraccessapicheck.h"
72 #include "viraccessapichecklxc.h"
73
74 #define VIR_FROM_THIS VIR_FROM_LXC
75
76
77 #define LXC_NB_MEM_PARAM  3
78
79 static int lxcStateInitialize(bool privileged,
80                               virStateInhibitCallback callback,
81                               void *opaque);
82 static int lxcStateCleanup(void);
83 virLXCDriverPtr lxc_driver = NULL;
84
85 /* callbacks for nwfilter */
86 static int
87 lxcVMFilterRebuild(virDomainObjListIterator iter, void *data)
88 {
89     return virDomainObjListForEach(lxc_driver->domains, iter, data);
90 }
91
92 static void
93 lxcVMDriverLock(void)
94 {
95     lxcDriverLock(lxc_driver);
96 }
97
98 static void
99 lxcVMDriverUnlock(void)
100 {
101     lxcDriverUnlock(lxc_driver);
102 }
103
104 static virNWFilterCallbackDriver lxcCallbackDriver = {
105     .name = "LXC",
106     .vmFilterRebuild = lxcVMFilterRebuild,
107     .vmDriverLock = lxcVMDriverLock,
108     .vmDriverUnlock = lxcVMDriverUnlock,
109 };
110
111 /**
112  * lxcDomObjFromDomain:
113  * @domain: Domain pointer that has to be looked up
114  *
115  * This function looks up @domain and returns the appropriate
116  * virDomainObjPtr.
117  *
118  * Returns the domain object which is locked on success, NULL
119  * otherwise.
120  */
121 static virDomainObjPtr
122 lxcDomObjFromDomain(virDomainPtr domain)
123 {
124     virDomainObjPtr vm;
125     virLXCDriverPtr driver = domain->conn->privateData;
126     char uuidstr[VIR_UUID_STRING_BUFLEN];
127
128     vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
129     if (!vm) {
130         virUUIDFormat(domain->uuid, uuidstr);
131         virReportError(VIR_ERR_NO_DOMAIN,
132                        _("no domain with matching uuid '%s' (%s)"),
133                        uuidstr, domain->name);
134         return NULL;
135     }
136
137     return vm;
138 }
139
140 /* Functions */
141
142 static virDrvOpenStatus lxcConnectOpen(virConnectPtr conn,
143                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
144                                        unsigned int flags)
145 {
146     virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
147
148     /* Verify uri was specified */
149     if (conn->uri == NULL) {
150         if (lxc_driver == NULL)
151             return VIR_DRV_OPEN_DECLINED;
152
153         if (!(conn->uri = virURIParse("lxc:///")))
154             return VIR_DRV_OPEN_ERROR;
155     } else {
156         if (conn->uri->scheme == NULL ||
157             STRNEQ(conn->uri->scheme, "lxc"))
158             return VIR_DRV_OPEN_DECLINED;
159
160         /* Leave for remote driver */
161         if (conn->uri->server != NULL)
162             return VIR_DRV_OPEN_DECLINED;
163
164         /* If path isn't '/' then they typoed, tell them correct path */
165         if (conn->uri->path != NULL &&
166             STRNEQ(conn->uri->path, "/")) {
167             virReportError(VIR_ERR_INTERNAL_ERROR,
168                            _("Unexpected LXC URI path '%s', try lxc:///"),
169                            conn->uri->path);
170             return VIR_DRV_OPEN_ERROR;
171         }
172
173         /* URI was good, but driver isn't active */
174         if (lxc_driver == NULL) {
175             virReportError(VIR_ERR_INTERNAL_ERROR,
176                            "%s", _("lxc state driver is not active"));
177             return VIR_DRV_OPEN_ERROR;
178         }
179     }
180
181     if (virConnectOpenEnsureACL(conn) < 0)
182         return VIR_DRV_OPEN_ERROR;
183
184     conn->privateData = lxc_driver;
185
186     return VIR_DRV_OPEN_SUCCESS;
187 }
188
189 static int lxcConnectClose(virConnectPtr conn)
190 {
191     virLXCDriverPtr driver = conn->privateData;
192
193     virCloseCallbacksRun(driver->closeCallbacks, conn, driver->domains, driver);
194     conn->privateData = NULL;
195     return 0;
196 }
197
198
199 static int lxcConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
200 {
201     /* Trivially secure, since always inside the daemon */
202     return 1;
203 }
204
205
206 static int lxcConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
207 {
208     /* Not encrypted, but remote driver takes care of that */
209     return 0;
210 }
211
212
213 static int lxcConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
214 {
215     return 1;
216 }
217
218
219 static char *lxcConnectGetCapabilities(virConnectPtr conn) {
220     virLXCDriverPtr driver = conn->privateData;
221     virCapsPtr caps;
222     char *xml;
223
224     if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
225         return NULL;
226
227     if (!(caps = virLXCDriverGetCapabilities(driver, false)))
228         return NULL;
229
230     if ((xml = virCapabilitiesFormatXML(caps)) == NULL)
231         virReportOOMError();
232
233     virObjectUnref(caps);
234     return xml;
235 }
236
237
238 static virDomainPtr lxcDomainLookupByID(virConnectPtr conn,
239                                         int id)
240 {
241     virLXCDriverPtr driver = conn->privateData;
242     virDomainObjPtr vm;
243     virDomainPtr dom = NULL;
244
245     vm = virDomainObjListFindByID(driver->domains, id);
246
247     if (!vm) {
248         virReportError(VIR_ERR_NO_DOMAIN,
249                        _("No domain with matching id %d"), id);
250         goto cleanup;
251     }
252
253     if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
254         goto cleanup;
255
256     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
257     if (dom)
258         dom->id = vm->def->id;
259
260 cleanup:
261     if (vm)
262         virObjectUnlock(vm);
263     return dom;
264 }
265
266 static virDomainPtr lxcDomainLookupByUUID(virConnectPtr conn,
267                                           const unsigned char *uuid)
268 {
269     virLXCDriverPtr driver = conn->privateData;
270     virDomainObjPtr vm;
271     virDomainPtr dom = NULL;
272
273     vm = virDomainObjListFindByUUID(driver->domains, uuid);
274
275     if (!vm) {
276         char uuidstr[VIR_UUID_STRING_BUFLEN];
277         virUUIDFormat(uuid, uuidstr);
278         virReportError(VIR_ERR_NO_DOMAIN,
279                        _("No domain with matching uuid '%s'"), uuidstr);
280         goto cleanup;
281     }
282
283     if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
284         goto cleanup;
285
286     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
287     if (dom)
288         dom->id = vm->def->id;
289
290 cleanup:
291     if (vm)
292         virObjectUnlock(vm);
293     return dom;
294 }
295
296 static virDomainPtr lxcDomainLookupByName(virConnectPtr conn,
297                                           const char *name)
298 {
299     virLXCDriverPtr driver = conn->privateData;
300     virDomainObjPtr vm;
301     virDomainPtr dom = NULL;
302
303     vm = virDomainObjListFindByName(driver->domains, name);
304     if (!vm) {
305         virReportError(VIR_ERR_NO_DOMAIN,
306                        _("No domain with matching name '%s'"), name);
307         goto cleanup;
308     }
309
310     if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
311         goto cleanup;
312
313     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
314     if (dom)
315         dom->id = vm->def->id;
316
317 cleanup:
318     if (vm)
319         virObjectUnlock(vm);
320     return dom;
321 }
322
323
324 static int lxcDomainIsActive(virDomainPtr dom)
325 {
326     virDomainObjPtr obj;
327     int ret = -1;
328
329     if (!(obj = lxcDomObjFromDomain(dom)))
330         goto cleanup;
331
332     if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0)
333         goto cleanup;
334
335     ret = virDomainObjIsActive(obj);
336
337 cleanup:
338     if (obj)
339         virObjectUnlock(obj);
340     return ret;
341 }
342
343
344 static int lxcDomainIsPersistent(virDomainPtr dom)
345 {
346     virDomainObjPtr obj;
347     int ret = -1;
348
349     if (!(obj = lxcDomObjFromDomain(dom)))
350         goto cleanup;
351
352     if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0)
353         goto cleanup;
354
355     ret = obj->persistent;
356
357 cleanup:
358     if (obj)
359         virObjectUnlock(obj);
360     return ret;
361 }
362
363 static int lxcDomainIsUpdated(virDomainPtr dom)
364 {
365     virDomainObjPtr obj;
366     int ret = -1;
367
368     if (!(obj = lxcDomObjFromDomain(dom)))
369         goto cleanup;
370
371     if (virDomainIsUpdatedEnsureACL(dom->conn, obj->def) < 0)
372         goto cleanup;
373
374     ret = obj->updated;
375
376 cleanup:
377     if (obj)
378         virObjectUnlock(obj);
379     return ret;
380 }
381
382 static int lxcConnectListDomains(virConnectPtr conn, int *ids, int nids) {
383     virLXCDriverPtr driver = conn->privateData;
384     int n;
385
386     if (virConnectListDomainsEnsureACL(conn) < 0)
387         return -1;
388
389     n = virDomainObjListGetActiveIDs(driver->domains, ids, nids,
390                                      virConnectListDomainsCheckACL, conn);
391
392     return n;
393 }
394
395 static int lxcConnectNumOfDomains(virConnectPtr conn) {
396     virLXCDriverPtr driver = conn->privateData;
397     int n;
398
399     if (virConnectNumOfDomainsEnsureACL(conn) < 0)
400         return -1;
401
402     n = virDomainObjListNumOfDomains(driver->domains, true,
403                                      virConnectNumOfDomainsCheckACL, conn);
404
405     return n;
406 }
407
408 static int lxcConnectListDefinedDomains(virConnectPtr conn,
409                                         char **const names, int nnames) {
410     virLXCDriverPtr driver = conn->privateData;
411     int n;
412
413     if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
414         return -1;
415
416     n = virDomainObjListGetInactiveNames(driver->domains, names, nnames,
417                                          virConnectListDefinedDomainsCheckACL, conn);
418
419     return n;
420 }
421
422
423 static int lxcConnectNumOfDefinedDomains(virConnectPtr conn) {
424     virLXCDriverPtr driver = conn->privateData;
425     int n;
426
427     if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
428         return -1;
429
430     n = virDomainObjListNumOfDomains(driver->domains, false,
431                                      virConnectNumOfDefinedDomainsCheckACL, conn);
432
433     return n;
434 }
435
436
437
438 static virDomainPtr lxcDomainDefineXML(virConnectPtr conn, const char *xml)
439 {
440     virLXCDriverPtr driver = conn->privateData;
441     virDomainDefPtr def = NULL;
442     virDomainObjPtr vm = NULL;
443     virDomainPtr dom = NULL;
444     virDomainEventPtr event = NULL;
445     virDomainDefPtr oldDef = NULL;
446     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
447     virCapsPtr caps = NULL;
448
449     if (!(caps = virLXCDriverGetCapabilities(driver, false)))
450         goto cleanup;
451
452     if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
453                                         1 << VIR_DOMAIN_VIRT_LXC,
454                                         VIR_DOMAIN_XML_INACTIVE)))
455         goto cleanup;
456
457     if (virDomainDefineXMLEnsureACL(conn, def) < 0)
458         goto cleanup;
459
460     if (virSecurityManagerVerify(driver->securityManager, def) < 0)
461         goto cleanup;
462
463     if ((def->nets != NULL) && !(cfg->have_netns)) {
464         virReportError(VIR_ERR_OPERATION_INVALID,
465                        "%s", _("System lacks NETNS support"));
466         goto cleanup;
467     }
468
469     if (!(vm = virDomainObjListAdd(driver->domains, def,
470                                    driver->xmlopt,
471                                    0, &oldDef)))
472         goto cleanup;
473     def = NULL;
474     vm->persistent = 1;
475
476     if (virDomainSaveConfig(cfg->configDir,
477                             vm->newDef ? vm->newDef : vm->def) < 0) {
478         virDomainObjListRemove(driver->domains, vm);
479         vm = NULL;
480         goto cleanup;
481     }
482
483     event = virDomainEventNewFromObj(vm,
484                                      VIR_DOMAIN_EVENT_DEFINED,
485                                      !oldDef ?
486                                      VIR_DOMAIN_EVENT_DEFINED_ADDED :
487                                      VIR_DOMAIN_EVENT_DEFINED_UPDATED);
488
489     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
490     if (dom)
491         dom->id = vm->def->id;
492
493 cleanup:
494     virDomainDefFree(def);
495     virDomainDefFree(oldDef);
496     if (vm)
497         virObjectUnlock(vm);
498     if (event)
499         virDomainEventStateQueue(driver->domainEventState, event);
500     virObjectUnref(caps);
501     virObjectUnref(cfg);
502     return dom;
503 }
504
505 static int lxcDomainUndefineFlags(virDomainPtr dom,
506                                   unsigned int flags)
507 {
508     virLXCDriverPtr driver = dom->conn->privateData;
509     virDomainObjPtr vm;
510     virDomainEventPtr event = NULL;
511     int ret = -1;
512     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
513
514     virCheckFlags(0, -1);
515
516     if (!(vm = lxcDomObjFromDomain(dom)))
517         goto cleanup;
518
519     if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
520         goto cleanup;
521
522     if (!vm->persistent) {
523         virReportError(VIR_ERR_OPERATION_INVALID,
524                        "%s", _("Cannot undefine transient domain"));
525         goto cleanup;
526     }
527
528     if (virDomainDeleteConfig(cfg->configDir,
529                               cfg->autostartDir,
530                               vm) < 0)
531         goto cleanup;
532
533     event = virDomainEventNewFromObj(vm,
534                                      VIR_DOMAIN_EVENT_UNDEFINED,
535                                      VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
536
537     if (virDomainObjIsActive(vm)) {
538         vm->persistent = 0;
539     } else {
540         virDomainObjListRemove(driver->domains, vm);
541         vm = NULL;
542     }
543
544     ret = 0;
545
546 cleanup:
547     if (vm)
548         virObjectUnlock(vm);
549     if (event)
550         virDomainEventStateQueue(driver->domainEventState, event);
551     virObjectUnref(cfg);
552     return ret;
553 }
554
555 static int lxcDomainUndefine(virDomainPtr dom)
556 {
557     return lxcDomainUndefineFlags(dom, 0);
558 }
559
560 static int lxcDomainGetInfo(virDomainPtr dom,
561                             virDomainInfoPtr info)
562 {
563     virDomainObjPtr vm;
564     int ret = -1;
565     virLXCDomainObjPrivatePtr priv;
566
567     if (!(vm = lxcDomObjFromDomain(dom)))
568         goto cleanup;
569
570     priv = vm->privateData;
571
572     if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
573         goto cleanup;
574
575     info->state = virDomainObjGetState(vm, NULL);
576
577     if (!virDomainObjIsActive(vm)) {
578         info->cpuTime = 0;
579         info->memory = vm->def->mem.cur_balloon;
580     } else {
581         if (virCgroupGetCpuacctUsage(priv->cgroup, &(info->cpuTime)) < 0) {
582             virReportError(VIR_ERR_OPERATION_FAILED,
583                            "%s", _("Cannot read cputime for domain"));
584             goto cleanup;
585         }
586         if (virCgroupGetMemoryUsage(priv->cgroup, &(info->memory)) < 0) {
587             /* Don't fail if we can't read memory usage due to a lack of
588              * kernel support */
589             if (virLastErrorIsSystemErrno(ENOENT)) {
590                 virResetLastError();
591                 info->memory = 0;
592             } else {
593                 goto cleanup;
594             }
595         }
596     }
597
598     info->maxMem = vm->def->mem.max_balloon;
599     info->nrVirtCpu = vm->def->vcpus;
600     ret = 0;
601
602 cleanup:
603     if (vm)
604         virObjectUnlock(vm);
605     return ret;
606 }
607
608 static int
609 lxcDomainGetState(virDomainPtr dom,
610                   int *state,
611                   int *reason,
612                   unsigned int flags)
613 {
614     virDomainObjPtr vm;
615     int ret = -1;
616
617     virCheckFlags(0, -1);
618
619     if (!(vm = lxcDomObjFromDomain(dom)))
620         goto cleanup;
621
622     if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
623         goto cleanup;
624
625     *state = virDomainObjGetState(vm, reason);
626     ret = 0;
627
628 cleanup:
629     if (vm)
630         virObjectUnlock(vm);
631     return ret;
632 }
633
634 static char *lxcDomainGetOSType(virDomainPtr dom)
635 {
636     virDomainObjPtr vm;
637     char *ret = NULL;
638
639     if (!(vm = lxcDomObjFromDomain(dom)))
640         goto cleanup;
641
642     if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
643         goto cleanup;
644
645     if (VIR_STRDUP(ret, vm->def->os.type) < 0)
646         goto cleanup;
647
648 cleanup:
649     if (vm)
650         virObjectUnlock(vm);
651     return ret;
652 }
653
654 /* Returns max memory in kb, 0 if error */
655 static unsigned long long
656 lxcDomainGetMaxMemory(virDomainPtr dom)
657 {
658     virDomainObjPtr vm;
659     unsigned long long ret = 0;
660
661     if (!(vm = lxcDomObjFromDomain(dom)))
662         goto cleanup;
663
664     if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0)
665         goto cleanup;
666
667     ret = vm->def->mem.max_balloon;
668
669 cleanup:
670     if (vm)
671         virObjectUnlock(vm);
672     return ret;
673 }
674
675 static int lxcDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
676     virDomainObjPtr vm;
677     int ret = -1;
678
679     if (!(vm = lxcDomObjFromDomain(dom)))
680         goto cleanup;
681
682     if (virDomainSetMaxMemoryEnsureACL(dom->conn, vm->def) < 0)
683         goto cleanup;
684
685     if (newmax < vm->def->mem.cur_balloon) {
686         virReportError(VIR_ERR_INVALID_ARG,
687                        "%s", _("Cannot set max memory lower than current memory"));
688         goto cleanup;
689     }
690
691     vm->def->mem.max_balloon = newmax;
692     ret = 0;
693
694 cleanup:
695     if (vm)
696         virObjectUnlock(vm);
697     return ret;
698 }
699
700 static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
701     virDomainObjPtr vm;
702     int ret = -1;
703     virLXCDomainObjPrivatePtr priv;
704
705     if (!(vm = lxcDomObjFromDomain(dom)))
706         goto cleanup;
707
708     priv = vm->privateData;
709
710     if (virDomainSetMemoryEnsureACL(dom->conn, vm->def) < 0)
711         goto cleanup;
712
713     if (newmem > vm->def->mem.max_balloon) {
714         virReportError(VIR_ERR_INVALID_ARG,
715                        "%s", _("Cannot set memory higher than max memory"));
716         goto cleanup;
717     }
718
719     if (!virDomainObjIsActive(vm)) {
720         virReportError(VIR_ERR_OPERATION_INVALID,
721                        "%s", _("Domain is not running"));
722         goto cleanup;
723     }
724
725     if (virCgroupSetMemory(priv->cgroup, newmem) < 0) {
726         virReportError(VIR_ERR_OPERATION_FAILED,
727                        "%s", _("Failed to set memory for domain"));
728         goto cleanup;
729     }
730
731     ret = 0;
732
733 cleanup:
734     if (vm)
735         virObjectUnlock(vm);
736     return ret;
737 }
738
739 static int
740 lxcDomainSetMemoryParameters(virDomainPtr dom,
741                              virTypedParameterPtr params,
742                              int nparams,
743                              unsigned int flags)
744 {
745     virCapsPtr caps = NULL;
746     virDomainDefPtr vmdef = NULL;
747     virDomainObjPtr vm = NULL;
748     virLXCDomainObjPrivatePtr priv = NULL;
749     virLXCDriverConfigPtr cfg = NULL;
750     virLXCDriverPtr driver = dom->conn->privateData;
751     unsigned long long hard_limit;
752     unsigned long long soft_limit;
753     unsigned long long swap_hard_limit;
754     bool set_hard_limit = false;
755     bool set_soft_limit = false;
756     bool set_swap_hard_limit = false;
757     int rc;
758     int ret = -1;
759
760     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
761                   VIR_DOMAIN_AFFECT_CONFIG, -1);
762
763     if (virTypedParamsValidate(params, nparams,
764                                VIR_DOMAIN_MEMORY_HARD_LIMIT,
765                                VIR_TYPED_PARAM_ULLONG,
766                                VIR_DOMAIN_MEMORY_SOFT_LIMIT,
767                                VIR_TYPED_PARAM_ULLONG,
768                                VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
769                                VIR_TYPED_PARAM_ULLONG,
770                                NULL) < 0)
771         return -1;
772
773     if (!(vm = lxcDomObjFromDomain(dom)))
774         goto cleanup;
775
776     priv = vm->privateData;
777     cfg = virLXCDriverGetConfig(driver);
778
779     if (virDomainSetMemoryParametersEnsureACL(dom->conn, vm->def, flags) < 0 ||
780         !(caps = virLXCDriverGetCapabilities(driver, false)) ||
781         virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
782                                         vm, &flags, &vmdef) < 0)
783         goto cleanup;
784
785     if (flags & VIR_DOMAIN_AFFECT_LIVE &&
786         !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
787         virReportError(VIR_ERR_OPERATION_INVALID,
788                        "%s", _("cgroup memory controller is not mounted"));
789         goto cleanup;
790     }
791
792 #define VIR_GET_LIMIT_PARAMETER(PARAM, VALUE)                                \
793     if ((rc = virTypedParamsGetULLong(params, nparams, PARAM, &VALUE)) < 0)  \
794         goto cleanup;                                                        \
795                                                                              \
796     if (rc == 1)                                                             \
797         set_ ## VALUE = true;
798
799     VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, swap_hard_limit)
800     VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_HARD_LIMIT, hard_limit)
801     VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SOFT_LIMIT, soft_limit)
802
803 #undef VIR_GET_LIMIT_PARAMETER
804
805     /* Swap hard limit must be greater than hard limit.
806      * Note that limit of 0 denotes unlimited */
807     if (set_swap_hard_limit || set_hard_limit) {
808         unsigned long long mem_limit = vm->def->mem.hard_limit;
809         unsigned long long swap_limit = vm->def->mem.swap_hard_limit;
810
811         if (set_swap_hard_limit)
812             swap_limit = swap_hard_limit;
813
814         if (set_hard_limit)
815             mem_limit = hard_limit;
816
817         if (virCompareLimitUlong(mem_limit, swap_limit) > 0) {
818             virReportError(VIR_ERR_INVALID_ARG, "%s",
819                            _("memory hard_limit tunable value must be lower "
820                              "than or equal to swap_hard_limit"));
821             goto cleanup;
822         }
823     }
824
825 #define LXC_SET_MEM_PARAMETER(FUNC, VALUE)                                     \
826     if (set_ ## VALUE) {                                                        \
827         if (flags & VIR_DOMAIN_AFFECT_LIVE) {                                   \
828             if ((rc = FUNC(priv->cgroup, VALUE)) < 0) {                         \
829                 virReportSystemError(-rc, _("unable to set memory %s tunable"), \
830                                      #VALUE);                                   \
831                                                                                 \
832                 goto cleanup;                                                   \
833             }                                                                   \
834             vm->def->mem.VALUE = VALUE;                                         \
835         }                                                                       \
836                                                                                 \
837         if (flags & VIR_DOMAIN_AFFECT_CONFIG)                                   \
838             vmdef->mem.VALUE = VALUE;                                   \
839     }
840
841     /* Soft limit doesn't clash with the others */
842     LXC_SET_MEM_PARAMETER(virCgroupSetMemorySoftLimit, soft_limit);
843
844     /* set hard limit before swap hard limit if decreasing it */
845     if (virCompareLimitUlong(vm->def->mem.hard_limit, hard_limit) > 0) {
846         LXC_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);
847         /* inhibit changing the limit a second time */
848         set_hard_limit = false;
849     }
850
851     LXC_SET_MEM_PARAMETER(virCgroupSetMemSwapHardLimit, swap_hard_limit);
852
853     /* otherwise increase it after swap hard limit */
854     LXC_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);
855
856 #undef LXC_SET_MEM_PARAMETER
857
858     if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
859         virDomainSaveConfig(cfg->configDir, vmdef) < 0)
860         goto cleanup;
861
862     ret = 0;
863 cleanup:
864     if (vm)
865         virObjectUnlock(vm);
866     virObjectUnref(caps);
867     virObjectUnref(cfg);
868     return ret;
869 }
870
871 static int
872 lxcDomainGetMemoryParameters(virDomainPtr dom,
873                              virTypedParameterPtr params,
874                              int *nparams,
875                              unsigned int flags)
876 {
877     virCapsPtr caps = NULL;
878     virDomainDefPtr vmdef = NULL;
879     virDomainObjPtr vm = NULL;
880     virLXCDomainObjPrivatePtr priv = NULL;
881     virLXCDriverPtr driver = dom->conn->privateData;
882     unsigned long long val;
883     int ret = -1;
884     size_t i;
885
886     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
887                   VIR_DOMAIN_AFFECT_CONFIG, -1);
888
889     if (!(vm = lxcDomObjFromDomain(dom)))
890         goto cleanup;
891
892     priv = vm->privateData;
893
894     if (virDomainGetMemoryParametersEnsureACL(dom->conn, vm->def) < 0 ||
895         !(caps = virLXCDriverGetCapabilities(driver, false)) ||
896         virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
897                                         vm, &flags, &vmdef) < 0)
898         goto cleanup;
899
900     if (flags & VIR_DOMAIN_AFFECT_LIVE &&
901         !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
902         virReportError(VIR_ERR_OPERATION_INVALID,
903                        "%s", _("cgroup memory controller is not mounted"));
904         goto cleanup;
905     }
906
907     if ((*nparams) == 0) {
908         /* Current number of memory parameters supported by cgroups */
909         *nparams = LXC_NB_MEM_PARAM;
910         ret = 0;
911         goto cleanup;
912     }
913
914     for (i = 0; i < LXC_NB_MEM_PARAM && i < *nparams; i++) {
915         virTypedParameterPtr param = &params[i];
916         val = 0;
917
918         switch (i) {
919         case 0: /* fill memory hard limit here */
920             if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
921                 val = vmdef->mem.hard_limit;
922                 val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
923             } else if (virCgroupGetMemoryHardLimit(priv->cgroup, &val) < 0) {
924                 goto cleanup;
925             }
926             if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_HARD_LIMIT,
927                                         VIR_TYPED_PARAM_ULLONG, val) < 0)
928                 goto cleanup;
929             break;
930         case 1: /* fill memory soft limit here */
931             if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
932                 val = vmdef->mem.soft_limit;
933                 val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
934             } else if (virCgroupGetMemorySoftLimit(priv->cgroup, &val) < 0) {
935                 goto cleanup;
936             }
937             if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_SOFT_LIMIT,
938                                         VIR_TYPED_PARAM_ULLONG, val) < 0)
939                 goto cleanup;
940             break;
941         case 2: /* fill swap hard limit here */
942             if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
943                 val = vmdef->mem.swap_hard_limit;
944                 val = val ? val : VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
945             } else if (virCgroupGetMemSwapHardLimit(priv->cgroup, &val) < 0) {
946                 goto cleanup;
947             }
948             if (virTypedParameterAssign(param,
949                                         VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
950                                         VIR_TYPED_PARAM_ULLONG, val) < 0)
951                 goto cleanup;
952             break;
953
954         /* coverity[dead_error_begin] */
955         default:
956             break;
957             /* should not hit here */
958         }
959     }
960
961     if (*nparams > LXC_NB_MEM_PARAM)
962         *nparams = LXC_NB_MEM_PARAM;
963     ret = 0;
964
965 cleanup:
966     if (vm)
967         virObjectUnlock(vm);
968     virObjectUnref(caps);
969     return ret;
970 }
971
972 static char *lxcDomainGetXMLDesc(virDomainPtr dom,
973                                  unsigned int flags)
974 {
975     virDomainObjPtr vm;
976     char *ret = NULL;
977
978     /* Flags checked by virDomainDefFormat */
979
980     if (!(vm = lxcDomObjFromDomain(dom)))
981         goto cleanup;
982
983     if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
984         goto cleanup;
985
986     ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) &&
987                              vm->newDef ? vm->newDef : vm->def,
988                              flags);
989
990 cleanup:
991     if (vm)
992         virObjectUnlock(vm);
993     return ret;
994 }
995
996 /**
997  * lxcDomainCreateWithFlags:
998  * @dom: domain to start
999  * @flags: Must be 0 for now
1000  *
1001  * Looks up domain and starts it.
1002  *
1003  * Returns 0 on success or -1 in case of error
1004  */
1005 static int lxcDomainCreateWithFiles(virDomainPtr dom,
1006                                     unsigned int nfiles,
1007                                     int *files,
1008                                     unsigned int flags)
1009 {
1010     virLXCDriverPtr driver = dom->conn->privateData;
1011     virDomainObjPtr vm;
1012     virDomainEventPtr event = NULL;
1013     int ret = -1;
1014     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
1015
1016     virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, -1);
1017
1018     virNWFilterReadLockFilterUpdates();
1019
1020     if (!(vm = lxcDomObjFromDomain(dom)))
1021         goto cleanup;
1022
1023     if (virDomainCreateWithFilesEnsureACL(dom->conn, vm->def) < 0)
1024         goto cleanup;
1025
1026     if ((vm->def->nets != NULL) && !(cfg->have_netns)) {
1027         virReportError(VIR_ERR_OPERATION_INVALID,
1028                        "%s", _("System lacks NETNS support"));
1029         goto cleanup;
1030     }
1031
1032     if (virDomainObjIsActive(vm)) {
1033         virReportError(VIR_ERR_OPERATION_INVALID,
1034                        "%s", _("Domain is already running"));
1035         goto cleanup;
1036     }
1037
1038     ret = virLXCProcessStart(dom->conn, driver, vm,
1039                              nfiles, files,
1040                              (flags & VIR_DOMAIN_START_AUTODESTROY),
1041                              VIR_DOMAIN_RUNNING_BOOTED);
1042
1043     if (ret == 0) {
1044         event = virDomainEventNewFromObj(vm,
1045                                          VIR_DOMAIN_EVENT_STARTED,
1046                                          VIR_DOMAIN_EVENT_STARTED_BOOTED);
1047         virDomainAuditStart(vm, "booted", true);
1048     } else {
1049         virDomainAuditStart(vm, "booted", false);
1050     }
1051
1052 cleanup:
1053     if (vm)
1054         virObjectUnlock(vm);
1055     if (event)
1056         virDomainEventStateQueue(driver->domainEventState, event);
1057     virObjectUnref(cfg);
1058     virNWFilterUnlockFilterUpdates();
1059     return ret;
1060 }
1061
1062 /**
1063  * lxcDomainCreate:
1064  * @dom: domain to start
1065  *
1066  * Looks up domain and starts it.
1067  *
1068  * Returns 0 on success or -1 in case of error
1069  */
1070 static int lxcDomainCreate(virDomainPtr dom)
1071 {
1072     return lxcDomainCreateWithFiles(dom, 0, NULL, 0);
1073 }
1074
1075 /**
1076  * lxcDomainCreateWithFlags:
1077  * @dom: domain to start
1078  *
1079  * Looks up domain and starts it.
1080  *
1081  * Returns 0 on success or -1 in case of error
1082  */
1083 static int lxcDomainCreateWithFlags(virDomainPtr dom,
1084                                     unsigned int flags)
1085 {
1086     return lxcDomainCreateWithFiles(dom, 0, NULL, flags);
1087 }
1088
1089 /**
1090  * lxcDomainCreateXML:
1091  * @conn: pointer to connection
1092  * @xml: XML definition of domain
1093  * @flags: Must be 0 for now
1094  *
1095  * Creates a domain based on xml and starts it
1096  *
1097  * Returns 0 on success or -1 in case of error
1098  */
1099 static virDomainPtr
1100 lxcDomainCreateXMLWithFiles(virConnectPtr conn,
1101                             const char *xml,
1102                             unsigned int nfiles,
1103                             int *files,
1104                             unsigned int flags) {
1105     virLXCDriverPtr driver = conn->privateData;
1106     virDomainObjPtr vm = NULL;
1107     virDomainDefPtr def = NULL;
1108     virDomainPtr dom = NULL;
1109     virDomainEventPtr event = NULL;
1110     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
1111     virCapsPtr caps = NULL;
1112
1113     virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, NULL);
1114
1115     virNWFilterReadLockFilterUpdates();
1116
1117     if (!(caps = virLXCDriverGetCapabilities(driver, false)))
1118         goto cleanup;
1119
1120     if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
1121                                         1 << VIR_DOMAIN_VIRT_LXC,
1122                                         VIR_DOMAIN_XML_INACTIVE)))
1123         goto cleanup;
1124
1125     if (virDomainCreateXMLWithFilesEnsureACL(conn, def) < 0)
1126         goto cleanup;
1127
1128     if (virSecurityManagerVerify(driver->securityManager, def) < 0)
1129         goto cleanup;
1130
1131     if ((def->nets != NULL) && !(cfg->have_netns)) {
1132         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1133                        "%s", _("System lacks NETNS support"));
1134         goto cleanup;
1135     }
1136
1137
1138     if (!(vm = virDomainObjListAdd(driver->domains, def,
1139                                    driver->xmlopt,
1140                                    VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
1141                                    NULL)))
1142         goto cleanup;
1143     def = NULL;
1144
1145     if (virLXCProcessStart(conn, driver, vm,
1146                            nfiles, files,
1147                            (flags & VIR_DOMAIN_START_AUTODESTROY),
1148                            VIR_DOMAIN_RUNNING_BOOTED) < 0) {
1149         virDomainAuditStart(vm, "booted", false);
1150         virDomainObjListRemove(driver->domains, vm);
1151         vm = NULL;
1152         goto cleanup;
1153     }
1154
1155     event = virDomainEventNewFromObj(vm,
1156                                      VIR_DOMAIN_EVENT_STARTED,
1157                                      VIR_DOMAIN_EVENT_STARTED_BOOTED);
1158     virDomainAuditStart(vm, "booted", true);
1159
1160     dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1161     if (dom)
1162         dom->id = vm->def->id;
1163
1164 cleanup:
1165     virDomainDefFree(def);
1166     if (vm)
1167         virObjectUnlock(vm);
1168     if (event)
1169         virDomainEventStateQueue(driver->domainEventState, event);
1170     virObjectUnref(caps);
1171     virObjectUnref(cfg);
1172     virNWFilterUnlockFilterUpdates();
1173     return dom;
1174 }
1175
1176
1177 static virDomainPtr
1178 lxcDomainCreateXML(virConnectPtr conn,
1179                    const char *xml,
1180                    unsigned int flags) {
1181     return lxcDomainCreateXMLWithFiles(conn, xml, 0, NULL,  flags);
1182 }
1183
1184
1185 static int lxcDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
1186 {
1187     virLXCDriverPtr driver = dom->conn->privateData;
1188     virDomainObjPtr vm;
1189     int ret = -1;
1190
1191     memset(seclabel, 0, sizeof(*seclabel));
1192
1193     if (!(vm = lxcDomObjFromDomain(dom)))
1194         goto cleanup;
1195
1196     if (virDomainGetSecurityLabelEnsureACL(dom->conn, vm->def) < 0)
1197         goto cleanup;
1198
1199     if (!virDomainVirtTypeToString(vm->def->virtType)) {
1200         virReportError(VIR_ERR_INTERNAL_ERROR,
1201                        _("unknown virt type in domain definition '%d'"),
1202                        vm->def->virtType);
1203         goto cleanup;
1204     }
1205
1206     /*
1207      * Theoretically, the pid can be replaced during this operation and
1208      * return the label of a different process.  If atomicity is needed,
1209      * further validation will be required.
1210      *
1211      * Comment from Dan Berrange:
1212      *
1213      *   Well the PID as stored in the virDomainObjPtr can't be changed
1214      *   because you've got a locked object.  The OS level PID could have
1215      *   exited, though and in extreme circumstances have cycled through all
1216      *   PIDs back to ours. We could sanity check that our PID still exists
1217      *   after reading the label, by checking that our FD connecting to the
1218      *   LXC monitor hasn't seen SIGHUP/ERR on poll().
1219      */
1220     if (virDomainObjIsActive(vm)) {
1221         virLXCDomainObjPrivatePtr priv = vm->privateData;
1222
1223         if (!priv->initpid) {
1224             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
1225                            _("Init pid is not yet available"));
1226             goto cleanup;
1227         }
1228
1229         if (virSecurityManagerGetProcessLabel(driver->securityManager,
1230                                               vm->def, priv->initpid, seclabel) < 0) {
1231             virReportError(VIR_ERR_INTERNAL_ERROR,
1232                            "%s", _("Failed to get security label"));
1233             goto cleanup;
1234         }
1235     }
1236
1237     ret = 0;
1238
1239 cleanup:
1240     if (vm)
1241         virObjectUnlock(vm);
1242     return ret;
1243 }
1244
1245 static int lxcNodeGetSecurityModel(virConnectPtr conn,
1246                                    virSecurityModelPtr secmodel)
1247 {
1248     virLXCDriverPtr driver = conn->privateData;
1249     virCapsPtr caps = NULL;
1250     int ret = 0;
1251
1252     memset(secmodel, 0, sizeof(*secmodel));
1253
1254     if (virNodeGetSecurityModelEnsureACL(conn) < 0)
1255         goto cleanup;
1256
1257     if (!(caps = virLXCDriverGetCapabilities(driver, false)))
1258         goto cleanup;
1259
1260     /* we treat no driver as success, but simply return no data in *secmodel */
1261     if (caps->host.nsecModels == 0
1262         || caps->host.secModels[0].model == NULL)
1263         goto cleanup;
1264
1265     if (!virStrcpy(secmodel->model, caps->host.secModels[0].model,
1266                    VIR_SECURITY_MODEL_BUFLEN)) {
1267         virReportError(VIR_ERR_INTERNAL_ERROR,
1268                        _("security model string exceeds max %d bytes"),
1269                        VIR_SECURITY_MODEL_BUFLEN - 1);
1270         ret = -1;
1271         goto cleanup;
1272     }
1273
1274     if (!virStrcpy(secmodel->doi, caps->host.secModels[0].doi,
1275                    VIR_SECURITY_DOI_BUFLEN)) {
1276         virReportError(VIR_ERR_INTERNAL_ERROR,
1277                        _("security DOI string exceeds max %d bytes"),
1278                        VIR_SECURITY_DOI_BUFLEN-1);
1279         ret = -1;
1280         goto cleanup;
1281     }
1282
1283 cleanup:
1284     virObjectUnref(caps);
1285     return ret;
1286 }
1287
1288
1289 static int
1290 lxcConnectDomainEventRegister(virConnectPtr conn,
1291                               virConnectDomainEventCallback callback,
1292                               void *opaque,
1293                               virFreeCallback freecb)
1294 {
1295     virLXCDriverPtr driver = conn->privateData;
1296     int ret;
1297
1298     if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
1299         return -1;
1300
1301     ret = virDomainEventStateRegister(conn,
1302                                       driver->domainEventState,
1303                                       callback, opaque, freecb);
1304
1305     return ret;
1306 }
1307
1308
1309 static int
1310 lxcConnectDomainEventDeregister(virConnectPtr conn,
1311                                 virConnectDomainEventCallback callback)
1312 {
1313     virLXCDriverPtr driver = conn->privateData;
1314     int ret;
1315
1316     if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
1317         return -1;
1318
1319     ret = virDomainEventStateDeregister(conn,
1320                                         driver->domainEventState,
1321                                         callback);
1322
1323     return ret;
1324 }
1325
1326
1327 static int
1328 lxcConnectDomainEventRegisterAny(virConnectPtr conn,
1329                                  virDomainPtr dom,
1330                                  int eventID,
1331                                  virConnectDomainEventGenericCallback callback,
1332                                  void *opaque,
1333                                  virFreeCallback freecb)
1334 {
1335     virLXCDriverPtr driver = conn->privateData;
1336     int ret;
1337
1338     if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
1339         return -1;
1340
1341     if (virDomainEventStateRegisterID(conn,
1342                                       driver->domainEventState,
1343                                       dom, eventID,
1344                                       callback, opaque, freecb, &ret) < 0)
1345         ret = -1;
1346
1347     return ret;
1348 }
1349
1350
1351 static int
1352 lxcConnectDomainEventDeregisterAny(virConnectPtr conn,
1353                                    int callbackID)
1354 {
1355     virLXCDriverPtr driver = conn->privateData;
1356     int ret;
1357
1358     if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
1359         return -1;
1360
1361     ret = virDomainEventStateDeregisterID(conn,
1362                                           driver->domainEventState,
1363                                           callbackID);
1364
1365     return ret;
1366 }
1367
1368
1369 /**
1370  * lxcDomainDestroyFlags:
1371  * @dom: pointer to domain to destroy
1372  * @flags: an OR'ed set of virDomainDestroyFlags
1373  *
1374  * Sends SIGKILL to container root process to terminate the container
1375  *
1376  * Returns 0 on success or -1 in case of error
1377  */
1378 static int
1379 lxcDomainDestroyFlags(virDomainPtr dom,
1380                       unsigned int flags)
1381 {
1382     virLXCDriverPtr driver = dom->conn->privateData;
1383     virDomainObjPtr vm;
1384     virDomainEventPtr event = NULL;
1385     int ret = -1;
1386     virLXCDomainObjPrivatePtr priv;
1387
1388     virCheckFlags(0, -1);
1389
1390     if (!(vm = lxcDomObjFromDomain(dom)))
1391         goto cleanup;
1392
1393     if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
1394         goto cleanup;
1395
1396     if (!virDomainObjIsActive(vm)) {
1397         virReportError(VIR_ERR_OPERATION_INVALID,
1398                        "%s", _("Domain is not running"));
1399         goto cleanup;
1400     }
1401
1402     priv = vm->privateData;
1403     ret = virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
1404     event = virDomainEventNewFromObj(vm,
1405                                      VIR_DOMAIN_EVENT_STOPPED,
1406                                      VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1407     priv->doneStopEvent = true;
1408     virDomainAuditStop(vm, "destroyed");
1409     if (!vm->persistent) {
1410         virDomainObjListRemove(driver->domains, vm);
1411         vm = NULL;
1412     }
1413
1414 cleanup:
1415     if (vm)
1416         virObjectUnlock(vm);
1417     if (event)
1418         virDomainEventStateQueue(driver->domainEventState, event);
1419     return ret;
1420 }
1421
1422 /**
1423  * lxcDomainDestroy:
1424  * @dom: pointer to domain to destroy
1425  *
1426  * Sends SIGKILL to container root process to terminate the container
1427  *
1428  * Returns 0 on success or -1 in case of error
1429  */
1430 static int
1431 lxcDomainDestroy(virDomainPtr dom)
1432 {
1433     return lxcDomainDestroyFlags(dom, 0);
1434 }
1435
1436 static int lxcCheckNetNsSupport(void)
1437 {
1438     const char *argv[] = {"ip", "link", "set", "lo", "netns", "-1", NULL};
1439     int ip_rc;
1440
1441     if (virRun(argv, &ip_rc) < 0 ||
1442         !(WIFEXITED(ip_rc) && (WEXITSTATUS(ip_rc) != 255)))
1443         return 0;
1444
1445     if (lxcContainerAvailable(LXC_CONTAINER_FEATURE_NET) < 0)
1446         return 0;
1447
1448     return 1;
1449 }
1450
1451
1452 static virSecurityManagerPtr
1453 lxcSecurityInit(virLXCDriverConfigPtr cfg)
1454 {
1455     VIR_INFO("lxcSecurityInit %s", cfg->securityDriverName);
1456     virSecurityManagerPtr mgr = virSecurityManagerNew(cfg->securityDriverName,
1457                                                       LXC_DRIVER_NAME,
1458                                                       false,
1459                                                       cfg->securityDefaultConfined,
1460                                                       cfg->securityRequireConfined);
1461     if (!mgr)
1462         goto error;
1463
1464     return mgr;
1465
1466 error:
1467     VIR_ERROR(_("Failed to initialize security drivers"));
1468     virObjectUnref(mgr);
1469     return NULL;
1470 }
1471
1472
1473 static int lxcStateInitialize(bool privileged,
1474                               virStateInhibitCallback callback ATTRIBUTE_UNUSED,
1475                               void *opaque ATTRIBUTE_UNUSED)
1476 {
1477     virCapsPtr caps = NULL;
1478     const char *ld;
1479     virLXCDriverConfigPtr cfg = NULL;
1480
1481     /* Valgrind gets very annoyed when we clone containers, so
1482      * disable LXC when under valgrind
1483      * XXX remove this when valgrind is fixed
1484      */
1485     ld = virGetEnvBlockSUID("LD_PRELOAD");
1486     if (ld && strstr(ld, "vgpreload")) {
1487         VIR_INFO("Running under valgrind, disabling driver");
1488         return 0;
1489     }
1490
1491     /* Check that the user is root, silently disable if not */
1492     if (!privileged) {
1493         VIR_INFO("Not running privileged, disabling driver");
1494         return 0;
1495     }
1496
1497     /* Check that this is a container enabled kernel */
1498     if (lxcContainerAvailable(0) < 0) {
1499         VIR_INFO("LXC support not available in this kernel, disabling driver");
1500         return 0;
1501     }
1502
1503     if (VIR_ALLOC(lxc_driver) < 0) {
1504         return -1;
1505     }
1506     if (virMutexInit(&lxc_driver->lock) < 0) {
1507         VIR_FREE(lxc_driver);
1508         return -1;
1509     }
1510
1511     if (!(lxc_driver->domains = virDomainObjListNew()))
1512         goto cleanup;
1513
1514     lxc_driver->domainEventState = virDomainEventStateNew();
1515     if (!lxc_driver->domainEventState)
1516         goto cleanup;
1517
1518     lxc_driver->hostsysinfo = virSysinfoRead();
1519
1520     if (!(lxc_driver->config = cfg = virLXCDriverConfigNew()))
1521         goto cleanup;
1522
1523     cfg->log_libvirtd = 0; /* by default log to container logfile */
1524     cfg->have_netns = lxcCheckNetNsSupport();
1525
1526     /* Call function to load lxc driver configuration information */
1527     if (virLXCLoadDriverConfig(cfg, SYSCONFDIR "/libvirt/lxc.conf") < 0)
1528         goto cleanup;
1529
1530     if (!(lxc_driver->securityManager = lxcSecurityInit(cfg)))
1531         goto cleanup;
1532
1533     if ((lxc_driver->activeUsbHostdevs = virUSBDeviceListNew()) == NULL)
1534         goto cleanup;
1535
1536     if ((virLXCDriverGetCapabilities(lxc_driver, true)) == NULL)
1537         goto cleanup;
1538
1539     if (!(lxc_driver->xmlopt = lxcDomainXMLConfInit()))
1540         goto cleanup;
1541
1542     if (!(lxc_driver->closeCallbacks = virCloseCallbacksNew()))
1543         goto cleanup;
1544
1545     if (!(caps = virLXCDriverGetCapabilities(lxc_driver, false)))
1546         goto cleanup;
1547
1548     /* Get all the running persistent or transient configs first */
1549     if (virDomainObjListLoadAllConfigs(lxc_driver->domains,
1550                                        cfg->stateDir,
1551                                        NULL, 1,
1552                                        caps,
1553                                        lxc_driver->xmlopt,
1554                                        1 << VIR_DOMAIN_VIRT_LXC,
1555                                        NULL, NULL) < 0)
1556         goto cleanup;
1557
1558     virLXCProcessReconnectAll(lxc_driver, lxc_driver->domains);
1559
1560     /* Then inactive persistent configs */
1561     if (virDomainObjListLoadAllConfigs(lxc_driver->domains,
1562                                        cfg->configDir,
1563                                        cfg->autostartDir, 0,
1564                                        caps,
1565                                        lxc_driver->xmlopt,
1566                                        1 << VIR_DOMAIN_VIRT_LXC,
1567                                        NULL, NULL) < 0)
1568         goto cleanup;
1569
1570     virNWFilterRegisterCallbackDriver(&lxcCallbackDriver);
1571     return 0;
1572
1573 cleanup:
1574     virObjectUnref(caps);
1575     lxcStateCleanup();
1576     return -1;
1577 }
1578
1579 /**
1580  * lxcStateAutoStart:
1581  *
1582  * Function to autostart the LXC daemons
1583  */
1584 static void lxcStateAutoStart(void)
1585 {
1586     if (!lxc_driver)
1587         return;
1588
1589     virLXCProcessAutostartAll(lxc_driver);
1590 }
1591
1592 static void lxcNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
1593 {
1594     virLXCDriverPtr driver = opaque;
1595
1596     if (newVM) {
1597         virDomainEventPtr event =
1598             virDomainEventNewFromObj(vm,
1599                                      VIR_DOMAIN_EVENT_DEFINED,
1600                                      VIR_DOMAIN_EVENT_DEFINED_ADDED);
1601         if (event)
1602             virDomainEventStateQueue(driver->domainEventState, event);
1603     }
1604 }
1605
1606 /**
1607  * lxcStateReload:
1608  *
1609  * Function to restart the LXC driver, it will recheck the configuration
1610  * files and perform autostart
1611  */
1612 static int
1613 lxcStateReload(void) {
1614     virLXCDriverConfigPtr cfg = NULL;
1615     virCapsPtr caps = NULL;
1616
1617     if (!lxc_driver)
1618         return 0;
1619
1620     if (!(caps = virLXCDriverGetCapabilities(lxc_driver, false)))
1621         return -1;
1622
1623     cfg = virLXCDriverGetConfig(lxc_driver);
1624
1625     virDomainObjListLoadAllConfigs(lxc_driver->domains,
1626                                    cfg->configDir,
1627                                    cfg->autostartDir, 0,
1628                                    caps,
1629                                    lxc_driver->xmlopt,
1630                                    1 << VIR_DOMAIN_VIRT_LXC,
1631                                    lxcNotifyLoadDomain, lxc_driver);
1632     virObjectUnref(caps);
1633     virObjectUnref(cfg);
1634     return 0;
1635 }
1636
1637 static int lxcStateCleanup(void)
1638 {
1639     if (lxc_driver == NULL)
1640         return -1;
1641
1642     virNWFilterUnRegisterCallbackDriver(&lxcCallbackDriver);
1643     virObjectUnref(lxc_driver->domains);
1644     virDomainEventStateFree(lxc_driver->domainEventState);
1645
1646     virObjectUnref(lxc_driver->closeCallbacks);
1647
1648     virSysinfoDefFree(lxc_driver->hostsysinfo);
1649
1650     virObjectUnref(lxc_driver->activeUsbHostdevs);
1651     virObjectUnref(lxc_driver->caps);
1652     virObjectUnref(lxc_driver->securityManager);
1653     virObjectUnref(lxc_driver->xmlopt);
1654     virObjectUnref(lxc_driver->config);
1655     virMutexDestroy(&lxc_driver->lock);
1656     VIR_FREE(lxc_driver);
1657
1658     return 0;
1659 }
1660
1661
1662 static int lxcConnectGetVersion(virConnectPtr conn, unsigned long *version)
1663 {
1664     struct utsname ver;
1665
1666     uname(&ver);
1667
1668     if (virConnectGetVersionEnsureACL(conn) < 0)
1669         return -1;
1670
1671     if (virParseVersionString(ver.release, version, true) < 0) {
1672         virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown release: %s"), ver.release);
1673         return -1;
1674     }
1675
1676     return 0;
1677 }
1678
1679
1680 static char *lxcConnectGetHostname(virConnectPtr conn)
1681 {
1682     if (virConnectGetHostnameEnsureACL(conn) < 0)
1683         return NULL;
1684
1685     return virGetHostname();
1686 }
1687
1688
1689
1690 /*
1691  * check whether the host supports CFS bandwidth
1692  *
1693  * Return 1 when CFS bandwidth is supported, 0 when CFS bandwidth is not
1694  * supported, -1 on error.
1695  */
1696 static int lxcGetCpuBWStatus(virCgroupPtr cgroup)
1697 {
1698     char *cfs_period_path = NULL;
1699     int ret = -1;
1700
1701     if (!cgroup)
1702         return 0;
1703
1704     if (virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_CPU,
1705                                   "cpu.cfs_period_us", &cfs_period_path) < 0) {
1706         VIR_INFO("cannot get the path of cgroup CPU controller");
1707         ret = 0;
1708         goto cleanup;
1709     }
1710
1711     if (access(cfs_period_path, F_OK) < 0) {
1712         ret = 0;
1713     } else {
1714         ret = 1;
1715     }
1716
1717 cleanup:
1718     VIR_FREE(cfs_period_path);
1719     return ret;
1720 }
1721
1722
1723 static char *lxcDomainGetSchedulerType(virDomainPtr dom,
1724                                        int *nparams)
1725 {
1726     char *ret = NULL;
1727     int rc;
1728     virDomainObjPtr vm;
1729     virLXCDomainObjPrivatePtr priv;
1730
1731     if (!(vm = lxcDomObjFromDomain(dom)))
1732         goto cleanup;
1733
1734     priv = vm->privateData;
1735
1736     if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
1737         goto cleanup;
1738
1739     /* Domain not running, thus no cgroups - return defaults */
1740     if (!virDomainObjIsActive(vm)) {
1741         if (nparams)
1742             *nparams = 3;
1743         ignore_value(VIR_STRDUP(ret, "posix"));
1744         goto cleanup;
1745     }
1746
1747     if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
1748         virReportError(VIR_ERR_OPERATION_INVALID,
1749                        "%s", _("cgroup CPU controller is not mounted"));
1750         goto cleanup;
1751     }
1752
1753     if (nparams) {
1754         rc = lxcGetCpuBWStatus(priv->cgroup);
1755         if (rc < 0)
1756             goto cleanup;
1757         else if (rc == 0)
1758             *nparams = 1;
1759         else
1760             *nparams = 3;
1761     }
1762
1763     ignore_value(VIR_STRDUP(ret, "posix"));
1764
1765 cleanup:
1766     if (vm)
1767         virObjectUnlock(vm);
1768     return ret;
1769 }
1770
1771
1772 static int
1773 lxcGetVcpuBWLive(virCgroupPtr cgroup, unsigned long long *period,
1774                  long long *quota)
1775 {
1776     if (virCgroupGetCpuCfsPeriod(cgroup, period) < 0)
1777         return -1;
1778
1779     if (virCgroupGetCpuCfsQuota(cgroup, quota) < 0)
1780         return -1;
1781
1782     return 0;
1783 }
1784
1785
1786 static int lxcSetVcpuBWLive(virCgroupPtr cgroup, unsigned long long period,
1787                             long long quota)
1788 {
1789     unsigned long long old_period;
1790
1791     if (period == 0 && quota == 0)
1792         return 0;
1793
1794     if (period) {
1795         /* get old period, and we can rollback if set quota failed */
1796         if (virCgroupGetCpuCfsPeriod(cgroup, &old_period) < 0)
1797             return -1;
1798
1799         if (virCgroupSetCpuCfsPeriod(cgroup, period) < 0)
1800             return -1;
1801     }
1802
1803     if (quota) {
1804         if (virCgroupSetCpuCfsQuota(cgroup, quota) < 0)
1805             goto error;
1806     }
1807
1808     return 0;
1809
1810 error:
1811     if (period) {
1812         virErrorPtr saved = virSaveLastError();
1813         virCgroupSetCpuCfsPeriod(cgroup, old_period);
1814         if (saved) {
1815             virSetError(saved);
1816             virFreeError(saved);
1817         }
1818     }
1819
1820     return -1;
1821 }
1822
1823
1824 static int
1825 lxcDomainSetSchedulerParametersFlags(virDomainPtr dom,
1826                                      virTypedParameterPtr params,
1827                                      int nparams,
1828                                      unsigned int flags)
1829 {
1830     virLXCDriverPtr driver = dom->conn->privateData;
1831     virCapsPtr caps = NULL;
1832     size_t i;
1833     virDomainObjPtr vm = NULL;
1834     virDomainDefPtr vmdef = NULL;
1835     int ret = -1;
1836     int rc;
1837     virLXCDomainObjPrivatePtr priv;
1838     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
1839
1840     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
1841                   VIR_DOMAIN_AFFECT_CONFIG, -1);
1842     if (virTypedParamsValidate(params, nparams,
1843                                VIR_DOMAIN_SCHEDULER_CPU_SHARES,
1844                                VIR_TYPED_PARAM_ULLONG,
1845                                VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
1846                                VIR_TYPED_PARAM_ULLONG,
1847                                VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
1848                                VIR_TYPED_PARAM_LLONG,
1849                                NULL) < 0)
1850         return -1;
1851
1852     if (!(vm = lxcDomObjFromDomain(dom)))
1853         goto cleanup;
1854
1855     priv = vm->privateData;
1856
1857     if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
1858         goto cleanup;
1859
1860     if (!(caps = virLXCDriverGetCapabilities(driver, false)))
1861         goto cleanup;
1862
1863     if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
1864                                         vm, &flags, &vmdef) < 0)
1865         goto cleanup;
1866
1867     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
1868         /* Make a copy for updated domain. */
1869         vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
1870         if (!vmdef)
1871             goto cleanup;
1872     }
1873
1874     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
1875         if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
1876             virReportError(VIR_ERR_OPERATION_INVALID,
1877                            "%s", _("cgroup CPU controller is not mounted"));
1878             goto cleanup;
1879         }
1880     }
1881
1882     for (i = 0; i < nparams; i++) {
1883         virTypedParameterPtr param = &params[i];
1884
1885         if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CPU_SHARES)) {
1886             if (flags & VIR_DOMAIN_AFFECT_LIVE) {
1887                 if (virCgroupSetCpuShares(priv->cgroup, params[i].value.ul) < 0)
1888                     goto cleanup;
1889
1890                 vm->def->cputune.shares = params[i].value.ul;
1891             }
1892
1893             if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
1894                 vmdef->cputune.shares = params[i].value.ul;
1895             }
1896         } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD)) {
1897             if (flags & VIR_DOMAIN_AFFECT_LIVE) {
1898                 rc = lxcSetVcpuBWLive(priv->cgroup, params[i].value.ul, 0);
1899                 if (rc != 0)
1900                     goto cleanup;
1901
1902                 if (params[i].value.ul)
1903                     vm->def->cputune.period = params[i].value.ul;
1904             }
1905
1906             if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
1907                 vmdef->cputune.period = params[i].value.ul;
1908             }
1909         } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA)) {
1910             if (flags & VIR_DOMAIN_AFFECT_LIVE) {
1911                 rc = lxcSetVcpuBWLive(priv->cgroup, 0, params[i].value.l);
1912                 if (rc != 0)
1913                     goto cleanup;
1914
1915                 if (params[i].value.l)
1916                     vm->def->cputune.quota = params[i].value.l;
1917             }
1918
1919             if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
1920                 vmdef->cputune.quota = params[i].value.l;
1921             }
1922         }
1923     }
1924
1925     if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1926         goto cleanup;
1927
1928
1929     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
1930         rc = virDomainSaveConfig(cfg->configDir, vmdef);
1931         if (rc < 0)
1932             goto cleanup;
1933
1934         virDomainObjAssignDef(vm, vmdef, false, NULL);
1935         vmdef = NULL;
1936     }
1937
1938     ret = 0;
1939
1940 cleanup:
1941     virDomainDefFree(vmdef);
1942     if (vm)
1943         virObjectUnlock(vm);
1944     virObjectUnref(caps);
1945     virObjectUnref(cfg);
1946     return ret;
1947 }
1948
1949 static int
1950 lxcDomainSetSchedulerParameters(virDomainPtr domain,
1951                                 virTypedParameterPtr params,
1952                                 int nparams)
1953 {
1954     return lxcDomainSetSchedulerParametersFlags(domain, params, nparams, 0);
1955 }
1956
1957 static int
1958 lxcDomainGetSchedulerParametersFlags(virDomainPtr dom,
1959                                      virTypedParameterPtr params,
1960                                      int *nparams,
1961                                      unsigned int flags)
1962 {
1963     virLXCDriverPtr driver = dom->conn->privateData;
1964     virCapsPtr caps = NULL;
1965     virDomainObjPtr vm = NULL;
1966     virDomainDefPtr persistentDef;
1967     unsigned long long shares = 0;
1968     unsigned long long period = 0;
1969     long long quota = 0;
1970     int ret = -1;
1971     int rc;
1972     bool cpu_bw_status = false;
1973     int saved_nparams = 0;
1974     virLXCDomainObjPrivatePtr priv;
1975
1976     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
1977                   VIR_DOMAIN_AFFECT_CONFIG, -1);
1978
1979     if (!(vm = lxcDomObjFromDomain(dom)))
1980         goto cleanup;
1981
1982     priv = vm->privateData;
1983
1984     if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
1985         goto cleanup;
1986
1987     if (*nparams > 1) {
1988         rc = lxcGetCpuBWStatus(priv->cgroup);
1989         if (rc < 0)
1990             goto cleanup;
1991         cpu_bw_status = !!rc;
1992     }
1993
1994     if (!(caps = virLXCDriverGetCapabilities(driver, false)))
1995         goto cleanup;
1996
1997     if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
1998                                         vm, &flags, &persistentDef) < 0)
1999         goto cleanup;
2000
2001     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
2002         shares = persistentDef->cputune.shares;
2003         if (*nparams > 1) {
2004             period = persistentDef->cputune.period;
2005             quota = persistentDef->cputune.quota;
2006             cpu_bw_status = true; /* Allow copy of data to params[] */
2007         }
2008         goto out;
2009     }
2010
2011     if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
2012         virReportError(VIR_ERR_OPERATION_INVALID,
2013                        "%s", _("cgroup CPU controller is not mounted"));
2014         goto cleanup;
2015     }
2016
2017     if (virCgroupGetCpuShares(priv->cgroup, &shares) < 0)
2018         goto cleanup;
2019
2020     if (*nparams > 1 && cpu_bw_status) {
2021         rc = lxcGetVcpuBWLive(priv->cgroup, &period, &quota);
2022         if (rc != 0)
2023             goto cleanup;
2024     }
2025 out:
2026     if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_CPU_SHARES,
2027                                 VIR_TYPED_PARAM_ULLONG, shares) < 0)
2028         goto cleanup;
2029     saved_nparams++;
2030
2031     if (cpu_bw_status) {
2032         if (*nparams > saved_nparams) {
2033             if (virTypedParameterAssign(&params[1],
2034                                         VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
2035                                         VIR_TYPED_PARAM_ULLONG, period) < 0)
2036                 goto cleanup;
2037             saved_nparams++;
2038         }
2039
2040         if (*nparams > saved_nparams) {
2041             if (virTypedParameterAssign(&params[2],
2042                                         VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
2043                                         VIR_TYPED_PARAM_LLONG, quota) < 0)
2044                 goto cleanup;
2045             saved_nparams++;
2046         }
2047     }
2048
2049     *nparams = saved_nparams;
2050
2051     ret = 0;
2052
2053 cleanup:
2054     if (vm)
2055         virObjectUnlock(vm);
2056     virObjectUnref(caps);
2057     return ret;
2058 }
2059
2060 static int
2061 lxcDomainGetSchedulerParameters(virDomainPtr domain,
2062                                 virTypedParameterPtr params,
2063                                 int *nparams)
2064 {
2065     return lxcDomainGetSchedulerParametersFlags(domain, params, nparams, 0);
2066 }
2067
2068
2069 static int
2070 lxcDomainSetBlkioParameters(virDomainPtr dom,
2071                             virTypedParameterPtr params,
2072                             int nparams,
2073                             unsigned int flags)
2074 {
2075     virLXCDriverPtr driver = dom->conn->privateData;
2076     virCapsPtr caps = NULL;
2077     size_t i;
2078     virDomainObjPtr vm = NULL;
2079     virDomainDefPtr persistentDef = NULL;
2080     int ret = -1;
2081     virLXCDomainObjPrivatePtr priv;
2082     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
2083
2084     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
2085                   VIR_DOMAIN_AFFECT_CONFIG, -1);
2086     if (virTypedParamsValidate(params, nparams,
2087                                VIR_DOMAIN_BLKIO_WEIGHT,
2088                                VIR_TYPED_PARAM_UINT,
2089                                NULL) < 0)
2090         return -1;
2091
2092     if (!(vm = lxcDomObjFromDomain(dom)))
2093         goto cleanup;
2094
2095     priv = vm->privateData;
2096
2097     if (virDomainSetBlkioParametersEnsureACL(dom->conn, vm->def, flags) < 0)
2098         goto cleanup;
2099
2100     if (!(caps = virLXCDriverGetCapabilities(driver, false)))
2101         goto cleanup;
2102
2103     if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
2104                                         vm, &flags, &persistentDef) < 0)
2105         goto cleanup;
2106
2107     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
2108         if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
2109             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2110                            _("blkio cgroup isn't mounted"));
2111             goto cleanup;
2112         }
2113
2114         for (i = 0; i < nparams; i++) {
2115             virTypedParameterPtr param = &params[i];
2116
2117             if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
2118                 if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
2119                     virReportError(VIR_ERR_INVALID_ARG, "%s",
2120                                    _("out of blkio weight range."));
2121                     goto cleanup;
2122                 }
2123
2124                 if (virCgroupSetBlkioWeight(priv->cgroup, params[i].value.ui) < 0)
2125                     goto cleanup;
2126             }
2127         }
2128     }
2129     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
2130         /* Clang can't see that if we get here, persistentDef was set.  */
2131         sa_assert(persistentDef);
2132
2133         for (i = 0; i < nparams; i++) {
2134             virTypedParameterPtr param = &params[i];
2135
2136             if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
2137                 if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
2138                     virReportError(VIR_ERR_INVALID_ARG, "%s",
2139                                    _("out of blkio weight range."));
2140                     goto cleanup;
2141                 }
2142
2143                 persistentDef->blkio.weight = params[i].value.ui;
2144             }
2145         }
2146
2147         if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
2148             goto cleanup;
2149     }
2150
2151     ret = 0;
2152 cleanup:
2153     if (vm)
2154         virObjectUnlock(vm);
2155     virObjectUnref(caps);
2156     virObjectUnref(cfg);
2157     return ret;
2158 }
2159
2160
2161 #define LXC_NB_BLKIO_PARAM  1
2162 static int
2163 lxcDomainGetBlkioParameters(virDomainPtr dom,
2164                             virTypedParameterPtr params,
2165                             int *nparams,
2166                             unsigned int flags)
2167 {
2168     virLXCDriverPtr driver = dom->conn->privateData;
2169     virCapsPtr caps = NULL;
2170     size_t i;
2171     virDomainObjPtr vm = NULL;
2172     virDomainDefPtr persistentDef = NULL;
2173     unsigned int val;
2174     int ret = -1;
2175     virLXCDomainObjPrivatePtr priv;
2176
2177     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
2178                   VIR_DOMAIN_AFFECT_CONFIG, -1);
2179
2180     if (!(vm = lxcDomObjFromDomain(dom)))
2181         goto cleanup;
2182
2183     priv = vm->privateData;
2184
2185     if (virDomainGetBlkioParametersEnsureACL(dom->conn, vm->def) < 0)
2186         goto cleanup;
2187
2188     if ((*nparams) == 0) {
2189         /* Current number of blkio parameters supported by cgroups */
2190         *nparams = LXC_NB_BLKIO_PARAM;
2191         ret = 0;
2192         goto cleanup;
2193     }
2194
2195     if (!(caps = virLXCDriverGetCapabilities(driver, false)))
2196         goto cleanup;
2197
2198     if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
2199                                         vm, &flags, &persistentDef) < 0)
2200         goto cleanup;
2201
2202     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
2203         if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
2204             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2205                            _("blkio cgroup isn't mounted"));
2206             goto cleanup;
2207         }
2208
2209         for (i = 0; i < *nparams && i < LXC_NB_BLKIO_PARAM; i++) {
2210             virTypedParameterPtr param = &params[i];
2211             val = 0;
2212
2213             switch (i) {
2214             case 0: /* fill blkio weight here */
2215                 if (virCgroupGetBlkioWeight(priv->cgroup, &val) < 0)
2216                     goto cleanup;
2217                 if (virTypedParameterAssign(param, VIR_DOMAIN_BLKIO_WEIGHT,
2218                                             VIR_TYPED_PARAM_UINT, val) < 0)
2219                     goto cleanup;
2220                 break;
2221
2222             /* coverity[dead_error_begin] */
2223             default:
2224                 break;
2225                 /* should not hit here */
2226             }
2227         }
2228     } else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
2229         for (i = 0; i < *nparams && i < LXC_NB_BLKIO_PARAM; i++) {
2230             virTypedParameterPtr param = &params[i];
2231
2232             switch (i) {
2233             case 0: /* fill blkio weight here */
2234                 if (virTypedParameterAssign(param, VIR_DOMAIN_BLKIO_WEIGHT,
2235                                             VIR_TYPED_PARAM_UINT,
2236                                             persistentDef->blkio.weight) < 0)
2237                     goto cleanup;
2238                 break;
2239
2240             /* coverity[dead_error_begin] */
2241             default:
2242                 break;
2243                 /* should not hit here */
2244             }
2245         }
2246     }
2247
2248     if (LXC_NB_BLKIO_PARAM < *nparams)
2249         *nparams = LXC_NB_BLKIO_PARAM;
2250     ret = 0;
2251
2252 cleanup:
2253     if (vm)
2254         virObjectUnlock(vm);
2255     virObjectUnref(caps);
2256     return ret;
2257 }
2258
2259
2260 #ifdef __linux__
2261 static int
2262 lxcDomainInterfaceStats(virDomainPtr dom,
2263                         const char *path,
2264                         struct _virDomainInterfaceStats *stats)
2265 {
2266     virDomainObjPtr vm;
2267     size_t i;
2268     int ret = -1;
2269
2270     if (!(vm = lxcDomObjFromDomain(dom)))
2271         goto cleanup;
2272
2273     if (virDomainInterfaceStatsEnsureACL(dom->conn, vm->def) < 0)
2274         goto cleanup;
2275
2276     if (!virDomainObjIsActive(vm)) {
2277         virReportError(VIR_ERR_OPERATION_INVALID,
2278                        "%s", _("Domain is not running"));
2279         goto cleanup;
2280     }
2281
2282     /* Check the path is one of the domain's network interfaces. */
2283     for (i = 0; i < vm->def->nnets; i++) {
2284         if (vm->def->nets[i]->ifname &&
2285             STREQ(vm->def->nets[i]->ifname, path)) {
2286             ret = 0;
2287             break;
2288         }
2289     }
2290
2291     if (ret == 0)
2292         ret = linuxDomainInterfaceStats(path, stats);
2293     else
2294         virReportError(VIR_ERR_INVALID_ARG,
2295                        _("Invalid path, '%s' is not a known interface"), path);
2296
2297 cleanup:
2298     if (vm)
2299         virObjectUnlock(vm);
2300     return ret;
2301 }
2302 #else
2303 static int
2304 lxcDomainInterfaceStats(virDomainPtr dom,
2305                         const char *path ATTRIBUTE_UNUSED,
2306                         struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
2307 {
2308     virReportError(VIR_ERR_NO_SUPPORT, "%s", __FUNCTION__);
2309     return -1;
2310 }
2311 #endif
2312
2313 static int lxcDomainGetAutostart(virDomainPtr dom,
2314                                    int *autostart) {
2315     virDomainObjPtr vm;
2316     int ret = -1;
2317
2318     if (!(vm = lxcDomObjFromDomain(dom)))
2319         goto cleanup;
2320
2321     if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
2322         goto cleanup;
2323
2324     *autostart = vm->autostart;
2325     ret = 0;
2326
2327 cleanup:
2328     if (vm)
2329         virObjectUnlock(vm);
2330     return ret;
2331 }
2332
2333 static int lxcDomainSetAutostart(virDomainPtr dom,
2334                                    int autostart)
2335 {
2336     virLXCDriverPtr driver = dom->conn->privateData;
2337     virDomainObjPtr vm;
2338     char *configFile = NULL, *autostartLink = NULL;
2339     int ret = -1;
2340     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
2341
2342     if (!(vm = lxcDomObjFromDomain(dom)))
2343         goto cleanup;
2344
2345     if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
2346         goto cleanup;
2347
2348     if (!vm->persistent) {
2349         virReportError(VIR_ERR_OPERATION_INVALID,
2350                        "%s", _("Cannot set autostart for transient domain"));
2351         goto cleanup;
2352     }
2353
2354     autostart = (autostart != 0);
2355
2356     if (vm->autostart == autostart) {
2357         ret = 0;
2358         goto cleanup;
2359     }
2360
2361     configFile = virDomainConfigFile(cfg->configDir,
2362                                      vm->def->name);
2363     if (configFile == NULL)
2364         goto cleanup;
2365     autostartLink = virDomainConfigFile(cfg->autostartDir,
2366                                         vm->def->name);
2367     if (autostartLink == NULL)
2368         goto cleanup;
2369
2370     if (autostart) {
2371         if (virFileMakePath(cfg->autostartDir) < 0) {
2372             virReportSystemError(errno,
2373                                  _("Cannot create autostart directory %s"),
2374                                  cfg->autostartDir);
2375             goto cleanup;
2376         }
2377
2378         if (symlink(configFile, autostartLink) < 0) {
2379             virReportSystemError(errno,
2380                                  _("Failed to create symlink '%s to '%s'"),
2381                                  autostartLink, configFile);
2382             goto cleanup;
2383         }
2384     } else {
2385         if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
2386             virReportSystemError(errno,
2387                                  _("Failed to delete symlink '%s'"),
2388                                  autostartLink);
2389             goto cleanup;
2390         }
2391     }
2392
2393     vm->autostart = autostart;
2394     ret = 0;
2395
2396 cleanup:
2397     VIR_FREE(configFile);
2398     VIR_FREE(autostartLink);
2399     if (vm)
2400         virObjectUnlock(vm);
2401     virObjectUnref(cfg);
2402     return ret;
2403 }
2404
2405 static int lxcFreezeContainer(virDomainObjPtr vm)
2406 {
2407     int timeout = 1000; /* In milliseconds */
2408     int check_interval = 1; /* In milliseconds */
2409     int exp = 10;
2410     int waited_time = 0;
2411     int ret = -1;
2412     char *state = NULL;
2413     virLXCDomainObjPrivatePtr priv = vm->privateData;
2414
2415     while (waited_time < timeout) {
2416         int r;
2417         /*
2418          * Writing "FROZEN" to the "freezer.state" freezes the group,
2419          * i.e., the container, temporarily transiting "FREEZING" state.
2420          * Once the freezing is completed, the state of the group transits
2421          * to "FROZEN".
2422          * (see linux-2.6/Documentation/cgroups/freezer-subsystem.txt)
2423          */
2424         r = virCgroupSetFreezerState(priv->cgroup, "FROZEN");
2425
2426         /*
2427          * Returning EBUSY explicitly indicates that the group is
2428          * being freezed but incomplete and other errors are true
2429          * errors.
2430          */
2431         if (r < 0 && r != -EBUSY) {
2432             VIR_DEBUG("Writing freezer.state failed with errno: %d", r);
2433             goto error;
2434         }
2435         if (r == -EBUSY)
2436             VIR_DEBUG("Writing freezer.state gets EBUSY");
2437
2438         /*
2439          * Unfortunately, returning 0 (success) is likely to happen
2440          * even when the freezing has not been completed. Sometimes
2441          * the state of the group remains "FREEZING" like when
2442          * returning -EBUSY and even worse may never transit to
2443          * "FROZEN" even if writing "FROZEN" again.
2444          *
2445          * So we don't trust the return value anyway and always
2446          * decide that the freezing has been complete only with
2447          * the state actually transit to "FROZEN".
2448          */
2449         usleep(check_interval * 1000);
2450
2451         r = virCgroupGetFreezerState(priv->cgroup, &state);
2452
2453         if (r < 0) {
2454             VIR_DEBUG("Reading freezer.state failed with errno: %d", r);
2455             goto error;
2456         }
2457         VIR_DEBUG("Read freezer.state: %s", state);
2458
2459         if (STREQ(state, "FROZEN")) {
2460             ret = 0;
2461             goto cleanup;
2462         }
2463
2464         waited_time += check_interval;
2465         /*
2466          * Increasing check_interval exponentially starting with
2467          * small initial value treats nicely two cases; One is
2468          * a container is under no load and waiting for long period
2469          * makes no sense. The other is under heavy load. The container
2470          * may stay longer time in FREEZING or never transit to FROZEN.
2471          * In that case, eager polling will just waste CPU time.
2472          */
2473         check_interval *= exp;
2474         VIR_FREE(state);
2475     }
2476     VIR_DEBUG("lxcFreezeContainer timeout");
2477 error:
2478     /*
2479      * If timeout or an error on reading the state occurs,
2480      * activate the group again and return an error.
2481      * This is likely to fall the group back again gracefully.
2482      */
2483     virCgroupSetFreezerState(priv->cgroup, "THAWED");
2484     ret = -1;
2485
2486 cleanup:
2487     VIR_FREE(state);
2488     return ret;
2489 }
2490
2491 static int lxcDomainSuspend(virDomainPtr dom)
2492 {
2493     virLXCDriverPtr driver = dom->conn->privateData;
2494     virDomainObjPtr vm;
2495     virDomainEventPtr event = NULL;
2496     int ret = -1;
2497     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
2498
2499     if (!(vm = lxcDomObjFromDomain(dom)))
2500         goto cleanup;
2501
2502     if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0)
2503         goto cleanup;
2504
2505     if (!virDomainObjIsActive(vm)) {
2506         virReportError(VIR_ERR_OPERATION_INVALID,
2507                        "%s", _("Domain is not running"));
2508         goto cleanup;
2509     }
2510
2511     if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
2512         if (lxcFreezeContainer(vm) < 0) {
2513             virReportError(VIR_ERR_OPERATION_FAILED,
2514                            "%s", _("Suspend operation failed"));
2515             goto cleanup;
2516         }
2517         virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
2518
2519         event = virDomainEventNewFromObj(vm,
2520                                          VIR_DOMAIN_EVENT_SUSPENDED,
2521                                          VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
2522     }
2523
2524     if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
2525         goto cleanup;
2526     ret = 0;
2527
2528 cleanup:
2529     if (event)
2530         virDomainEventStateQueue(driver->domainEventState, event);
2531     if (vm)
2532         virObjectUnlock(vm);
2533     virObjectUnref(cfg);
2534     return ret;
2535 }
2536
2537 static int lxcDomainResume(virDomainPtr dom)
2538 {
2539     virLXCDriverPtr driver = dom->conn->privateData;
2540     virDomainObjPtr vm;
2541     virDomainEventPtr event = NULL;
2542     int ret = -1;
2543     virLXCDomainObjPrivatePtr priv;
2544     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
2545
2546     if (!(vm = lxcDomObjFromDomain(dom)))
2547         goto cleanup;
2548
2549     priv = vm->privateData;
2550
2551     if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
2552         goto cleanup;
2553
2554     if (!virDomainObjIsActive(vm)) {
2555         virReportError(VIR_ERR_OPERATION_INVALID,
2556                        "%s", _("Domain is not running"));
2557         goto cleanup;
2558     }
2559
2560     if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
2561         if (virCgroupSetFreezerState(priv->cgroup, "THAWED") < 0) {
2562             virReportError(VIR_ERR_OPERATION_FAILED,
2563                            "%s", _("Resume operation failed"));
2564             goto cleanup;
2565         }
2566         virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
2567                              VIR_DOMAIN_RUNNING_UNPAUSED);
2568
2569         event = virDomainEventNewFromObj(vm,
2570                                          VIR_DOMAIN_EVENT_RESUMED,
2571                                          VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
2572     }
2573
2574     if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
2575         goto cleanup;
2576     ret = 0;
2577
2578 cleanup:
2579     if (event)
2580         virDomainEventStateQueue(driver->domainEventState, event);
2581     if (vm)
2582         virObjectUnlock(vm);
2583     virObjectUnref(cfg);
2584     return ret;
2585 }
2586
2587 static int
2588 lxcDomainOpenConsole(virDomainPtr dom,
2589                       const char *dev_name,
2590                       virStreamPtr st,
2591                       unsigned int flags)
2592 {
2593     virDomainObjPtr vm = NULL;
2594     int ret = -1;
2595     virDomainChrDefPtr chr = NULL;
2596     size_t i;
2597
2598     virCheckFlags(0, -1);
2599
2600     if (!(vm = lxcDomObjFromDomain(dom)))
2601         goto cleanup;
2602
2603     if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0)
2604         goto cleanup;
2605
2606     if (!virDomainObjIsActive(vm)) {
2607         virReportError(VIR_ERR_OPERATION_INVALID,
2608                        "%s", _("domain is not running"));
2609         goto cleanup;
2610     }
2611
2612     if (dev_name) {
2613         for (i = 0; i < vm->def->nconsoles; i++) {
2614             if (vm->def->consoles[i]->info.alias &&
2615                 STREQ(vm->def->consoles[i]->info.alias, dev_name)) {
2616                 chr = vm->def->consoles[i];
2617                 break;
2618             }
2619         }
2620     } else {
2621         if (vm->def->nconsoles)
2622             chr = vm->def->consoles[0];
2623         else if (vm->def->nserials)
2624             chr = vm->def->serials[0];
2625     }
2626
2627     if (!chr) {
2628         virReportError(VIR_ERR_INTERNAL_ERROR,
2629                        _("cannot find console device '%s'"),
2630                        dev_name ? dev_name : _("default"));
2631         goto cleanup;
2632     }
2633
2634     if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
2635         virReportError(VIR_ERR_INTERNAL_ERROR,
2636                        _("character device %s is not using a PTY"), dev_name);
2637         goto cleanup;
2638     }
2639
2640     if (virFDStreamOpenFile(st, chr->source.data.file.path,
2641                             0, 0, O_RDWR) < 0)
2642         goto cleanup;
2643
2644     ret = 0;
2645 cleanup:
2646     if (vm)
2647         virObjectUnlock(vm);
2648     return ret;
2649 }
2650
2651
2652 static int
2653 lxcDomainSendProcessSignal(virDomainPtr dom,
2654                            long long pid_value,
2655                            unsigned int signum,
2656                            unsigned int flags)
2657 {
2658     virDomainObjPtr vm = NULL;
2659     virLXCDomainObjPrivatePtr priv;
2660     pid_t victim;
2661     int ret = -1;
2662
2663     virCheckFlags(0, -1);
2664
2665     if (signum >= VIR_DOMAIN_PROCESS_SIGNAL_LAST) {
2666         virReportError(VIR_ERR_INVALID_ARG,
2667                        _("signum value %d is out of range"),
2668                        signum);
2669         return -1;
2670     }
2671
2672     if (!(vm = lxcDomObjFromDomain(dom)))
2673         goto cleanup;
2674
2675     priv = vm->privateData;
2676
2677     if (virDomainSendProcessSignalEnsureACL(dom->conn, vm->def) < 0)
2678         goto cleanup;
2679
2680     if (!virDomainObjIsActive(vm)) {
2681         virReportError(VIR_ERR_OPERATION_INVALID,
2682                        "%s", _("domain is not running"));
2683         goto cleanup;
2684     }
2685
2686     /*
2687      * XXX if the kernel has /proc/$PID/ns/pid we can
2688      * switch into container namespace & that way be
2689      * able to kill any PID. Alternatively if there
2690      * is a way to find a mapping of guest<->host PIDs
2691      * we can kill that way.
2692      */
2693     if (pid_value != 1) {
2694         virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
2695                        _("Only the init process may be killed"));
2696         goto cleanup;
2697     }
2698
2699     if (!priv->initpid) {
2700         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2701                        _("Init pid is not yet available"));
2702         goto cleanup;
2703     }
2704     victim = priv->initpid;
2705
2706     /* We're relying on fact libvirt header signal numbers
2707      * are taken from Linux, to avoid mapping
2708      */
2709     if (kill(victim, signum) < 0) {
2710         virReportSystemError(errno,
2711                              _("Unable to send %d signal to process %d"),
2712                              signum, victim);
2713         goto cleanup;
2714     }
2715
2716     ret = 0;
2717
2718 cleanup:
2719     if (vm)
2720         virObjectUnlock(vm);
2721     return ret;
2722 }
2723
2724
2725 static int
2726 lxcConnectListAllDomains(virConnectPtr conn,
2727                          virDomainPtr **domains,
2728                   unsigned int flags)
2729 {
2730     virLXCDriverPtr driver = conn->privateData;
2731     int ret = -1;
2732
2733     virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
2734
2735     if (virConnectListAllDomainsEnsureACL(conn) < 0)
2736         return -1;
2737
2738     ret = virDomainObjListExport(driver->domains, conn, domains,
2739                                  virConnectListAllDomainsCheckACL, flags);
2740     return ret;
2741 }
2742
2743
2744 static int
2745 lxcDomainInitctlCallback(pid_t pid ATTRIBUTE_UNUSED,
2746                          void *opaque)
2747 {
2748     int *command = opaque;
2749     return virInitctlSetRunLevel(*command);
2750 }
2751
2752
2753 static int
2754 lxcDomainShutdownFlags(virDomainPtr dom,
2755                        unsigned int flags)
2756 {
2757     virLXCDomainObjPrivatePtr priv;
2758     virDomainObjPtr vm;
2759     int ret = -1;
2760     int rc;
2761
2762     virCheckFlags(VIR_DOMAIN_SHUTDOWN_INITCTL |
2763                   VIR_DOMAIN_SHUTDOWN_SIGNAL, -1);
2764
2765     if (!(vm = lxcDomObjFromDomain(dom)))
2766         goto cleanup;
2767
2768     priv = vm->privateData;
2769
2770     if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def) < 0)
2771         goto cleanup;
2772
2773     if (!virDomainObjIsActive(vm)) {
2774         virReportError(VIR_ERR_OPERATION_INVALID,
2775                        "%s", _("Domain is not running"));
2776         goto cleanup;
2777     }
2778
2779     if (priv->initpid == 0) {
2780         virReportError(VIR_ERR_OPERATION_INVALID,
2781                        "%s", _("Init process ID is not yet known"));
2782         goto cleanup;
2783     }
2784
2785     if (flags == 0 ||
2786         (flags & VIR_DOMAIN_SHUTDOWN_INITCTL)) {
2787         int command = VIR_INITCTL_RUNLEVEL_POWEROFF;
2788
2789         if ((rc = virProcessRunInMountNamespace(priv->initpid,
2790                                                 lxcDomainInitctlCallback,
2791                                                 &command)) < 0)
2792             goto cleanup;
2793         if (rc == 0 && flags != 0 &&
2794             ((flags & ~VIR_DOMAIN_SHUTDOWN_INITCTL) == 0)) {
2795             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2796                            _("Container does not provide an initctl pipe"));
2797             goto cleanup;
2798         }
2799     } else {
2800         rc = 0;
2801     }
2802
2803     if (rc == 0 &&
2804         (flags == 0 ||
2805          (flags & VIR_DOMAIN_SHUTDOWN_SIGNAL))) {
2806         if (kill(priv->initpid, SIGTERM) < 0 &&
2807             errno != ESRCH) {
2808             virReportSystemError(errno,
2809                                  _("Unable to send SIGTERM to init pid %llu"),
2810                                  (unsigned long long)priv->initpid);
2811             goto cleanup;
2812         }
2813     }
2814
2815     ret = 0;
2816
2817 cleanup:
2818     if (vm)
2819         virObjectUnlock(vm);
2820     return ret;
2821 }
2822
2823 static int
2824 lxcDomainShutdown(virDomainPtr dom)
2825 {
2826     return lxcDomainShutdownFlags(dom, 0);
2827 }
2828
2829
2830 static int
2831 lxcDomainReboot(virDomainPtr dom,
2832                 unsigned int flags)
2833 {
2834     virLXCDomainObjPrivatePtr priv;
2835     virDomainObjPtr vm;
2836     int ret = -1;
2837     int rc;
2838
2839     virCheckFlags(VIR_DOMAIN_REBOOT_INITCTL |
2840                   VIR_DOMAIN_REBOOT_SIGNAL, -1);
2841
2842     if (!(vm = lxcDomObjFromDomain(dom)))
2843         goto cleanup;
2844
2845     priv = vm->privateData;
2846
2847     if (virDomainRebootEnsureACL(dom->conn, vm->def) < 0)
2848         goto cleanup;
2849
2850     if (!virDomainObjIsActive(vm)) {
2851         virReportError(VIR_ERR_OPERATION_INVALID,
2852                        "%s", _("Domain is not running"));
2853         goto cleanup;
2854     }
2855
2856     if (priv->initpid == 0) {
2857         virReportError(VIR_ERR_OPERATION_INVALID,
2858                        "%s", _("Init process ID is not yet known"));
2859         goto cleanup;
2860     }
2861
2862     if (flags == 0 ||
2863         (flags & VIR_DOMAIN_REBOOT_INITCTL)) {
2864         int command = VIR_INITCTL_RUNLEVEL_REBOOT;
2865
2866         if ((rc = virProcessRunInMountNamespace(priv->initpid,
2867                                                 lxcDomainInitctlCallback,
2868                                                 &command)) < 0)
2869             goto cleanup;
2870         if (rc == 0 && flags != 0 &&
2871             ((flags & ~VIR_DOMAIN_SHUTDOWN_INITCTL) == 0)) {
2872             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2873                            _("Container does not provide an initctl pipe"));
2874             goto cleanup;
2875         }
2876     } else {
2877         rc = 0;
2878     }
2879
2880     if (rc == 0 &&
2881         (flags == 0 ||
2882          (flags & VIR_DOMAIN_REBOOT_SIGNAL))) {
2883         if (kill(priv->initpid, SIGHUP) < 0 &&
2884             errno != ESRCH) {
2885             virReportSystemError(errno,
2886                                  _("Unable to send SIGTERM to init pid %llu"),
2887                                  (unsigned long long)priv->initpid);
2888             goto cleanup;
2889         }
2890     }
2891
2892     ret = 0;
2893
2894 cleanup:
2895     if (vm)
2896         virObjectUnlock(vm);
2897     return ret;
2898 }
2899
2900
2901 static int
2902 lxcDomainAttachDeviceConfig(virDomainDefPtr vmdef,
2903                             virDomainDeviceDefPtr dev)
2904 {
2905     int ret = -1;
2906     virDomainDiskDefPtr disk;
2907     virDomainNetDefPtr net;
2908     virDomainHostdevDefPtr hostdev;
2909
2910     switch (dev->type) {
2911     case VIR_DOMAIN_DEVICE_DISK:
2912         disk = dev->data.disk;
2913         if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
2914             virReportError(VIR_ERR_INVALID_ARG,
2915                            _("target %s already exists."), disk->dst);
2916             return -1;
2917         }
2918         if (virDomainDiskInsert(vmdef, disk))
2919             return -1;
2920         /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
2921         dev->data.disk = NULL;
2922         ret = 0;
2923         break;
2924
2925     case VIR_DOMAIN_DEVICE_NET:
2926         net = dev->data.net;
2927         if (virDomainNetInsert(vmdef, net) < 0)
2928             goto cleanup;
2929         dev->data.net = NULL;
2930         ret = 0;
2931         break;
2932
2933     case VIR_DOMAIN_DEVICE_HOSTDEV:
2934         hostdev = dev->data.hostdev;
2935         if (virDomainHostdevFind(vmdef, hostdev, NULL) >= 0) {
2936             virReportError(VIR_ERR_INVALID_ARG, "%s",
2937                            _("device is already in the domain configuration"));
2938             return -1;
2939         }
2940         if (virDomainHostdevInsert(vmdef, hostdev) < 0)
2941             return -1;
2942         dev->data.hostdev = NULL;
2943         ret = 0;
2944         break;
2945
2946     default:
2947          virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2948                         _("persistent attach of device is not supported"));
2949          break;
2950     }
2951
2952 cleanup:
2953     return ret;
2954 }
2955
2956
2957 static int
2958 lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
2959                             virDomainDeviceDefPtr dev)
2960 {
2961     int ret = -1;
2962     virDomainNetDefPtr net;
2963     int idx;
2964     char mac[VIR_MAC_STRING_BUFLEN];
2965
2966     switch (dev->type) {
2967     case VIR_DOMAIN_DEVICE_NET:
2968         net = dev->data.net;
2969         idx = virDomainNetFindIdx(vmdef, net);
2970         if (idx == -2) {
2971             virReportError(VIR_ERR_OPERATION_FAILED,
2972                            _("multiple devices matching mac address %s found"),
2973                            virMacAddrFormat(&net->mac, mac));
2974             goto cleanup;
2975         } else if (idx < 0) {
2976             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
2977                            _("no matching network device was found"));
2978             goto cleanup;
2979         }
2980
2981         virDomainNetDefFree(vmdef->nets[idx]);
2982
2983         vmdef->nets[idx] = net;
2984         dev->data.net = NULL;
2985         ret = 0;
2986
2987         break;
2988
2989     default:
2990         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2991                        _("persistent update of device is not supported"));
2992         break;
2993     }
2994
2995 cleanup:
2996     return ret;
2997 }
2998
2999
3000 static int
3001 lxcDomainDetachDeviceConfig(virDomainDefPtr vmdef,
3002                             virDomainDeviceDefPtr dev)
3003 {
3004     int ret = -1;
3005     virDomainDiskDefPtr disk, det_disk;
3006     virDomainNetDefPtr net;
3007     virDomainHostdevDefPtr hostdev, det_hostdev;
3008     int idx;
3009     char mac[VIR_MAC_STRING_BUFLEN];
3010
3011     switch (dev->type) {
3012     case VIR_DOMAIN_DEVICE_DISK:
3013         disk = dev->data.disk;
3014         if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
3015             virReportError(VIR_ERR_INVALID_ARG,
3016                            _("no target device %s"), disk->dst);
3017             return -1;
3018         }
3019         virDomainDiskDefFree(det_disk);
3020         ret = 0;
3021         break;
3022
3023     case VIR_DOMAIN_DEVICE_NET:
3024         net = dev->data.net;
3025         idx = virDomainNetFindIdx(vmdef, net);
3026         if (idx == -2) {
3027             virReportError(VIR_ERR_OPERATION_FAILED,
3028                            _("multiple devices matching mac address %s found"),
3029                            virMacAddrFormat(&net->mac, mac));
3030             goto cleanup;
3031         } else if (idx < 0) {
3032             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3033                            _("no matching network device was found"));
3034             goto cleanup;
3035         }
3036         /* this is guaranteed to succeed */
3037         virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
3038         ret = 0;
3039         break;
3040
3041     case VIR_DOMAIN_DEVICE_HOSTDEV: {
3042         hostdev = dev->data.hostdev;
3043         if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
3044             virReportError(VIR_ERR_INVALID_ARG, "%s",
3045                            _("device not present in domain configuration"));
3046             return -1;
3047         }
3048         virDomainHostdevRemove(vmdef, idx);
3049         virDomainHostdevDefFree(det_hostdev);
3050         ret = 0;
3051         break;
3052     }
3053
3054     default:
3055         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3056                        _("persistent detach of device is not supported"));
3057         break;
3058     }
3059
3060 cleanup:
3061     return ret;
3062 }
3063
3064
3065 struct lxcDomainAttachDeviceMknodData {
3066     virLXCDriverPtr driver;
3067     mode_t mode;
3068     dev_t dev;
3069     virDomainObjPtr vm;
3070     virDomainDeviceDefPtr def;
3071     char *file;
3072 };
3073
3074 static int
3075 lxcDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED,
3076                                  void *opaque)
3077 {
3078     struct lxcDomainAttachDeviceMknodData *data = opaque;
3079     int ret = -1;
3080
3081     virSecurityManagerPostFork(data->driver->securityManager);
3082
3083     if (virFileMakeParentPath(data->file) < 0) {
3084         virReportSystemError(errno,
3085                              _("Unable to create %s"), data->file);
3086         goto cleanup;
3087     }
3088
3089     /* Yes, the device name we're creating may not
3090      * actually correspond to the major:minor number
3091      * we're using, but we've no other option at this
3092      * time. Just have to hope that containerized apps
3093      * don't get upset that the major:minor is different
3094      * to that normally implied by the device name
3095      */
3096     VIR_DEBUG("Creating dev %s (%d,%d)",
3097               data->file, major(data->dev), minor(data->dev));
3098     if (mknod(data->file, data->mode, data->dev) < 0) {
3099         virReportSystemError(errno,
3100                              _("Unable to create device %s"),
3101                              data->file);
3102         goto cleanup;
3103     }
3104
3105     if (lxcContainerChown(data->vm->def, data->file) < 0)
3106         goto cleanup;
3107
3108     /* Labelling normally operates on src, but we need
3109      * to actually label the dst here, so hack the config */
3110     switch (data->def->type) {
3111     case VIR_DOMAIN_DEVICE_DISK: {
3112         virDomainDiskDefPtr def = data->def->data.disk;
3113         char *tmpsrc = def->src;
3114         def->src = data->file;
3115         if (virSecurityManagerSetImageLabel(data->driver->securityManager,
3116                                             data->vm->def, def) < 0) {
3117             def->src = tmpsrc;
3118             goto cleanup;
3119         }
3120         def->src = tmpsrc;
3121     }   break;
3122
3123     default:
3124         virReportError(VIR_ERR_INTERNAL_ERROR,
3125                        _("Unexpected device type %d"),
3126                        data->def->type);
3127         goto cleanup;
3128     }
3129
3130     ret = 0;
3131
3132  cleanup:
3133     if (ret < 0)
3134         unlink(data->file);
3135     return ret;
3136 }
3137
3138
3139 static int
3140 lxcDomainAttachDeviceMknod(virLXCDriverPtr driver,
3141                            mode_t mode,
3142                            dev_t dev,
3143                            virDomainObjPtr vm,
3144                            virDomainDeviceDefPtr def,
3145                            char *file)
3146 {
3147     virLXCDomainObjPrivatePtr priv = vm->privateData;
3148     struct lxcDomainAttachDeviceMknodData data;
3149
3150     memset(&data, 0, sizeof(data));
3151
3152     data.driver = driver;
3153     data.mode = mode;
3154     data.dev = dev;
3155     data.vm = vm;
3156     data.def = def;
3157     data.file = file;
3158
3159     if (virSecurityManagerPreFork(driver->securityManager) < 0)
3160         return -1;
3161
3162     if (virProcessRunInMountNamespace(priv->initpid,
3163                                       lxcDomainAttachDeviceMknodHelper,
3164                                       &data) < 0) {
3165         virSecurityManagerPostFork(driver->securityManager);
3166         return -1;
3167     }
3168
3169     virSecurityManagerPostFork(driver->securityManager);
3170     return 0;
3171 }
3172
3173
3174 static int
3175 lxcDomainAttachDeviceDiskLive(virLXCDriverPtr driver,
3176                               virDomainObjPtr vm,
3177                               virDomainDeviceDefPtr dev)
3178 {
3179     virLXCDomainObjPrivatePtr priv = vm->privateData;
3180     virDomainDiskDefPtr def = dev->data.disk;
3181     int ret = -1;
3182     struct stat sb;
3183     char *file = NULL;
3184     int perms;
3185
3186     if (!priv->initpid) {
3187         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3188                        _("Cannot attach disk until init PID is known"));
3189         goto cleanup;
3190     }
3191
3192     if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) {
3193         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3194                        _("devices cgroup isn't mounted"));
3195         goto cleanup;
3196     }
3197
3198     if (def->type != VIR_DOMAIN_DISK_TYPE_BLOCK) {
3199         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3200                        _("Can't setup disk for non-block device"));
3201         goto cleanup;
3202     }
3203     if (def->src == NULL) {
3204         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3205                        _("Can't setup disk without media"));
3206         goto cleanup;
3207     }
3208
3209     if (virDomainDiskIndexByName(vm->def, def->dst, true) >= 0) {
3210         virReportError(VIR_ERR_OPERATION_FAILED,
3211                        _("target %s already exists"), def->dst);
3212         goto cleanup;
3213     }
3214
3215     if (stat(def->src, &sb) < 0) {
3216         virReportSystemError(errno,
3217                              _("Unable to access %s"), def->src);
3218         goto cleanup;
3219     }
3220
3221     if (!S_ISBLK(sb.st_mode)) {
3222         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3223                        _("Disk source %s must be a block device"),
3224                        def->src);
3225         goto cleanup;
3226     }
3227
3228     if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) {
3229         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3230                        _("devices cgroup isn't mounted"));
3231         goto cleanup;
3232     }
3233
3234     perms = (def->readonly ?
3235              VIR_CGROUP_DEVICE_READ :
3236              VIR_CGROUP_DEVICE_RW) |
3237         VIR_CGROUP_DEVICE_MKNOD;
3238
3239     if (virCgroupAllowDevice(priv->cgroup,
3240                              'b',
3241                              major(sb.st_rdev),
3242                              minor(sb.st_rdev),
3243                              perms) < 0)
3244         goto cleanup;
3245
3246     if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks + 1) < 0)
3247         goto cleanup;
3248
3249     if (virAsprintf(&file,
3250                     "/dev/%s", def->dst) < 0)
3251         goto cleanup;
3252
3253     if (lxcDomainAttachDeviceMknod(driver,
3254                                    0700 | S_IFBLK,
3255                                    sb.st_rdev,
3256                                    vm,
3257                                    dev,
3258                                    file) < 0) {
3259         if (virCgroupDenyDevice(priv->cgroup,
3260                                 'b',
3261                                 major(sb.st_rdev),
3262                                 minor(sb.st_rdev),
3263                                 perms) < 0)
3264             VIR_WARN("cannot deny device %s for domain %s",
3265                      def->src, vm->def->name);
3266         goto cleanup;
3267     }
3268
3269     virDomainDiskInsertPreAlloced(vm->def, def);
3270
3271     ret = 0;
3272
3273 cleanup:
3274     virDomainAuditDisk(vm, NULL, def->src, "attach", ret == 0);
3275     VIR_FREE(file);
3276     return ret;
3277 }
3278
3279
3280 /* XXX conn required for network -> bridge resolution */
3281 static int
3282 lxcDomainAttachDeviceNetLive(virConnectPtr conn,
3283                              virDomainObjPtr vm,
3284                              virDomainNetDefPtr net)
3285 {
3286     virLXCDomainObjPrivatePtr priv = vm->privateData;
3287     int ret = -1;
3288     int actualType;
3289     char *veth = NULL;
3290
3291     if (!priv->initpid) {
3292         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3293                        _("Cannot attach disk until init PID is known"));
3294         goto cleanup;
3295     }
3296
3297     /* preallocate new slot for device */
3298     if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0)
3299         return -1;
3300
3301     /* If appropriate, grab a physical device from the configured
3302      * network's pool of devices, or resolve bridge device name
3303      * to the one defined in the network definition.
3304      */
3305     if (networkAllocateActualDevice(net) < 0)
3306         return -1;
3307
3308     actualType = virDomainNetGetActualType(net);
3309
3310     switch (actualType) {
3311     case VIR_DOMAIN_NET_TYPE_BRIDGE: {
3312         const char *brname = virDomainNetGetActualBridgeName(net);
3313         if (!brname) {
3314             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3315                            _("No bridge name specified"));
3316             goto cleanup;
3317         }
3318         if (!(veth = virLXCProcessSetupInterfaceBridged(conn,
3319                                                         vm->def,
3320                                                         net,
3321                                                         brname)))
3322             goto cleanup;
3323     }   break;
3324     case VIR_DOMAIN_NET_TYPE_NETWORK: {
3325         virNetworkPtr network;
3326         char *brname = NULL;
3327         bool fail = false;
3328         int active;
3329         virErrorPtr errobj;
3330
3331         if (!(network = virNetworkLookupByName(conn,
3332                                                net->data.network.name)))
3333             goto cleanup;
3334
3335         active = virNetworkIsActive(network);
3336         if (active != 1) {
3337             fail = true;
3338             if (active == 0)
3339                 virReportError(VIR_ERR_INTERNAL_ERROR,
3340                                _("Network '%s' is not active."),
3341                                net->data.network.name);
3342         }
3343
3344         if (!fail) {
3345             brname = virNetworkGetBridgeName(network);
3346             if (brname == NULL)
3347                 fail = true;
3348         }
3349
3350         /* Make sure any above failure is preserved */
3351         errobj = virSaveLastError();
3352         virNetworkFree(network);
3353         virSetError(errobj);
3354         virFreeError(errobj);
3355
3356         if (fail)
3357             goto cleanup;
3358
3359         if (!(veth = virLXCProcessSetupInterfaceBridged(conn,
3360                                                         vm->def,
3361                                                         net,
3362                                                         brname))) {
3363             VIR_FREE(brname);
3364             goto cleanup;
3365         }
3366         VIR_FREE(brname);
3367     }   break;
3368     case VIR_DOMAIN_NET_TYPE_DIRECT: {
3369         if (!(veth = virLXCProcessSetupInterfaceDirect(conn,
3370                                                        vm->def,
3371                                                        net)))
3372             goto cleanup;
3373     }   break;
3374     default:
3375         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3376                        _("Network device type is not supported"));
3377         goto cleanup;
3378     }
3379
3380     if (virNetDevSetNamespace(veth, priv->initpid) < 0) {
3381         virDomainAuditNet(vm, NULL, net, "attach", false);
3382         goto cleanup;
3383     }
3384
3385     virDomainAuditNet(vm, NULL, net, "attach", true);
3386
3387     ret = 0;
3388
3389 cleanup:
3390     if (!ret) {
3391         vm->def->nets[vm->def->nnets++] = net;
3392     } else if (veth) {
3393         switch (actualType) {
3394         case VIR_DOMAIN_NET_TYPE_BRIDGE:
3395         case VIR_DOMAIN_NET_TYPE_NETWORK:
3396             ignore_value(virNetDevVethDelete(veth));
3397             break;
3398
3399         case VIR_DOMAIN_NET_TYPE_DIRECT:
3400             ignore_value(virNetDevMacVLanDelete(veth));
3401             break;
3402         }
3403     }
3404
3405     return ret;
3406 }
3407
3408
3409 static int
3410 lxcDomainAttachDeviceHostdevSubsysUSBLive(virLXCDriverPtr driver,
3411                                           virDomainObjPtr vm,
3412                                           virDomainDeviceDefPtr dev)
3413 {
3414     virLXCDomainObjPrivatePtr priv = vm->privateData;
3415     virDomainHostdevDefPtr def = dev->data.hostdev;
3416     int ret = -1;
3417     char *vroot = NULL;
3418     char *src = NULL;
3419     char *dstdir = NULL;
3420     char *dstfile = NULL;
3421     struct stat sb;
3422     mode_t mode;
3423     bool created = false;
3424     virUSBDevicePtr usb = NULL;
3425
3426     if (virDomainHostdevFind(vm->def, def, NULL) >= 0) {
3427         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3428                        _("host USB device already exists"));
3429         return -1;
3430     }
3431
3432     if (virAsprintf(&vroot, "/proc/%llu/root",
3433                     (unsigned long long)priv->initpid) < 0)
3434         goto cleanup;
3435
3436     if (virAsprintf(&dstdir, "%s/dev/bus/usb/%03d",
3437                     vroot,
3438                     def->source.subsys.u.usb.bus) < 0)
3439         goto cleanup;
3440
3441     if (virAsprintf(&dstfile, "%s/%03d",
3442                     dstdir,
3443                     def->source.subsys.u.usb.device) < 0)
3444         goto cleanup;
3445
3446     if (virAsprintf(&src, "/dev/bus/usb/%03d/%03d",
3447                     def->source.subsys.u.usb.bus,
3448                     def->source.subsys.u.usb.device) < 0)
3449         goto cleanup;
3450
3451     if (!(usb = virUSBDeviceNew(def->source.subsys.u.usb.bus,
3452                                 def->source.subsys.u.usb.device, vroot)))
3453         goto cleanup;
3454
3455     if (stat(src, &sb) < 0) {
3456         virReportSystemError(errno,
3457                              _("Unable to access %s"), src);
3458         goto cleanup;
3459     }
3460
3461     if (!S_ISCHR(sb.st_mode)) {
3462         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3463                        _("USB source %s was not a character device"),
3464                        src);
3465         goto cleanup;
3466     }
3467
3468     mode = 0700 | S_IFCHR;
3469
3470     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
3471         goto cleanup;
3472
3473     if (virFileMakePath(dstdir) < 0) {
3474         virReportSystemError(errno,
3475                              _("Unable to create %s"), dstdir);
3476         goto cleanup;
3477     }
3478
3479     VIR_DEBUG("Creating dev %s (%d,%d)",
3480               dstfile, major(sb.st_rdev), minor(sb.st_rdev));
3481     if (mknod(dstfile, mode, sb.st_rdev) < 0) {
3482         virReportSystemError(errno,
3483                              _("Unable to create device %s"),
3484                              dstfile);
3485         goto cleanup;
3486     }
3487     created = true;
3488
3489     if (lxcContainerChown(vm->def, dstfile) < 0)
3490         goto cleanup;
3491
3492     if (virSecurityManagerSetHostdevLabel(driver->securityManager,
3493                                           vm->def, def, vroot) < 0)
3494         goto cleanup;
3495
3496     if (virUSBDeviceFileIterate(usb,
3497                                 virLXCSetupHostUsbDeviceCgroup,
3498                                 priv->cgroup) < 0)
3499         goto cleanup;
3500
3501     vm->def->hostdevs[vm->def->nhostdevs++] = def;
3502
3503     ret = 0;
3504
3505 cleanup:
3506     virDomainAuditHostdev(vm, def, "attach", ret == 0);
3507     if (ret < 0 && created)
3508         unlink(dstfile);
3509
3510     virUSBDeviceFree(usb);
3511     VIR_FREE(src);
3512     VIR_FREE(dstfile);
3513     VIR_FREE(dstdir);
3514     VIR_FREE(vroot);
3515     return ret;
3516 }
3517
3518
3519 static int
3520 lxcDomainAttachDeviceHostdevStorageLive(virLXCDriverPtr driver,
3521                                         virDomainObjPtr vm,
3522                                         virDomainDeviceDefPtr dev)
3523 {
3524     virLXCDomainObjPrivatePtr priv = vm->privateData;
3525     virDomainHostdevDefPtr def = dev->data.hostdev;
3526     int ret = -1;
3527     char *dst = NULL;
3528     char *vroot = NULL;
3529     struct stat sb;
3530     bool created = false;
3531     mode_t mode = 0;
3532
3533     if (!def->source.caps.u.storage.block) {
3534         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3535                        _("Missing storage block path"));
3536         goto cleanup;
3537     }
3538
3539     if (virDomainHostdevFind(vm->def, def, NULL) >= 0) {
3540         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3541                        _("host device already exists"));
3542         return -1;
3543     }
3544
3545     if (stat(def->source.caps.u.storage.block, &sb) < 0) {
3546         virReportSystemError(errno,
3547                              _("Unable to access %s"),
3548                              def->source.caps.u.storage.block);
3549         goto cleanup;
3550     }
3551
3552     if (!S_ISBLK(sb.st_mode)) {
3553         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3554                        _("Hostdev source %s must be a block device"),
3555                        def->source.caps.u.storage.block);
3556         goto cleanup;
3557     }
3558
3559     if (virAsprintf(&vroot, "/proc/%llu/root",
3560                     (unsigned long long)priv->initpid) < 0)
3561         goto cleanup;
3562
3563     if (virAsprintf(&dst, "%s/%s",
3564                     vroot,
3565                     def->source.caps.u.storage.block) < 0)
3566         goto cleanup;
3567
3568     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0)
3569         goto cleanup;
3570
3571     if (lxcContainerSetupHostdevCapsMakePath(dst) < 0) {
3572         virReportSystemError(errno,
3573                              _("Unable to create directory for device %s"),
3574                              dst);
3575         goto cleanup;
3576     }
3577
3578     mode = 0700 | S_IFBLK;
3579
3580     VIR_DEBUG("Creating dev %s (%d,%d)",
3581               def->source.caps.u.storage.block,
3582               major(sb.st_rdev), minor(sb.st_rdev));
3583     if (mknod(dst, mode, sb.st_rdev) < 0) {
3584         virReportSystemError(errno,
3585                              _("Unable to create device %s"),
3586                              dst);
3587         goto cleanup;
3588     }
3589     created = true;
3590
3591     if (lxcContainerChown(vm->def, dst) < 0)
3592         goto cleanup;
3593
3594     if (virSecurityManagerSetHostdevLabel(driver->securityManager,
3595                                           vm->def, def, vroot) < 0)
3596         goto cleanup;
3597
3598     if (virCgroupAllowDevicePath(priv->cgroup, def->source.caps.u.storage.block,
3599                                  VIR_CGROUP_DEVICE_RW |
3600                                  VIR_CGROUP_DEVICE_MKNOD) != 0) {
3601         virReportError(VIR_ERR_INTERNAL_ERROR,
3602                        _("cannot allow device %s for domain %s"),
3603                        def->source.caps.u.storage.block, vm->def->name);
3604         goto cleanup;
3605     }
3606
3607     vm->def->hostdevs[vm->def->nhostdevs++] = def;
3608
3609     ret = 0;
3610
3611 cleanup:
3612     virDomainAuditHostdev(vm, def, "attach", ret == 0);
3613     if (dst && created && ret < 0)
3614         unlink(dst);
3615     VIR_FREE(dst);
3616     VIR_FREE(vroot);
3617     return ret;
3618 }
3619
3620
3621 static int
3622 lxcDomainAttachDeviceHostdevMiscLive(virLXCDriverPtr driver,
3623                                      virDomainObjPtr vm,
3624                                      virDomainDeviceDefPtr dev)
3625 {
3626     virLXCDomainObjPrivatePtr priv = vm->privateData;
3627     virDomainHostdevDefPtr def = dev->data.hostdev;
3628     int ret = -1;
3629     char *dst = NULL;
3630     char *vroot = NULL;
3631     struct stat sb;
3632     bool created = false;
3633     mode_t mode = 0;
3634
3635     if (!def->source.caps.u.misc.chardev) {
3636         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3637                        _("Missing storage block path"));
3638         goto cleanup;
3639     }
3640
3641     if (virDomainHostdevFind(vm->def, def, NULL) >= 0) {
3642         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3643                        _("host device already exists"));
3644         return -1;
3645     }
3646
3647     if (stat(def->source.caps.u.misc.chardev, &sb) < 0) {
3648         virReportSystemError(errno,
3649                              _("Unable to access %s"),
3650                              def->source.caps.u.misc.chardev);
3651         goto cleanup;
3652     }
3653
3654     if (!S_ISCHR(sb.st_mode)) {
3655         virReportError(VIR_ERR_CONFIG