security_dac.c 42.5 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
 *
 * POSIX DAC security driver
 */

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

26 27 28 29 30
#ifdef  __FreeBSD__
# include <sys/sysctl.h>
# include <sys/user.h>
#endif

31
#include "security_dac.h"
32
#include "virerror.h"
33
#include "virfile.h"
34
#include "viralloc.h"
35
#include "virlog.h"
36
#include "virpci.h"
37
#include "virusb.h"
38
#include "virscsi.h"
39
#include "virstoragefile.h"
40
#include "virstring.h"
M
Martin Kletzander 已提交
41
#include "virutil.h"
42 43

#define VIR_FROM_THIS VIR_FROM_SECURITY
44 45 46

VIR_LOG_INIT("security.security_dac");

47
#define SECURITY_DAC_NAME "dac"
48 49 50 51 52 53 54

typedef struct _virSecurityDACData virSecurityDACData;
typedef virSecurityDACData *virSecurityDACDataPtr;

struct _virSecurityDACData {
    uid_t user;
    gid_t group;
55 56
    gid_t *groups;
    int ngroups;
57
    bool dynamicOwnership;
58
    char *baselabel;
59
    virSecurityManagerDACChownCallback chownCallback;
60 61
};

62 63 64 65 66 67 68 69
typedef struct _virSecurityDACCallbackData virSecurityDACCallbackData;
typedef virSecurityDACCallbackData *virSecurityDACCallbackDataPtr;

struct _virSecurityDACCallbackData {
    virSecurityManagerPtr manager;
    virSecurityLabelDefPtr secdef;
};

70 71 72 73 74
/* returns -1 on error, 0 on success */
int
virSecurityDACSetUserAndGroup(virSecurityManagerPtr mgr,
                              uid_t user,
                              gid_t group)
75 76 77 78
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    priv->user = user;
    priv->group = group;
79

80
    if (virAsprintf(&priv->baselabel, "+%u:+%u",
81 82 83 84 85
                    (unsigned int) user,
                    (unsigned int) group) < 0)
        return -1;

    return 0;
86 87
}

O
Osier Yang 已提交
88 89 90
void
virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr,
                                  bool dynamicOwnership)
91 92 93 94 95
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    priv->dynamicOwnership = dynamicOwnership;
}

96 97 98 99 100 101 102 103
void
virSecurityDACSetChownCallback(virSecurityManagerPtr mgr,
                               virSecurityManagerDACChownCallback chownCallback)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    priv->chownCallback = chownCallback;
}

104
/* returns 1 if label isn't found, 0 on success, -1 on error */
O
Osier Yang 已提交
105
static int
106
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
107 108
virSecurityDACParseIds(virSecurityLabelDefPtr seclabel,
                       uid_t *uidPtr, gid_t *gidPtr)
109
{
110
    if (!seclabel || !seclabel->label)
111
        return 1;
112

113
    if (virParseOwnershipIds(seclabel->label, uidPtr, gidPtr) < 0)
114 115 116 117 118
        return -1;

    return 0;
}

O
Osier Yang 已提交
119
static int
120
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
121 122
virSecurityDACGetIds(virSecurityLabelDefPtr seclabel,
                     virSecurityDACDataPtr priv,
123 124
                     uid_t *uidPtr, gid_t *gidPtr,
                     gid_t **groups, int *ngroups)
125
{
126 127
    int ret;

128 129 130 131 132
    if (groups)
        *groups = priv ? priv->groups : NULL;
    if (ngroups)
        *ngroups = priv ? priv->ngroups : 0;

133
    if ((ret = virSecurityDACParseIds(seclabel, uidPtr, gidPtr)) <= 0)
134 135 136
        return ret;

    if (!priv) {
137 138
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("DAC seclabel couldn't be determined"));
139 140 141
        return -1;
    }

142 143
    *uidPtr = priv->user;
    *gidPtr = priv->group;
144 145

    return 0;
146 147
}

148 149

/* returns 1 if label isn't found, 0 on success, -1 on error */
O
Osier Yang 已提交
150
static int
151
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
152
virSecurityDACParseImageIds(virSecurityLabelDefPtr seclabel,
O
Osier Yang 已提交
153
                            uid_t *uidPtr, gid_t *gidPtr)
154
{
155
    if (!seclabel || !seclabel->imagelabel)
156
        return 1;
157

158
    if (virParseOwnershipIds(seclabel->imagelabel, uidPtr, gidPtr) < 0)
159 160 161 162 163
        return -1;

    return 0;
}

O
Osier Yang 已提交
164
static int
165
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
166 167
virSecurityDACGetImageIds(virSecurityLabelDefPtr seclabel,
                          virSecurityDACDataPtr priv,
O
Osier Yang 已提交
168
                          uid_t *uidPtr, gid_t *gidPtr)
169
{
170 171
    int ret;

172
    if ((ret = virSecurityDACParseImageIds(seclabel, uidPtr, gidPtr)) <= 0)
173 174 175
        return ret;

    if (!priv) {
176 177
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("DAC imagelabel couldn't be determined"));
178
        return -1;
179
    }
180

181 182
    *uidPtr = priv->user;
    *gidPtr = priv->group;
