security_dac.c 38.7 KB
Newer Older
1
/*
2
 * Copyright (C) 2010-2014 Red Hat, Inc.
3 4 5 6 7 8 9 10 11 12 13 14
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library.  If not, see
O
Osier Yang 已提交
16
 * <http://www.gnu.org/licenses/>.
17 18 19 20 21 22 23 24 25 26
 *
 * POSIX DAC security driver
 */

#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "security_dac.h"
27
#include "virerror.h"
28
#include "virfile.h"
29
#include "viralloc.h"
30
#include "virlog.h"
31
#include "virpci.h"
32
#include "virusb.h"
33
#include "virscsi.h"
34
#include "virstoragefile.h"
35
#include "virstring.h"
M
Martin Kletzander 已提交
36
#include "virutil.h"
37 38

#define VIR_FROM_THIS VIR_FROM_SECURITY
39 40 41

VIR_LOG_INIT("security.security_dac");

42
#define SECURITY_DAC_NAME "dac"
43 44 45 46 47 48 49

typedef struct _virSecurityDACData virSecurityDACData;
typedef virSecurityDACData *virSecurityDACDataPtr;

struct _virSecurityDACData {
    uid_t user;
    gid_t group;
50 51
    gid_t *groups;
    int ngroups;
52
    bool dynamicOwnership;
53
    char *baselabel;
54 55
};

56 57 58 59 60 61 62 63
typedef struct _virSecurityDACCallbackData virSecurityDACCallbackData;
typedef virSecurityDACCallbackData *virSecurityDACCallbackDataPtr;

struct _virSecurityDACCallbackData {
    virSecurityManagerPtr manager;
    virSecurityLabelDefPtr secdef;
};

64 65 66 67 68
/* returns -1 on error, 0 on success */
int
virSecurityDACSetUserAndGroup(virSecurityManagerPtr mgr,
                              uid_t user,
                              gid_t group)
69 70 71 72
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    priv->user = user;
    priv->group = group;
73

74
    if (virAsprintf(&priv->baselabel, "+%u:+%u",
75 76 77 78 79
                    (unsigned int) user,
                    (unsigned int) group) < 0)
        return -1;

    return 0;
80 81
}

O
Osier Yang 已提交
82 83 84
void
virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr,
                                  bool dynamicOwnership)
85 86 87 88 89
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    priv->dynamicOwnership = dynamicOwnership;
}

90
/* returns 1 if label isn't found, 0 on success, -1 on error */
O
Osier Yang 已提交
91
static int
92
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
93 94
virSecurityDACParseIds(virSecurityLabelDefPtr seclabel,
                       uid_t *uidPtr, gid_t *gidPtr)
95
{
96
    if (!seclabel || !seclabel->label)
97
        return 1;
98

99
    if (virParseOwnershipIds(seclabel->label, uidPtr, gidPtr) < 0)
100 101 102 103 104
        return -1;

    return 0;
}

O
Osier Yang 已提交
105
static int
106
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
107 108
virSecurityDACGetIds(virSecurityLabelDefPtr seclabel,
                     virSecurityDACDataPtr priv,
109 110
                     uid_t *uidPtr, gid_t *gidPtr,
                     gid_t **groups, int *ngroups)
111
{
112 113
    int ret;

114 115 116 117 118
    if (groups)
        *groups = priv ? priv->groups : NULL;
    if (ngroups)
        *ngroups = priv ? priv->ngroups : 0;

119
    if ((ret = virSecurityDACParseIds(seclabel, uidPtr, gidPtr)) <= 0)
120 121 122
        return ret;

    if (!priv) {
123 124
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("DAC seclabel couldn't be determined"));
125 126 127
        return -1;
    }

128 129
    *uidPtr = priv->user;
    *gidPtr = priv->group;
130 131

    return 0;
132 133
}

134 135

/* returns 1 if label isn't found, 0 on success, -1 on error */
O
Osier Yang 已提交
136
static int
137
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
138
virSecurityDACParseImageIds(virSecurityLabelDefPtr seclabel,
O
Osier Yang 已提交
139
                            uid_t *uidPtr, gid_t *gidPtr)
140
{
141
    if (!seclabel || !seclabel->imagelabel)
142
        return 1;
143

144
    if (virParseOwnershipIds(seclabel->imagelabel, uidPtr, gidPtr) < 0)
145 146 147 148 149
        return -1;

    return 0;
}

O
Osier Yang 已提交
150
static int
151
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
152 153
virSecurityDACGetImageIds(virSecurityLabelDefPtr seclabel,
                          virSecurityDACDataPtr priv,
O
Osier Yang 已提交
154
                          uid_t *uidPtr, gid_t *gidPtr)
155
{
156 157
    int ret;

158
    if ((ret = virSecurityDACParseImageIds(seclabel, uidPtr, gidPtr)) <= 0)
159 160 161
        return ret;

    if (!priv) {
162 163
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("DAC imagelabel couldn't be determined"));
164
        return -1;
165
    }
166

167 168
    *uidPtr = priv->user;
    *gidPtr = priv->group;
169 170

    return 0;
171 172 173
}