183 184

    return 0;
185 186 187
}


188
static virSecurityDriverStatus
189
virSecurityDACProbe(const char *virtDriver ATTRIBUTE_UNUSED)
190 191 192 193 194 195 196 197 198 199 200
{
    return SECURITY_DRIVER_ENABLE;
}

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

static int
201
virSecurityDACClose(virSecurityManagerPtr mgr)
202
{
203 204
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    VIR_FREE(priv->groups);
205
    VIR_FREE(priv->baselabel);
206 207 208 209
    return 0;
}


O
Osier Yang 已提交
210 211
static const char *
virSecurityDACGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
212
{
213
    return SECURITY_DAC_NAME;
214 215
}

O
Osier Yang 已提交
216 217
static const char *
virSecurityDACGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
218 219 220 221
{
    return "0";
}

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
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;
}

237
static int
238 239 240 241 242
virSecurityDACSetOwnershipInternal(virSecurityDACDataPtr priv,
                                   virStorageSourcePtr src,
                                   const char *path,
                                   uid_t uid,
                                   gid_t gid)
243
{
244 245 246
    int rc;
    int chown_errno;

247
    VIR_INFO("Setting DAC user and group on '%s' to '%ld:%ld'",
248 249 250 251 252 253 254 255 256 257
             NULLSTR(src ? src->path : path), (long) uid, (long) gid);

    if (priv && src && priv->chownCallback) {
        rc = priv->chownCallback(src, uid, gid);
        /* here path is used only for error messages */
        path = NULLSTR(src->path);

        /* on -2 returned an error was already reported */
        if (rc == -2)
            return -1;
258

259 260 261
        /* on -1 only errno was set */
        chown_errno = errno;
    } else {
262 263
        struct stat sb;

264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
        if (!path) {
            if (!src || !src->path)
                return 0;

            if (!virStorageSourceIsLocalStorage(src))
                return 0;

            path = src->path;
        }

        rc = chown(path, uid, gid);
        chown_errno = errno;

        if (rc < 0 &&
            stat(path, &sb) >= 0) {
279 280 281 282 283 284
            if (sb.st_uid == uid &&
                sb.st_gid == gid) {
                /* It's alright, there's nothing to change anyway. */
                return 0;
            }
        }
285
    }
286

287
    if (rc < 0) {
288
        if (chown_errno == EOPNOTSUPP || chown_errno == EINVAL) {
289 290 291
            VIR_INFO("Setting user and group to '%ld:%ld' on '%s' not "
                     "supported by filesystem",
                     (long) uid, (long) gid, path);
292
        } else if (chown_errno == EPERM) {
293 294 295
            VIR_INFO("Setting user and group to '%ld:%ld' on '%s' not "
                     "permitted",
                     (long) uid, (long) gid, path);
296
        } else if (chown_errno == EROFS) {
297 298 299
            VIR_INFO("Setting user and group to '%ld:%ld' on '%s' not "
                     "possible on readonly filesystem",
                     (long) uid, (long) gid, path);
300 301
        } else {
            virReportSystemError(chown_errno,
302 303 304
                                 _("unable to set user and group to '%ld:%ld' "
                                   "on '%s'"),
                                 (long) uid, (long) gid, path);
305 306 307 308 309 310
            return -1;
        }
    }
    return 0;
}

311

312
static int
313 314 315 316 317 318 319 320 321 322
virSecurityDACSetOwnership(const char *path, uid_t uid, gid_t gid)
{
    return virSecurityDACSetOwnershipInternal(NULL, NULL, path, uid, gid);
}


static int
virSecurityDACRestoreSecurityFileLabelInternal(virSecurityDACDataPtr priv,
                                               virStorageSourcePtr src,
                                               const char *path)
323
{
324 325
    VIR_INFO("Restoring DAC user and group on '%s'",
             NULLSTR(src ? src->path : path));
326 327

    /* XXX record previous ownership */
328 329 330 331 332 333 334 335
    return virSecurityDACSetOwnershipInternal(priv, src, path, 0, 0);
}


static int
virSecurityDACRestoreSecurityFileLabel(const char *path)
{
    return virSecurityDACRestoreSecurityFileLabelInternal(NULL, NULL, path);
336 337 338 339
}


static int
340 341 342
virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr,
                                    virDomainDefPtr def,
                                    virStorageSourcePtr src)
343
{
344
    virSecurityLabelDefPtr secdef;
345
    virSecurityDeviceLabelDefPtr disk_seclabel;
346
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
347 348 349
    uid_t user;
    gid_t group;

350 351 352 353
    if (!priv->dynamicOwnership)
        return 0;

    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
354
    if (secdef && !secdef->relabel)
355
        return 0;
356

357 358
    disk_seclabel = virStorageSourceGetSecurityLabelDef(src,
                                                        SECURITY_DAC_NAME);
359
    if (disk_seclabel && !disk_seclabel->relabel)
360 361 362 363 364 365 366 367 368
        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;
    }
369

370
    return virSecurityDACSetOwnershipInternal(priv, src, NULL, user, group);
371 372 373 374
}


static int
375 376 377
virSecurityDACSetSecurityDiskLabel(virSecurityManagerPtr mgr,
                                   virDomainDefPtr def,
                                   virDomainDiskDefPtr disk)
378 379

{
380
    virStorageSourcePtr next;
381

382 383 384 385
    for (next = disk->src; next; next = next->backingStore) {
        if (virSecurityDACSetSecurityImageLabel(mgr, def, next) < 0)
            return -1;
    }
386

387
    return 0;
388 389 390 391 392
}


static int
virSecurityDACRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
393
                                           virDomainDefPtr def,
394
                                           virStorageSourcePtr src,
395
                                           bool migrated)
396 397
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
398 399
    virSecurityLabelDefPtr secdef;
    virSecurityDeviceLabelDefPtr disk_seclabel;
400 401 402 403

    if (!priv->dynamicOwnership)
        return 0;

404 405 406 407 408 409 410
    /* 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 (src->readonly || src->shared)
        return 0;
411

412
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
413
    if (secdef && !secdef->relabel)
414 415
        return 0;

416
    disk_seclabel = virStorageSourceGetSecurityLabelDef(src,
417
                                                        SECURITY_DAC_NAME);
418
    if (disk_seclabel && !disk_seclabel->relabel)
419 420
        return 0;

421 422 423
    /* If we have a shared FS and are doing migration, 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 :-) */
424
    if (migrated) {
425 426 427 428 429 430 431 432 433 434
        int rc = 1;

        if (virStorageSourceIsLocalStorage(src)) {
            if (!src->path)
                return 0;

            if ((rc = virFileIsSharedFS(src->path)) < 0)
                return -1;
        }

435 436
        if (rc == 1) {
            VIR_DEBUG("Skipping image label restore on %s because FS is shared",
437
                      src->path);
438 439 440 441
            return 0;
        }
    }

442
    return virSecurityDACRestoreSecurityFileLabelInternal(priv, src, NULL);
443 444 445 446 447 448 449 450 451
}


static int
virSecurityDACRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
                                        virDomainDefPtr def,
                                        virStorageSourcePtr src)
{
    return virSecurityDACRestoreSecurityImageLabelInt(mgr, def, src, false);
452 453 454 455
}


static int
456 457 458
virSecurityDACRestoreSecurityDiskLabel(virSecurityManagerPtr mgr,
                                       virDomainDefPtr def,
                                       virDomainDiskDefPtr disk)
459
{
460
    return virSecurityDACRestoreSecurityImageLabelInt(mgr, def, disk->src, false);
461 462 463 464
}


static int
465 466
virSecurityDACSetSecurityHostdevLabelHelper(const char *file,
                                            void *opaque)
467
{
468 469 470
    virSecurityDACCallbackDataPtr cbdata = opaque;
    virSecurityManagerPtr mgr = cbdata->manager;
    virSecurityLabelDefPtr secdef = cbdata->secdef;
471
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
472 473
    uid_t user;
    gid_t group;
474

475
    if (virSecurityDACGetIds(secdef, priv, &user, &group, NULL, NULL))
476 477 478
        return -1;

    return virSecurityDACSetOwnership(file, user, group);
479 480 481
}


482 483 484 485 486 487 488 489 490
static int
virSecurityDACSetSecurityPCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
                                  const char *file,
                                  void *opaque)
{
    return virSecurityDACSetSecurityHostdevLabelHelper(file, opaque);
}


491
static int
492
virSecurityDACSetSecurityUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
493 494 495
                                  const char *file,
                                  void *opaque)
{
496 497
    return virSecurityDACSetSecurityHostdevLabelHelper(file, opaque);
}
498

499

500 501 502 503 504 505
static int
virSecurityDACSetSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
                                   const char *file,
                                   void *opaque)
{
    return virSecurityDACSetSecurityHostdevLabelHelper(file, opaque);
506 507 508 509 510
}


static int
virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
511
                                      virDomainDefPtr def,
512 513
                                      virDomainHostdevDefPtr dev,
                                      const char *vroot)
514 515
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
516
    virSecurityDACCallbackData cbdata;
517
    virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
518
    virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
519
    virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
520 521 522 523 524 525 526 527
    int ret = -1;

    if (!priv->dynamicOwnership)
        return 0;

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

528 529 530
    /* Like virSecurityDACSetSecurityImageLabel() for a networked disk,
     * do nothing for an iSCSI hostdev
     */
531 532
    if (dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
        scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
533 534
        return 0;

535 536 537
    cbdata.manager = mgr;
    cbdata.secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

538
    if (cbdata.secdef && !cbdata.secdef->relabel)
539 540
        return 0;

541
    switch ((virDomainHostdevSubsysType) dev->source.subsys.type) {
542
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
543
        virUSBDevicePtr usb;
544

545 546 547
        if (dev->missing)
            return 0;

548
        if (!(usb = virUSBDeviceNew(usbsrc->bus, usbsrc->device, vroot)))
549 550
            goto done;

551 552 553
        ret = virUSBDeviceFileIterate(usb,
                                      virSecurityDACSetSecurityUSBLabel,
                                      &cbdata);
554
        virUSBDeviceFree(usb);
555 556 557 558
        break;
    }

    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
559
        virPCIDevicePtr pci =
560 561
            virPCIDeviceNew(pcisrc->addr.domain, pcisrc->addr.bus,
                            pcisrc->addr.slot, pcisrc->addr.function);
562 563 564 565

        if (!pci)
            goto done;

566
        if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
567
            char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
568

569 570
            if (!vfioGroupDev) {
                virPCIDeviceFree(pci);
571
                goto done;
572
            }
573
            ret = virSecurityDACSetSecurityPCILabel(pci, vfioGroupDev, &cbdata);
574 575
            VIR_FREE(vfioGroupDev);
        } else {
576 577 578
            ret = virPCIDeviceFileIterate(pci,
                                          virSecurityDACSetSecurityPCILabel,
                                          &cbdata);
579 580
        }