174
static virSecurityDriverStatus
175
virSecurityDACProbe(const char *virtDriver ATTRIBUTE_UNUSED)
176 177 178 179 180 181 182 183 184 185 186
{
    return SECURITY_DRIVER_ENABLE;
}

static int
virSecurityDACOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
{
    return 0;
}

static int
187
virSecurityDACClose(virSecurityManagerPtr mgr)
188
{
189 190
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    VIR_FREE(priv->groups);
191
    VIR_FREE(priv->baselabel);
192 193 194 195
    return 0;
}


O
Osier Yang 已提交
196 197
static const char *
virSecurityDACGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
198
{
199
    return SECURITY_DAC_NAME;
200 201
}

O
Osier Yang 已提交
202 203
static const char *
virSecurityDACGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
204 205 206 207
{
    return "0";
}

208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
static int
virSecurityDACPreFork(virSecurityManagerPtr mgr)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    int ngroups;

    VIR_FREE(priv->groups);
    priv->ngroups = 0;
    if ((ngroups = virGetGroupList(priv->user, priv->group,
                                   &priv->groups)) < 0)
        return -1;
    priv->ngroups = ngroups;
    return 0;
}

223
static int
224
virSecurityDACSetOwnership(const char *path, uid_t uid, gid_t gid)
225
{
226 227
    VIR_INFO("Setting DAC user and group on '%s' to '%ld:%ld'",
             path, (long) uid, (long) gid);
228 229 230 231 232 233 234 235 236 237 238 239 240

    if (chown(path, uid, gid) < 0) {
        struct stat sb;
        int chown_errno = errno;

        if (stat(path, &sb) >= 0) {
            if (sb.st_uid == uid &&
                sb.st_gid == gid) {
                /* It's alright, there's nothing to change anyway. */
                return 0;
            }
        }

241
        if (chown_errno == EOPNOTSUPP || chown_errno == EINVAL) {
242 243 244
            VIR_INFO("Setting user and group to '%ld:%ld' on '%s' not "
                     "supported by filesystem",
                     (long) uid, (long) gid, path);
245
        } else if (chown_errno == EPERM) {
246 247 248
            VIR_INFO("Setting user and group to '%ld:%ld' on '%s' not "
                     "permitted",
                     (long) uid, (long) gid, path);
249
        } else if (chown_errno == EROFS) {
250 251 252
            VIR_INFO("Setting user and group to '%ld:%ld' on '%s' not "
                     "possible on readonly filesystem",
                     (long) uid, (long) gid, path);
253 254
        } else {
            virReportSystemError(chown_errno,
255 256 257
                                 _("unable to set user and group to '%ld:%ld' "
                                   "on '%s'"),
                                 (long) uid, (long) gid, path);
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
            return -1;
        }
    }
    return 0;
}

static int
virSecurityDACRestoreSecurityFileLabel(const char *path)
{
    struct stat buf;
    int rc = -1;
    char *newpath = NULL;

    VIR_INFO("Restoring DAC user and group on '%s'", path);

    if (virFileResolveLink(path, &newpath) < 0) {
        virReportSystemError(errno,
                             _("cannot resolve symlink %s"), path);
        goto err;
    }

    if (stat(newpath, &buf) != 0)
        goto err;

    /* XXX record previous ownership */
    rc = virSecurityDACSetOwnership(newpath, 0, 0);

285
 err:
286 287 288 289 290 291
    VIR_FREE(newpath);
    return rc;
}


static int
292
virSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk,
293 294 295 296
                                   const char *path,
                                   size_t depth ATTRIBUTE_UNUSED,
                                   void *opaque)
{
297 298 299
    virSecurityDACCallbackDataPtr cbdata = opaque;
    virSecurityManagerPtr mgr = cbdata->manager;
    virSecurityLabelDefPtr secdef = cbdata->secdef;
300
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
301
    virSecurityDeviceLabelDefPtr disk_seclabel;
302 303 304
    uid_t user;
    gid_t group;

305 306 307 308 309 310 311 312 313 314 315 316 317
    disk_seclabel = virDomainDiskDefGetSecurityLabelDef(disk,
                                                        SECURITY_DAC_NAME);

    if (disk_seclabel && disk_seclabel->norelabel)
        return 0;

    if (disk_seclabel && disk_seclabel->label) {
        if (virParseOwnershipIds(disk_seclabel->label, &user, &group) < 0)
            return -1;
    } else {
        if (virSecurityDACGetImageIds(secdef, priv, &user, &group))
            return -1;
    }
318

319
    return virSecurityDACSetOwnership(path, user, group);
320 321 322 323 324
}


static int
virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr,
325
                                    virDomainDefPtr def,
326 327 328 329
                                    virDomainDiskDefPtr disk)

{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
330 331
    virSecurityDACCallbackData cbdata;
    virSecurityLabelDefPtr secdef;
332 333 334 335

    if (!priv->dynamicOwnership)
        return 0;

E
Eric Blake 已提交
336
    if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_NETWORK)
337 338
        return 0;

339 340
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

341 342 343
    if (secdef && secdef->norelabel)
        return 0;

344 345
    cbdata.manager = mgr;
    cbdata.secdef = secdef;