581
        virPCIDeviceFree(pci);
582 583 584
        break;
    }

585
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
586
        virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
587
        virSCSIDevicePtr scsi =
588
            virSCSIDeviceNew(NULL,
589 590
                             scsihostsrc->adapter, scsihostsrc->bus,
                             scsihostsrc->target, scsihostsrc->unit,
591
                             dev->readonly, dev->shareable);
592 593 594 595

        if (!scsi)
            goto done;

596 597 598
        ret = virSCSIDeviceFileIterate(scsi,
                                       virSecurityDACSetSecuritySCSILabel,
                                       &cbdata);
599 600 601 602 603
        virSCSIDeviceFree(scsi);

        break;
    }

604
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
605 606 607 608
        ret = 0;
        break;
    }

609
 done:
610 611 612 613 614
    return ret;
}


static int
615
virSecurityDACRestoreSecurityPCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
616 617 618 619 620 621 622 623
                                      const char *file,
                                      void *opaque ATTRIBUTE_UNUSED)
{
    return virSecurityDACRestoreSecurityFileLabel(file);
}


static int
624 625 626
virSecurityDACRestoreSecurityUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
                                      const char *file,
                                      void *opaque ATTRIBUTE_UNUSED)
627 628 629 630 631
{
    return virSecurityDACRestoreSecurityFileLabel(file);
}


632 633 634 635 636 637 638 639 640
static int
virSecurityDACRestoreSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
                                       const char *file,
                                       void *opaque ATTRIBUTE_UNUSED)
{
    return virSecurityDACRestoreSecurityFileLabel(file);
}


641 642
static int
virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
643
                                          virDomainDefPtr def,
644 645
                                          virDomainHostdevDefPtr dev,
                                          const char *vroot)
646 647 648

{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
649
    virSecurityLabelDefPtr secdef;
650
    virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
651
    virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
652
    virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
653 654
    int ret = -1;

655 656
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

657
    if (!priv->dynamicOwnership || (secdef && !secdef->relabel))
658 659 660 661 662
        return 0;

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

663 664 665
    /* Like virSecurityDACRestoreSecurityImageLabelInt() for a networked disk,
     * do nothing for an iSCSI hostdev
     */
666 667
    if (dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
        scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
668 669
        return 0;

670
    switch ((virDomainHostdevSubsysType) dev->source.subsys.type) {
671
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
672
        virUSBDevicePtr usb;
673 674 675

        if (dev->missing)
            return 0;
676

677
        if (!(usb = virUSBDeviceNew(usbsrc->bus, usbsrc->device, vroot)))
678 679
            goto done;

680 681
        ret = virUSBDeviceFileIterate(usb, virSecurityDACRestoreSecurityUSBLabel, mgr);
        virUSBDeviceFree(usb);
682 683 684 685 686

        break;
    }

    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
687
        virPCIDevicePtr pci =
688 689
            virPCIDeviceNew(pcisrc->addr.domain, pcisrc->addr.bus,
                            pcisrc->addr.slot, pcisrc->addr.function);
690 691 692 693

        if (!pci)
            goto done;

694
        if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
695
            char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
696

697 698
            if (!vfioGroupDev) {
                virPCIDeviceFree(pci);
699
                goto done;
700
            }
701 702 703 704 705
            ret = virSecurityDACRestoreSecurityPCILabel(pci, vfioGroupDev, mgr);
            VIR_FREE(vfioGroupDev);
        } else {
            ret = virPCIDeviceFileIterate(pci, virSecurityDACRestoreSecurityPCILabel, mgr);
        }
706
        virPCIDeviceFree(pci);
707 708 709
        break;
    }

710
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
711
        virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
712
        virSCSIDevicePtr scsi =
713
            virSCSIDeviceNew(NULL,
714 715
                             scsihostsrc->adapter, scsihostsrc->bus,
                             scsihostsrc->target, scsihostsrc->unit,
716
                             dev->readonly, dev->shareable);
717 718 719 720 721 722 723 724 725 726

        if (!scsi)
            goto done;

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

        break;
    }

727
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
728 729 730 731
        ret = 0;
        break;
    }

732
 done:
733 734 735 736 737 738
    return ret;
}


static int
virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr,
739
                              virDomainDefPtr def,
740 741
                              virDomainChrDefPtr dev,
                              virDomainChrSourceDefPtr dev_source)
742 743 744