346 347 348
    return virDomainDiskDefForeachPath(disk,
                                       false,
                                       virSecurityDACSetSecurityFileLabel,
349
                                       &cbdata);
350 351 352 353 354
}


static int
virSecurityDACRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
355
                                           virDomainDefPtr def,
356 357 358 359
                                           virDomainDiskDefPtr disk,
                                           int migrated)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
360 361
    virSecurityLabelDefPtr secdef;
    virSecurityDeviceLabelDefPtr disk_seclabel;
362
    const char *src = virDomainDiskGetSource(disk);
363 364 365 366

    if (!priv->dynamicOwnership)
        return 0;

E
Eric Blake 已提交
367
    if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_NETWORK)
368 369
        return 0;

370 371 372 373 374 375 376 377 378 379 380
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (secdef && secdef->norelabel)
        return 0;

    disk_seclabel = virDomainDiskDefGetSecurityLabelDef(disk,
                                                        SECURITY_DAC_NAME);

    if (disk_seclabel && disk_seclabel->norelabel)
        return 0;

381 382 383 384 385 386 387 388 389 390 391
    /* Don't restore labels on readoly/shared disks, because
     * other VMs may still be accessing these
     * Alternatively we could iterate over all running
     * domains and try to figure out if it is in use, but
     * this would not work for clustered filesystems, since
     * we can't see running VMs using the file on other nodes
     * Safest bet is thus to skip the restore step.
     */
    if (disk->readonly || disk->shared)
        return 0;

392
    if (!src)
393 394 395 396 397 398 399 400
        return 0;

    /* If we have a shared FS & doing migrated, we must not
     * change ownership, because that kills access on the
     * destination host which is sub-optimal for the guest
     * VM's I/O attempts :-)
     */
    if (migrated) {
401
        int rc = virFileIsSharedFS(src);
402 403 404 405
        if (rc < 0)
            return -1;
        if (rc == 1) {
            VIR_DEBUG("Skipping image label restore on %s because FS is shared",
406
                      src);
407 408 409 410
            return 0;
        }
    }

411
    return virSecurityDACRestoreSecurityFileLabel(src);
412 413 414 415 416
}


static int
virSecurityDACRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
417
                                        virDomainDefPtr def,
418 419
                                        virDomainDiskDefPtr disk)
{
420
    return virSecurityDACRestoreSecurityImageLabelInt(mgr, def, disk, 0);
421 422 423 424
}


static int
425 426
virSecurityDACSetSecurityHostdevLabelHelper(const char *file,
                                            void *opaque)
427
{
428 429 430
    virSecurityDACCallbackDataPtr cbdata = opaque;
    virSecurityManagerPtr mgr = cbdata->manager;
    virSecurityLabelDefPtr secdef = cbdata->secdef;
431
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
432 433
    uid_t user;
    gid_t group;
434

435
    if (virSecurityDACGetIds(secdef, priv, &user, &group, NULL, NULL))
436 437 438
        return -1;

    return virSecurityDACSetOwnership(file, user, group);
439 440 441
}


442 443 444 445 446 447 448 449 450
static int
virSecurityDACSetSecurityPCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
                                  const char *file,
                                  void *opaque)
{
    return virSecurityDACSetSecurityHostdevLabelHelper(file, opaque);
}


451
static int
452
virSecurityDACSetSecurityUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
453 454 455
                                  const char *file,
                                  void *opaque)
{
456 457
    return virSecurityDACSetSecurityHostdevLabelHelper(file, opaque);
}
458

459

460 461 462 463 464 465
static int
virSecurityDACSetSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
                                   const char *file,
                                   void *opaque)
{
    return virSecurityDACSetSecurityHostdevLabelHelper(file, opaque);
466 467 468 469 470
}


static int
virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
471
                                      virDomainDefPtr def,
472 473
                                      virDomainHostdevDefPtr dev,
                                      const char *vroot)
474 475
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
476
    virSecurityDACCallbackData cbdata;
477 478 479 480 481 482 483 484
    int ret = -1;

    if (!priv->dynamicOwnership)
        return 0;

    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
        return 0;

485 486 487
    cbdata.manager = mgr;
    cbdata.secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

488 489 490
    if (cbdata.secdef && cbdata.secdef->norelabel)
        return 0;

491
    switch ((virDomainHostdevSubsysType) dev->source.subsys.type) {
492
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
493
        virUSBDevicePtr usb;
494

495 496 497
        if (dev->missing)
            return 0;

498 499 500
        usb = virUSBDeviceNew(dev->source.subsys.u.usb.bus,
                              dev->source.subsys.u.usb.device,
                              vroot);
501 502 503
        if (!usb)
            goto done;

504 505 506
        ret = virUSBDeviceFileIterate(usb,
                                      virSecurityDACSetSecurityUSBLabel,
                                      &cbdata);
507
        virUSBDeviceFree(usb);
508 509 510 511
        break;
    }

    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
512
        virPCIDevicePtr pci =
513 514 515 516
            virPCIDeviceNew(dev->source.subsys.u.pci.addr.domain,
                            dev->source.subsys.u.pci.addr.bus,
                            dev->source.subsys.u.pci.addr.slot,
                            dev->source.subsys.u.pci.addr.function);