{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
745
    virSecurityLabelDefPtr seclabel;
746
    virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
747 748
    char *in = NULL, *out = NULL;
    int ret = -1;
749 750 751
    uid_t user;
    gid_t group;

752 753
    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

754 755 756 757
    if (dev)
        chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev,
                                                          SECURITY_DAC_NAME);

758
    if (chr_seclabel && !chr_seclabel->relabel)
759 760 761 762 763 764 765 766 767
        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;
    }
768

769
    switch ((virDomainChrType) dev_source->type) {
770 771
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
772 773
        ret = virSecurityDACSetOwnership(dev_source->data.file.path,
                                         user, group);
774 775 776
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
777 778
        if ((virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0) ||
            (virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0))
779 780
            goto done;
        if (virFileExists(in) && virFileExists(out)) {
781 782
            if ((virSecurityDACSetOwnership(in, user, group) < 0) ||
                (virSecurityDACSetOwnership(out, user, group) < 0)) {
783
                goto done;
784
            }
785
        } else if (virSecurityDACSetOwnership(dev_source->data.file.path,
786
                                              user, group) < 0) {
787
            goto done;
788 789 790 791
        }
        ret = 0;
        break;

792 793 794 795 796 797 798 799 800 801 802
    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:
803 804 805 806
        ret = 0;
        break;
    }

807
 done:
808 809 810 811 812 813 814
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}

static int
virSecurityDACRestoreChardevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
815
                                  virDomainDefPtr def ATTRIBUTE_UNUSED,
816 817
                                  virDomainChrDefPtr dev,
                                  virDomainChrSourceDefPtr dev_source)
818
{
819
    virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
820 821 822
    char *in = NULL, *out = NULL;
    int ret = -1;

823 824 825 826
    if (dev)
        chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev,
                                                          SECURITY_DAC_NAME);

827
    if (chr_seclabel && !chr_seclabel->relabel)
828 829
        return 0;

830
    switch ((virDomainChrType) dev_source->type) {
831 832
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
833
        ret = virSecurityDACRestoreSecurityFileLabel(dev_source->data.file.path);
834 835 836
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
837 838
        if ((virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0) ||
            (virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0))
839
            goto done;
840 841 842
        if (virFileExists(in) && virFileExists(out)) {
            if ((virSecurityDACRestoreSecurityFileLabel(out) < 0) ||
                (virSecurityDACRestoreSecurityFileLabel(in) < 0)) {
J
Jim Fehlig 已提交
843
                goto done;
844
            }
845
        } else if (virSecurityDACRestoreSecurityFileLabel(dev_source->data.file.path) < 0) {
846 847
            goto done;
        }
848 849 850
        ret = 0;
        break;

851 852 853 854 855 856 857 858 859 860 861
    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:
862 863 864 865
        ret = 0;
        break;
    }

866
 done:
867 868 869 870 871 872 873
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}


static int
874
virSecurityDACRestoreChardevCallback(virDomainDefPtr def,
875 876 877 878 879
                                     virDomainChrDefPtr dev,
                                     void *opaque)
{
    virSecurityManagerPtr mgr = opaque;

880
    return virSecurityDACRestoreChardevLabel(mgr, def, dev, &dev->source);
881 882 883
}


884 885 886 887 888 889 890 891 892
static int
virSecurityDACSetSecurityTPMFileLabel(virSecurityManagerPtr mgr,
                                      virDomainDefPtr def,
                                      virDomainTPMDefPtr tpm)
{
    int ret = 0;

    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
893
        ret = virSecurityDACSetChardevLabel(mgr, def, NULL,
894 895 896 897 898 899 900 901 902 903 904
                                            &tpm->data.passthrough.source);
        break;
    case VIR_DOMAIN_TPM_TYPE_LAST:
        break;
    }

    return ret;
}


static int
O
Osier Yang 已提交
905
virSecurityDACRestoreSecurityTPMFileLabel(virSecurityManagerPtr mgr,
906
                                          virDomainDefPtr def,
O
Osier Yang 已提交
907
                                          virDomainTPMDefPtr tpm)
908 909 910 911 912
{
    int ret = 0;

    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
913
        ret = virSecurityDACRestoreChardevLabel(mgr, def, NULL,
914 915 916 917 918 919 920 921 922 923
                                          &tpm->data.passthrough.source);
        break;
    case VIR_DOMAIN_TPM_TYPE_LAST:
        break;
    }

    return ret;
}


924 925
static int
virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
926
                                      virDomainDefPtr def,
927
                                      bool migrated)
928 929
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
930
    virSecurityLabelDefPtr secdef;
931
    size_t i;
932 933
    int rc = 0;

934
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
935

936
    if (!priv->dynamicOwnership || (secdef && !secdef->relabel))
937
        return 0;
938 939

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

942
    for (i = 0; i < def->nhostdevs; i++) {
943
        if (virSecurityDACRestoreSecurityHostdevLabel(mgr,
944
                                                      def,
945 946
                                                      def->hostdevs[i],
                                                      NULL) < 0)
947 948
            rc = -1;
    }
949
    for (i = 0; i < def->ndisks; i++) {
950
        if (virSecurityDACRestoreSecurityImageLabelInt(mgr,
951
                                                       def,
952
                                                       def->disks[i]->src,
953 954 955 956
                                                       migrated) < 0)
            rc = -1;
    }

957
    if (virDomainChrDefForeach(def,
958 959
                               false,
                               virSecurityDACRestoreChardevCallback,
960
                               mgr) < 0)
961 962
        rc = -1;

963 964
    if (def->tpm) {
        if (virSecurityDACRestoreSecurityTPMFileLabel(mgr,
965
                                                      def,
966 967 968 969
                                                      def->tpm) < 0)
            rc = -1;
    }

970 971 972 973
    if (def->os.loader && def->os.loader->nvram &&
        virSecurityDACRestoreSecurityFileLabel(def->os.loader->nvram) < 0)
        rc = -1;

974 975
    if (def->os.kernel &&
        virSecurityDACRestoreSecurityFileLabel(def->os.kernel) < 0)
976 977
        rc = -1;

978 979
    if (def->os.initrd &&
        virSecurityDACRestoreSecurityFileLabel(def->os.initrd) < 0)
980 981
        rc = -1;

O
Olivia Yin 已提交
982 983 984 985
    if (def->os.dtb &&
        virSecurityDACRestoreSecurityFileLabel(def->os.dtb) < 0)
        rc = -1;

986 987 988 989 990
    return rc;
}


static int
991
virSecurityDACSetChardevCallback(virDomainDefPtr def,
992 993 994 995 996
                                 virDomainChrDefPtr dev,
                                 void *opaque)
{
    virSecurityManagerPtr mgr = opaque;

997
    return virSecurityDACSetChardevLabel(mgr, def, dev, &dev->source);
998 999 1000 1001 1002
}


static int
virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
1003
                                  virDomainDefPtr def,
1004 1005 1006
                                  const char *stdin_path ATTRIBUTE_UNUSED)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
1007
    virSecurityLabelDefPtr secdef;
1008
    size_t i;
1009 1010
    uid_t user;
    gid_t group;
1011

1012 1013
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

1014
    if (!priv->dynamicOwnership || (secdef && !secdef->relabel))
1015 1016
        return 0;

1017
    for (i = 0; i < def->ndisks; i++) {
1018
        /* XXX fixme - we need to recursively label the entire tree :-( */
E
Eric Blake 已提交
1019
        if (virDomainDiskGetType(def->disks[i]) == VIR_STORAGE_TYPE_DIR)
1020
            continue;
1021 1022 1023
        if (virSecurityDACSetSecurityDiskLabel(mgr,
                                               def,
                                               def->disks[i]) < 0)
1024 1025
            return -1;
    }
1026
    for (i = 0; i < def->nhostdevs; i++) {
1027
        if (virSecurityDACSetSecurityHostdevLabel(mgr,
1028
                                                  def,
1029 1030
                                                  def->hostdevs[i],
                                                  NULL) < 0)
1031 1032 1033
            return -1;
    }

1034
    if (virDomainChrDefForeach(def,
1035 1036
                               true,
                               virSecurityDACSetChardevCallback,
1037
                               mgr) < 0)
1038 1039
        return -1;

1040 1041 1042 1043 1044 1045 1046
    if (def->tpm) {
        if (virSecurityDACSetSecurityTPMFileLabel(mgr,
                                                  def,
                                                  def->tpm) < 0)
            return -1;
    }

1047
    if (virSecurityDACGetImageIds(secdef, priv, &user, &group))
1048 1049
        return -1;

1050 1051 1052 1053
    if (def->os.loader && def->os.loader->nvram &&
        virSecurityDACSetOwnership(def->os.loader->nvram, user, group) < 0)
        return -1;

1054
    if (def->os.kernel &&
1055
        virSecurityDACSetOwnership(def->os.kernel, user, group) < 0)
1056 1057
        return -1;

1058
    if (def->os.initrd &&
1059
        virSecurityDACSetOwnership(def->os.initrd, user, group) < 0)
1060 1061
        return -1;

O
Olivia Yin 已提交
1062 1063 1064 1065
    if (def->os.dtb &&
        virSecurityDACSetOwnership(def->os.dtb, user, group) < 0)
        return -1;

1066 1067 1068 1069 1070 1071
    return 0;
}


static int
virSecurityDACSetSavedStateLabel(virSecurityManagerPtr mgr,
1072
                                 virDomainDefPtr def,
1073 1074
                                 const char *savefile)
{
1075 1076
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1077 1078
    uid_t user;
    gid_t group;
1079

1080 1081 1082
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (virSecurityDACGetImageIds(secdef, priv, &user, &group) < 0)
1083 1084 1085
        return -1;

    return virSecurityDACSetOwnership(savefile, user, group);
1086 1087 1088 1089 1090
}


static int
virSecurityDACRestoreSavedStateLabel(virSecurityManagerPtr mgr,
1091
                                     virDomainDefPtr def ATTRIBUTE_UNUSED,
1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
                                     const char *savefile)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    if (!priv->dynamicOwnership)
        return 0;

    return virSecurityDACRestoreSecurityFileLabel(savefile);
}