517 518 519 520

        if (!pci)
            goto done;

521
        if (dev->source.subsys.u.pci.backend
522
            == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
523
            char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
524

525 526
            if (!vfioGroupDev) {
                virPCIDeviceFree(pci);
527
                goto done;
528
            }
529
            ret = virSecurityDACSetSecurityPCILabel(pci, vfioGroupDev, &cbdata);
530 531
            VIR_FREE(vfioGroupDev);
        } else {
532 533 534
            ret = virPCIDeviceFileIterate(pci,
                                          virSecurityDACSetSecurityPCILabel,
                                          &cbdata);
535 536
        }

537
        virPCIDeviceFree(pci);
538 539 540
        break;
    }

541 542
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
        virSCSIDevicePtr scsi =
543 544
            virSCSIDeviceNew(NULL,
                             dev->source.subsys.u.scsi.adapter,
545 546 547
                             dev->source.subsys.u.scsi.bus,
                             dev->source.subsys.u.scsi.target,
                             dev->source.subsys.u.scsi.unit,
548 549
                             dev->readonly,
                             dev->shareable);
550 551 552 553

        if (!scsi)
            goto done;

554 555 556
        ret = virSCSIDeviceFileIterate(scsi,
                                       virSecurityDACSetSecuritySCSILabel,
                                       &cbdata);
557 558 559 560 561
        virSCSIDeviceFree(scsi);

        break;
    }

562
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
563 564 565 566
        ret = 0;
        break;
    }

567
 done:
568 569 570 571 572
    return ret;
}


static int
573
virSecurityDACRestoreSecurityPCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
574 575 576 577 578 579 580 581
                                      const char *file,
                                      void *opaque ATTRIBUTE_UNUSED)
{
    return virSecurityDACRestoreSecurityFileLabel(file);
}


static int
582 583 584
virSecurityDACRestoreSecurityUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
                                      const char *file,
                                      void *opaque ATTRIBUTE_UNUSED)
585 586 587 588 589
{
    return virSecurityDACRestoreSecurityFileLabel(file);
}


590 591 592 593 594 595 596 597 598
static int
virSecurityDACRestoreSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
                                       const char *file,
                                       void *opaque ATTRIBUTE_UNUSED)
{
    return virSecurityDACRestoreSecurityFileLabel(file);
}


599 600
static int
virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
601
                                          virDomainDefPtr def,
602 603
                                          virDomainHostdevDefPtr dev,
                                          const char *vroot)
604 605 606

{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
607
    virSecurityLabelDefPtr secdef;
608 609
    int ret = -1;

610 611 612
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (!priv->dynamicOwnership || (secdef && secdef->norelabel))
613 614 615 616 617
        return 0;

    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
        return 0;

618
    switch ((virDomainHostdevSubsysType) dev->source.subsys.type) {
619
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
620
        virUSBDevicePtr usb;
621 622 623

        if (dev->missing)
            return 0;
624

625 626 627
        usb = virUSBDeviceNew(dev->source.subsys.u.usb.bus,
                              dev->source.subsys.u.usb.device,
                              vroot);
628 629 630
        if (!usb)
            goto done;

631 632
        ret = virUSBDeviceFileIterate(usb, virSecurityDACRestoreSecurityUSBLabel, mgr);
        virUSBDeviceFree(usb);
633 634 635 636 637

        break;
    }

    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
638
        virPCIDevicePtr pci =
639 640 641 642
            virPCIDeviceNew(dev->source.subsys.u.pci.addr.domain,
                            dev->source.subsys.u.pci.addr.bus,
                            dev->source.subsys.u.pci.addr.slot,
                            dev->source.subsys.u.pci.addr.function);
643 644 645 646

        if (!pci)
            goto done;

647
        if (dev->source.subsys.u.pci.backend
648
            == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
649
            char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
650

651 652
            if (!vfioGroupDev) {
                virPCIDeviceFree(pci);
653
                goto done;
654
            }
655 656 657 658 659
            ret = virSecurityDACRestoreSecurityPCILabel(pci, vfioGroupDev, mgr);
            VIR_FREE(vfioGroupDev);
        } else {
            ret = virPCIDeviceFileIterate(pci, virSecurityDACRestoreSecurityPCILabel, mgr);
        }
660
        virPCIDeviceFree(pci);
661 662 663
        break;
    }

664 665
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
        virSCSIDevicePtr scsi =
666 667
            virSCSIDeviceNew(NULL,
                             dev->source.subsys.u.scsi.adapter,
668 669 670
                             dev->source.subsys.u.scsi.bus,
                             dev->source.subsys.u.scsi.target,
                             dev->source.subsys.u.scsi.unit,
671 672
                             dev->readonly,
                             dev->shareable);
673 674 675 676 677 678 679 680 681 682

        if (!scsi)
            goto done;

        ret = virSCSIDeviceFileIterate(scsi, virSecurityDACRestoreSecuritySCSILabel, mgr);
        virSCSIDeviceFree(scsi);

        break;
    }

683
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
684 685 686 687
        ret = 0;
        break;
    }

688
 done:
689 690 691 692 693 694
    return ret;
}