static int
virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr,
1105
                              virDomainDefPtr def)
1106
{
1107 1108
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1109 1110
    uid_t user;
    gid_t group;
1111 1112
    gid_t *groups;
    int ngroups;
1113

1114 1115 1116
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

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

1119 1120
    VIR_DEBUG("Dropping privileges of DEF to %u:%u, %d supplemental groups",
              (unsigned int) user, (unsigned int) group, ngroups);
1121

1122
    if (virSetUIDGID(user, group, groups, ngroups) < 0)
1123 1124 1125
        return -1;

    return 0;
1126 1127 1128
}


1129 1130
static int
virSecurityDACSetChildProcessLabel(virSecurityManagerPtr mgr,
1131
                                   virDomainDefPtr def,
1132 1133
                                   virCommandPtr cmd)
{
1134 1135
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1136 1137 1138
    uid_t user;
    gid_t group;

1139 1140 1141
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (virSecurityDACGetIds(secdef, priv, &user, &group, NULL, NULL))
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
        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;
}


1153 1154 1155 1156 1157 1158 1159 1160
static int
virSecurityDACVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                     virDomainDefPtr def ATTRIBUTE_UNUSED)
{
    return 0;
}

static int
1161 1162
virSecurityDACGenLabel(virSecurityManagerPtr mgr,
                       virDomainDefPtr def)
1163
{
1164 1165 1166 1167 1168
    int rc = -1;
    virSecurityLabelDefPtr seclabel;
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
1169
    if (seclabel == NULL)
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
        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;
    }

1188
    switch ((virDomainSeclabelType) seclabel->type) {
1189 1190 1191 1192 1193 1194 1195 1196 1197
    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:
1198
        if (virAsprintf(&seclabel->label, "+%u:+%u",
1199
                        (unsigned int) priv->user,
1200
                        (unsigned int) priv->group) < 0)
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
            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 */
1211
        return 0;
1212 1213
    case VIR_DOMAIN_SECLABEL_DEFAULT:
    case VIR_DOMAIN_SECLABEL_LAST:
1214 1215 1216 1217 1218 1219
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected security label type '%s'"),
                       virDomainSeclabelTypeToString(seclabel->type));
        return rc;
    }

1220
    if (seclabel->relabel && !seclabel->imagelabel &&
1221 1222 1223
        VIR_STRDUP(seclabel->imagelabel, seclabel->label) < 0) {
        VIR_FREE(seclabel->label);
        return rc;
1224 1225
    }

1226 1227 1228 1229 1230
    return 0;
}

static int
virSecurityDACReleaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1231
                           virDomainDefPtr def ATTRIBUTE_UNUSED)
1232 1233 1234 1235 1236 1237
{
    return 0;
}

static int
virSecurityDACReserveLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1238 1239
                           virDomainDefPtr def ATTRIBUTE_UNUSED,
                           pid_t pid ATTRIBUTE_UNUSED)
1240 1241 1242 1243
{
    return 0;
}

1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309
#ifdef __linux__
static int
virSecurityDACGetProcessLabelInternal(pid_t pid,
                                      virSecurityLabelPtr seclabel)
{
    struct stat sb;
    char *path = NULL;
    int ret = -1;

    VIR_DEBUG("Getting DAC user and group on process '%d'", pid);

    if (virAsprintf(&path, "/proc/%d", (int) pid) < 0)
        goto cleanup;

    if (lstat(path, &sb) < 0) {
        virReportSystemError(errno,
                             _("unable to get uid and gid for PID %d via procfs"),
                             pid);
        goto cleanup;
    }

    snprintf(seclabel->label, VIR_SECURITY_LABEL_BUFLEN,
             "+%u:+%u", (unsigned int) sb.st_uid, (unsigned int) sb.st_gid);
    ret = 0;

 cleanup:
    VIR_FREE(path);
    return ret;
}
#elif defined(__FreeBSD__)
static int
virSecurityDACGetProcessLabelInternal(pid_t pid,
                                      virSecurityLabelPtr seclabel)
{
    struct kinfo_proc p;
    int mib[4];
    size_t len = 4;

    sysctlnametomib("kern.proc.pid", mib, &len);

    len = sizeof(struct kinfo_proc);
    mib[3] = pid;

    if (sysctl(mib, 4, &p, &len, NULL, 0) < 0) {
        virReportSystemError(errno,
                             _("unable to get PID %d uid and gid via sysctl"),
                             pid);
        return -1;
    }

    snprintf(seclabel->label, VIR_SECURITY_LABEL_BUFLEN,
             "+%u:+%u", (unsigned int) p.ki_uid, (unsigned int) p.ki_groups[0]);

    return 0;
}
#else
static int
virSecurityDACGetProcessLabelInternal(pid_t pid,
                                      virSecurityLabelPtr seclabel)
{
    virReportSystemError(ENOSYS, "%s",
                         _("Cannot get process uid and gid on this platform"));
    return -1;
}
#endif

1310 1311
static int
virSecurityDACGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1312
                              virDomainDefPtr def,
1313
                              pid_t pid,
1314
                              virSecurityLabelPtr seclabel)