static int
virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr,
695
                              virDomainDefPtr def,
696 697
                              virDomainChrDefPtr dev,
                              virDomainChrSourceDefPtr dev_source)
698 699 700

{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
701
    virSecurityLabelDefPtr seclabel;
702
    virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
703 704
    char *in = NULL, *out = NULL;
    int ret = -1;
705 706 707
    uid_t user;
    gid_t group;

708 709
    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

710 711 712 713 714 715 716 717 718 719 720 721 722 723
    if (dev)
        chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev,
                                                          SECURITY_DAC_NAME);

    if (chr_seclabel && chr_seclabel->norelabel)
        return 0;

    if (chr_seclabel && chr_seclabel->label) {
        if (virParseOwnershipIds(chr_seclabel->label, &user, &group) < 0)
            return -1;
    } else {
        if (virSecurityDACGetIds(seclabel, priv, &user, &group, NULL, NULL) < 0)
            return -1;
    }
724

725
    switch ((enum virDomainChrType) dev_source->type) {
726 727
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
728 729
        ret = virSecurityDACSetOwnership(dev_source->data.file.path,
                                         user, group);
730 731 732
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
733 734
        if ((virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0) ||
            (virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0))
735 736
            goto done;
        if (virFileExists(in) && virFileExists(out)) {
737 738
            if ((virSecurityDACSetOwnership(in, user, group) < 0) ||
                (virSecurityDACSetOwnership(out, user, group) < 0)) {
739
                goto done;
740
            }
741
        } else if (virSecurityDACSetOwnership(dev_source->data.file.path,
742
                                              user, group) < 0) {
743
            goto done;
744 745 746 747
        }
        ret = 0;
        break;

748 749 750 751 752 753 754 755 756 757 758
    case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
    case VIR_DOMAIN_CHR_TYPE_NULL:
    case VIR_DOMAIN_CHR_TYPE_VC:
    case VIR_DOMAIN_CHR_TYPE_PTY:
    case VIR_DOMAIN_CHR_TYPE_STDIO:
    case VIR_DOMAIN_CHR_TYPE_UDP:
    case VIR_DOMAIN_CHR_TYPE_TCP:
    case VIR_DOMAIN_CHR_TYPE_UNIX:
    case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
    case VIR_DOMAIN_CHR_TYPE_NMDM:
    case VIR_DOMAIN_CHR_TYPE_LAST:
759 760 761 762
        ret = 0;
        break;
    }

763
 done:
764 765 766 767 768 769 770
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}

static int
virSecurityDACRestoreChardevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
771
                                  virDomainDefPtr def ATTRIBUTE_UNUSED,
772 773
                                  virDomainChrDefPtr dev,
                                  virDomainChrSourceDefPtr dev_source)
774
{
775
    virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
776 777 778
    char *in = NULL, *out = NULL;
    int ret = -1;

779 780 781 782
    if (dev)
        chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev,
                                                          SECURITY_DAC_NAME);

783
    if (chr_seclabel && chr_seclabel->norelabel)
784 785 786
        return 0;

    switch ((enum virDomainChrType) dev_source->type) {
787 788
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
789
        ret = virSecurityDACRestoreSecurityFileLabel(dev_source->data.file.path);
790 791 792
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
793 794
        if ((virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0) ||
            (virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0))
795
            goto done;
796 797 798
        if (virFileExists(in) && virFileExists(out)) {
            if ((virSecurityDACRestoreSecurityFileLabel(out) < 0) ||
                (virSecurityDACRestoreSecurityFileLabel(in) < 0)) {
J
Jim Fehlig 已提交
799
                goto done;
800
            }
801
        } else if (virSecurityDACRestoreSecurityFileLabel(dev_source->data.file.path) < 0) {
802 803
            goto done;
        }
804 805 806
        ret = 0;
        break;

807 808 809 810 811 812 813 814 815 816 817
    case VIR_DOMAIN_CHR_TYPE_NULL:
    case VIR_DOMAIN_CHR_TYPE_VC:
    case VIR_DOMAIN_CHR_TYPE_PTY:
    case VIR_DOMAIN_CHR_TYPE_STDIO:
    case VIR_DOMAIN_CHR_TYPE_UDP:
    case VIR_DOMAIN_CHR_TYPE_TCP:
    case VIR_DOMAIN_CHR_TYPE_UNIX:
    case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
    case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
    case VIR_DOMAIN_CHR_TYPE_NMDM:
    case VIR_DOMAIN_CHR_TYPE_LAST:
818 819 820 821
        ret = 0;
        break;
    }

822
 done:
823 824 825 826 827 828 829
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}


static int
830
virSecurityDACRestoreChardevCallback(virDomainDefPtr def,
831 832 833 834 835
                                     virDomainChrDefPtr dev,
                                     void *opaque)
{
    virSecurityManagerPtr mgr = opaque;

836
    return virSecurityDACRestoreChardevLabel(mgr, def, dev, &dev->source);
837 838 839
}


840 841 842 843 844 845 846 847 848
static int
virSecurityDACSetSecurityTPMFileLabel(virSecurityManagerPtr mgr,
                                      virDomainDefPtr def,
                                      virDomainTPMDefPtr tpm)
{
    int ret = 0;

    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
849
        ret = virSecurityDACSetChardevLabel(mgr, def, NULL,
850 851 852 853 854 855 856 857 858 859 860
                                            &tpm->data.passthrough.source);
        break;
    case VIR_DOMAIN_TPM_TYPE_LAST:
        break;
    }

    return ret;
}


static int
O
Osier Yang 已提交
861
virSecurityDACRestoreSecurityTPMFileLabel(virSecurityManagerPtr mgr,
862
                                          virDomainDefPtr def,
O
Osier Yang 已提交
863
                                          virDomainTPMDefPtr tpm)
864 865 866 867 868
{
    int ret = 0;

    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
869
        ret = virSecurityDACRestoreChardevLabel(mgr, def, NULL,
870 871 872 873 874 875 876 877 878 879
                                          &tpm->data.passthrough.source);
        break;
    case VIR_DOMAIN_TPM_TYPE_LAST:
        break;
    }

    return ret;
}


880 881
static int
virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
882
                                      virDomainDefPtr def,
883 884 885
                                      int migrated)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
886
    virSecurityLabelDefPtr secdef;
887
    size_t i;
888 889
    int rc = 0;

890
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
891

892 893
    if (!priv->dynamicOwnership || (secdef && secdef->norelabel))
        return 0;
894 895

    VIR_DEBUG("Restoring security label on %s migrated=%d",
896
              def->name, migrated);
897

898
    for (i = 0; i < def->nhostdevs; i++) {
899
        if (virSecurityDACRestoreSecurityHostdevLabel(mgr,
900
                                                      def,
901 902
                                                      def->hostdevs[i],
                                                      NULL) < 0)
903 904
            rc = -1;
    }
905
    for (i = 0; i < def->ndisks; i++) {
906
        if (virSecurityDACRestoreSecurityImageLabelInt(mgr,
907 908
                                                       def,
                                                       def->disks[i],
909 910 911 912
                                                       migrated) < 0)
            rc = -1;
    }

913
    if (virDomainChrDefForeach(def,
914 915
                               false,
                               virSecurityDACRestoreChardevCallback,
916
                               mgr) < 0)
917 918
        rc = -1;

919 920
    if (def->tpm) {
        if (virSecurityDACRestoreSecurityTPMFileLabel(mgr,
921
                                                      def,
922 923 924 925
                                                      def->tpm) < 0)
            rc = -1;
    }

926 927
    if (def->os.kernel &&
        virSecurityDACRestoreSecurityFileLabel(def->os.kernel) < 0)
928 929
        rc = -1;

930 931
    if (def->os.initrd &&
        virSecurityDACRestoreSecurityFileLabel(def->os.initrd) < 0)
932 933
        rc = -1;

O
Olivia Yin 已提交
934 935 936 937
    if (def->os.dtb &&
        virSecurityDACRestoreSecurityFileLabel(def->os.dtb) < 0)
        rc = -1;

938 939 940 941 942
    return rc;
}


static int
943
virSecurityDACSetChardevCallback(virDomainDefPtr def,
944 945 946 947 948
                                 virDomainChrDefPtr dev,
                                 void *opaque)
{
    virSecurityManagerPtr mgr = opaque;

949
    return virSecurityDACSetChardevLabel(mgr, def, dev, &dev->source);
950 951 952 953 954
}


static int
virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
955
                                  virDomainDefPtr def,
956 957 958
                                  const char *stdin_path ATTRIBUTE_UNUSED)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
959
    virSecurityLabelDefPtr secdef;
960
    size_t i;
961 962
    uid_t user;
    gid_t group;
963

964 965
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

966 967 968
    if (!priv->dynamicOwnership || (secdef && secdef->norelabel))
        return 0;

969
    for (i = 0; i < def->ndisks; i++) {
970
        /* XXX fixme - we need to recursively label the entire tree :-( */
E
Eric Blake 已提交
971
        if (virDomainDiskGetType(def->disks[i]) == VIR_STORAGE_TYPE_DIR)
972 973
            continue;
        if (virSecurityDACSetSecurityImageLabel(mgr,
974 975
                                                def,
                                                def->disks[i]) < 0)
976 977
            return -1;
    }
978
    for (i = 0; i < def->nhostdevs; i++) {
979
        if (virSecurityDACSetSecurityHostdevLabel(mgr,
980
                                                  def,
981 982
                                                  def->hostdevs[i],
                                                  NULL) < 0)
983 984 985
            return -1;
    }

986
    if (virDomainChrDefForeach(def,
987 988
                               true,
                               virSecurityDACSetChardevCallback,
989
                               mgr) < 0)
990 991
        return -1;

992 993 994 995 996 997 998
    if (def->tpm) {
        if (virSecurityDACSetSecurityTPMFileLabel(mgr,
                                                  def,
                                                  def->tpm) < 0)
            return -1;
    }

999
    if (virSecurityDACGetImageIds(secdef, priv, &user, &group))
1000 1001
        return -1;

1002
    if (def->os.kernel &&
1003
        virSecurityDACSetOwnership(def->os.kernel, user, group) < 0)
1004 1005
        return -1;