1315
{
1316 1317 1318
    virSecurityLabelDefPtr secdef =
        virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

1319 1320 1321 1322 1323 1324 1325 1326
    if (secdef == NULL) {
        VIR_DEBUG("missing label for DAC security "
                  "driver in domain %s", def->name);

        if (virSecurityDACGetProcessLabelInternal(pid, seclabel) < 0)
            return -1;
        return 0;
    }
1327 1328

    if (secdef->label)
1329 1330
        ignore_value(virStrcpy(seclabel->label, secdef->label,
                               VIR_SECURITY_LABEL_BUFLEN));
1331

1332 1333 1334 1335
    return 0;
}

static int
1336
virSecurityDACSetDaemonSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1337
                                   virDomainDefPtr vm ATTRIBUTE_UNUSED)
1338 1339 1340 1341 1342
{
    return 0;
}


1343 1344
static int
virSecurityDACSetSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1345
                             virDomainDefPtr def ATTRIBUTE_UNUSED)
1346 1347 1348 1349 1350
{
    return 0;
}


1351 1352
static int
virSecurityDACClearSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1353
                               virDomainDefPtr def ATTRIBUTE_UNUSED)
1354 1355 1356 1357
{
    return 0;
}

1358
static int
1359
virSecurityDACSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1360
                              virDomainDefPtr def ATTRIBUTE_UNUSED,
1361
                              int fd ATTRIBUTE_UNUSED)
1362 1363 1364 1365
{
    return 0;
}

1366 1367 1368 1369 1370 1371 1372 1373
static int
virSecurityDACSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                            virDomainDefPtr def ATTRIBUTE_UNUSED,
                            int fd ATTRIBUTE_UNUSED)
{
    return 0;
}

O
Osier Yang 已提交
1374 1375 1376 1377
static char *
virSecurityDACGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                              virDomainDefPtr vm ATTRIBUTE_UNUSED)
{
1378 1379 1380
    return NULL;
}

1381 1382 1383 1384 1385 1386 1387 1388
static const char *
virSecurityDACGetBaseLabel(virSecurityManagerPtr mgr,
                           int virt ATTRIBUTE_UNUSED)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    return priv->baselabel;
}

1389
virSecurityDriver virSecurityDriverDAC = {
1390
    .privateDataLen                     = sizeof(virSecurityDACData),
1391
    .name                               = SECURITY_DAC_NAME,
1392 1393 1394
    .probe                              = virSecurityDACProbe,
    .open                               = virSecurityDACOpen,
    .close                              = virSecurityDACClose,
1395

1396 1397
    .getModel                           = virSecurityDACGetModel,
    .getDOI                             = virSecurityDACGetDOI,
1398

1399 1400
    .preFork                            = virSecurityDACPreFork,

1401
    .domainSecurityVerify               = virSecurityDACVerify,
1402

1403
    .domainSetSecurityDiskLabel         = virSecurityDACSetSecurityDiskLabel,
1404
    .domainRestoreSecurityDiskLabel     = virSecurityDACRestoreSecurityDiskLabel,
1405

1406
    .domainSetSecurityImageLabel        = virSecurityDACSetSecurityImageLabel,
1407 1408
    .domainRestoreSecurityImageLabel    = virSecurityDACRestoreSecurityImageLabel,

1409 1410 1411
    .domainSetSecurityDaemonSocketLabel = virSecurityDACSetDaemonSocketLabel,
    .domainSetSecuritySocketLabel       = virSecurityDACSetSocketLabel,
    .domainClearSecuritySocketLabel     = virSecurityDACClearSocketLabel,
1412

1413 1414 1415
    .domainGenSecurityLabel             = virSecurityDACGenLabel,
    .domainReserveSecurityLabel         = virSecurityDACReserveLabel,
    .domainReleaseSecurityLabel         = virSecurityDACReleaseLabel,
1416

1417 1418
    .domainGetSecurityProcessLabel      = virSecurityDACGetProcessLabel,
    .domainSetSecurityProcessLabel      = virSecurityDACSetProcessLabel,
1419
    .domainSetSecurityChildProcessLabel = virSecurityDACSetChildProcessLabel,
1420

1421 1422
    .domainSetSecurityAllLabel          = virSecurityDACSetSecurityAllLabel,
    .domainRestoreSecurityAllLabel      = virSecurityDACRestoreSecurityAllLabel,
1423

1424 1425
    .domainSetSecurityHostdevLabel      = virSecurityDACSetSecurityHostdevLabel,
    .domainRestoreSecurityHostdevLabel  = virSecurityDACRestoreSecurityHostdevLabel,
1426

1427 1428
    .domainSetSavedStateLabel           = virSecurityDACSetSavedStateLabel,
    .domainRestoreSavedStateLabel       = virSecurityDACRestoreSavedStateLabel,
1429

1430
    .domainSetSecurityImageFDLabel      = virSecurityDACSetImageFDLabel,
1431
    .domainSetSecurityTapFDLabel        = virSecurityDACSetTapFDLabel,
1432

1433
    .domainGetSecurityMountOptions      = virSecurityDACGetMountOptions,
1434 1435

    .getBaseLabel                       = virSecurityDACGetBaseLabel,
1436
};