1006
    if (def->os.initrd &&
1007
        virSecurityDACSetOwnership(def->os.initrd, user, group) < 0)
1008 1009
        return -1;

O
Olivia Yin 已提交
1010 1011 1012 1013
    if (def->os.dtb &&
        virSecurityDACSetOwnership(def->os.dtb, user, group) < 0)
        return -1;

1014 1015 1016 1017 1018 1019
    return 0;
}


static int
virSecurityDACSetSavedStateLabel(virSecurityManagerPtr mgr,
1020
                                 virDomainDefPtr def,
1021 1022
                                 const char *savefile)
{
1023 1024
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1025 1026
    uid_t user;
    gid_t group;
1027

1028 1029 1030
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (virSecurityDACGetImageIds(secdef, priv, &user, &group) < 0)
1031 1032 1033
        return -1;

    return virSecurityDACSetOwnership(savefile, user, group);
1034 1035 1036 1037 1038
}


static int
virSecurityDACRestoreSavedStateLabel(virSecurityManagerPtr mgr,
1039
                                     virDomainDefPtr def ATTRIBUTE_UNUSED,
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
                                     const char *savefile)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    if (!priv->dynamicOwnership)
        return 0;

    return virSecurityDACRestoreSecurityFileLabel(savefile);
}


static int
virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr,
1053
                              virDomainDefPtr def)
1054
{
1055 1056
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1057 1058
    uid_t user;
    gid_t group;
1059 1060
    gid_t *groups;
    int ngroups;
1061

1062 1063 1064
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (virSecurityDACGetIds(secdef, priv, &user, &group, &groups, &ngroups) < 0)
1065
        return -1;
1066

1067 1068
    VIR_DEBUG("Dropping privileges of DEF to %u:%u, %d supplemental groups",
              (unsigned int) user, (unsigned int) group, ngroups);
1069

1070
    if (virSetUIDGID(user, group, groups, ngroups) < 0)
1071 1072 1073
        return -1;

    return 0;
1074 1075 1076
}


1077 1078
static int
virSecurityDACSetChildProcessLabel(virSecurityManagerPtr mgr,
1079
                                   virDomainDefPtr def,
1080 1081
                                   virCommandPtr cmd)
{
1082 1083
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1084 1085 1086
    uid_t user;
    gid_t group;

1087 1088 1089
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (virSecurityDACGetIds(secdef, priv, &user, &group, NULL, NULL))
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
        return -1;

    VIR_DEBUG("Setting child to drop privileges of DEF to %u:%u",
              (unsigned int) user, (unsigned int) group);

    virCommandSetUID(cmd, user);
    virCommandSetGID(cmd, group);
    return 0;
}


1101 1102 1103 1104 1105 1106 1107 1108
static int
virSecurityDACVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                     virDomainDefPtr def ATTRIBUTE_UNUSED)
{
    return 0;
}

static int
1109 1110
virSecurityDACGenLabel(virSecurityManagerPtr mgr,
                       virDomainDefPtr def)
1111
{
1112 1113 1114 1115 1116
    int rc = -1;
    virSecurityLabelDefPtr seclabel;
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
1117
    if (seclabel == NULL)
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
        return rc;

    if (seclabel->imagelabel) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("security image label already "
                         "defined for VM"));
        return rc;
    }

    if (seclabel->model
        && STRNEQ(seclabel->model, SECURITY_DAC_NAME)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("security label model %s is not supported "
                         "with selinux"),
                       seclabel->model);
            return rc;
    }

1136
    switch ((virDomainSeclabelType) seclabel->type) {
1137 1138 1139 1140 1141 1142 1143 1144 1145
    case VIR_DOMAIN_SECLABEL_STATIC:
        if (seclabel->label == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("missing label for static security "
                             "driver in domain %s"), def->name);
            return rc;
        }
        break;
    case VIR_DOMAIN_SECLABEL_DYNAMIC:
1146
        if (virAsprintf(&seclabel->label, "+%u:+%u",
1147
                        (unsigned int) priv->user,
1148
                        (unsigned int) priv->group) < 0)
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
            return rc;
        if (seclabel->label == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("cannot generate dac user and group id "
                             "for domain %s"), def->name);
            return rc;
        }
        break;
    case VIR_DOMAIN_SECLABEL_NONE:
        /* no op */
1159
        return 0;
1160 1161
    case VIR_DOMAIN_SECLABEL_DEFAULT:
    case VIR_DOMAIN_SECLABEL_LAST:
1162 1163 1164 1165 1166 1167
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected security label type '%s'"),
                       virDomainSeclabelTypeToString(seclabel->type));
        return rc;
    }

1168 1169 1170 1171
    if (!seclabel->norelabel && !seclabel->imagelabel &&
        VIR_STRDUP(seclabel->imagelabel, seclabel->label) < 0) {
        VIR_FREE(seclabel->label);
        return rc;
1172 1173
    }

1174 1175 1176 1177 1178
    return 0;
}

static int
virSecurityDACReleaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1179
                           virDomainDefPtr def ATTRIBUTE_UNUSED)
1180 1181 1182 1183 1184 1185
{
    return 0;
}

static int
virSecurityDACReserveLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1186 1187
                           virDomainDefPtr def ATTRIBUTE_UNUSED,
                           pid_t pid ATTRIBUTE_UNUSED)
1188 1189 1190 1191 1192 1193
{
    return 0;
}

static int
virSecurityDACGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1194
                              virDomainDefPtr def,
1195
                              pid_t pid ATTRIBUTE_UNUSED,
1196
                              virSecurityLabelPtr seclabel)
1197
{
1198 1199 1200 1201 1202 1203 1204
    virSecurityLabelDefPtr secdef =
        virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (!secdef || !seclabel)
        return -1;

    if (secdef->label)
1205 1206
        ignore_value(virStrcpy(seclabel->label, secdef->label,
                               VIR_SECURITY_LABEL_BUFLEN));
1207

1208 1209 1210 1211
    return 0;
}

static int
1212
virSecurityDACSetDaemonSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1213
                                   virDomainDefPtr vm ATTRIBUTE_UNUSED)
1214 1215 1216 1217 1218
{
    return 0;
}


1219 1220
static int
virSecurityDACSetSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1221
                             virDomainDefPtr def ATTRIBUTE_UNUSED)
1222 1223 1224 1225 1226
{
    return 0;
}


1227 1228
static int
virSecurityDACClearSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1229
                               virDomainDefPtr def ATTRIBUTE_UNUSED)
1230 1231 1232 1233
{
    return 0;
}

1234
static int
1235
virSecurityDACSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1236
                              virDomainDefPtr def ATTRIBUTE_UNUSED,
1237
                              int fd ATTRIBUTE_UNUSED)
1238 1239 1240 1241
{
    return 0;
}

1242 1243 1244 1245 1246 1247 1248 1249
static int
virSecurityDACSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                            virDomainDefPtr def ATTRIBUTE_UNUSED,
                            int fd ATTRIBUTE_UNUSED)
{
    return 0;
}

O
Osier Yang 已提交
1250 1251 1252 1253
static char *
virSecurityDACGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                              virDomainDefPtr vm ATTRIBUTE_UNUSED)
{
1254 1255 1256
    return NULL;
}

1257 1258 1259 1260 1261 1262 1263 1264
static const char *
virSecurityDACGetBaseLabel(virSecurityManagerPtr mgr,
                           int virt ATTRIBUTE_UNUSED)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    return priv->baselabel;
}

1265
virSecurityDriver virSecurityDriverDAC = {
1266
    .privateDataLen                     = sizeof(virSecurityDACData),
1267
    .name                               = SECURITY_DAC_NAME,
1268 1269 1270
    .probe                              = virSecurityDACProbe,
    .open                               = virSecurityDACOpen,
    .close                              = virSecurityDACClose,
1271

1272 1273
    .getModel                           = virSecurityDACGetModel,
    .getDOI                             = virSecurityDACGetDOI,
1274

1275 1276
    .preFork                            = virSecurityDACPreFork,

1277
    .domainSecurityVerify               = virSecurityDACVerify,
1278

1279 1280
    .domainSetSecurityImageLabel        = virSecurityDACSetSecurityImageLabel,
    .domainRestoreSecurityImageLabel    = virSecurityDACRestoreSecurityImageLabel,
1281

1282 1283 1284
    .domainSetSecurityDaemonSocketLabel = virSecurityDACSetDaemonSocketLabel,
    .domainSetSecuritySocketLabel       = virSecurityDACSetSocketLabel,
    .domainClearSecuritySocketLabel     = virSecurityDACClearSocketLabel,
1285

1286 1287 1288
    .domainGenSecurityLabel             = virSecurityDACGenLabel,
    .domainReserveSecurityLabel         = virSecurityDACReserveLabel,
    .domainReleaseSecurityLabel         = virSecurityDACReleaseLabel,
1289

1290 1291
    .domainGetSecurityProcessLabel      = virSecurityDACGetProcessLabel,
    .domainSetSecurityProcessLabel      = virSecurityDACSetProcessLabel,
1292
    .domainSetSecurityChildProcessLabel = virSecurityDACSetChildProcessLabel,
1293

1294 1295
    .domainSetSecurityAllLabel          = virSecurityDACSetSecurityAllLabel,
    .domainRestoreSecurityAllLabel      = virSecurityDACRestoreSecurityAllLabel,
1296

1297 1298
    .domainSetSecurityHostdevLabel      = virSecurityDACSetSecurityHostdevLabel,
    .domainRestoreSecurityHostdevLabel  = virSecurityDACRestoreSecurityHostdevLabel,
1299

1300 1301
    .domainSetSavedStateLabel           = virSecurityDACSetSavedStateLabel,
    .domainRestoreSavedStateLabel       = virSecurityDACRestoreSavedStateLabel,
1302

1303
    .domainSetSecurityImageFDLabel      = virSecurityDACSetImageFDLabel,
1304
    .domainSetSecurityTapFDLabel        = virSecurityDACSetTapFDLabel,
1305

1306
    .domainGetSecurityMountOptions      = virSecurityDACGetMountOptions,
1307 1308

    .getBaseLabel                       = virSecurityDACGetBaseLabel,
1309
};