You need to sign in or sign up before continuing.
security_dac.c 43.4 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
    case VIR_DOMAIN_CHR_TYPE_UNIX:
        if (!dev_source->data.nix.listen) {
            if (virSecurityDACSetOwnership(dev_source->data.nix.path,
                                           user, group) < 0)
                goto done;
        }
        ret = 0;
        break;

801 802 803 804 805 806 807 808 809 810
    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_SPICEVMC:
    case VIR_DOMAIN_CHR_TYPE_NMDM:
    case VIR_DOMAIN_CHR_TYPE_LAST:
811 812 813 814
        ret = 0;
        break;
    }

815
 done:
816 817 818 819 820 821 822
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}

static int
virSecurityDACRestoreChardevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
823
                                  virDomainDefPtr def ATTRIBUTE_UNUSED,
824 825
                                  virDomainChrDefPtr dev,
                                  virDomainChrSourceDefPtr dev_source)
826
{
827
    virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
828 829 830
    char *in = NULL, *out = NULL;
    int ret = -1;

831 832 833 834
    if (dev)
        chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev,
                                                          SECURITY_DAC_NAME);

835
    if (chr_seclabel && !chr_seclabel->relabel)
836 837
        return 0;

838
    switch ((virDomainChrType) dev_source->type) {
839 840
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
841
        ret = virSecurityDACRestoreSecurityFileLabel(dev_source->data.file.path);
842 843 844
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
845 846
        if ((virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0) ||
            (virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0))
847
            goto done;
848 849 850
        if (virFileExists(in) && virFileExists(out)) {
            if ((virSecurityDACRestoreSecurityFileLabel(out) < 0) ||
                (virSecurityDACRestoreSecurityFileLabel(in) < 0)) {
J
Jim Fehlig 已提交
851
                goto done;
852
            }
853
        } else if (virSecurityDACRestoreSecurityFileLabel(dev_source->data.file.path) < 0) {
854 855
            goto done;
        }
856 857 858
        ret = 0;
        break;

859 860 861 862 863 864 865 866 867 868 869
    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:
870 871 872 873
        ret = 0;
        break;
    }

874
 done:
875 876 877 878 879 880 881
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}


static int
882
virSecurityDACRestoreChardevCallback(virDomainDefPtr def,
883 884 885 886 887
                                     virDomainChrDefPtr dev,
                                     void *opaque)
{
    virSecurityManagerPtr mgr = opaque;

888
    return virSecurityDACRestoreChardevLabel(mgr, def, dev, &dev->source);
889 890 891
}


892 893 894 895 896 897 898 899 900
static int
virSecurityDACSetSecurityTPMFileLabel(virSecurityManagerPtr mgr,
                                      virDomainDefPtr def,
                                      virDomainTPMDefPtr tpm)
{
    int ret = 0;

    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
901
        ret = virSecurityDACSetChardevLabel(mgr, def, NULL,
902 903 904 905 906 907 908 909 910 911 912
                                            &tpm->data.passthrough.source);
        break;
    case VIR_DOMAIN_TPM_TYPE_LAST:
        break;
    }

    return ret;
}


static int
O
Osier Yang 已提交
913
virSecurityDACRestoreSecurityTPMFileLabel(virSecurityManagerPtr mgr,
914
                                          virDomainDefPtr def,
O
Osier Yang 已提交
915
                                          virDomainTPMDefPtr tpm)
916 917 918 919 920
{
    int ret = 0;

    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
921
        ret = virSecurityDACRestoreChardevLabel(mgr, def, NULL,
922 923 924 925 926 927 928 929 930 931
                                          &tpm->data.passthrough.source);
        break;
    case VIR_DOMAIN_TPM_TYPE_LAST:
        break;
    }

    return ret;
}


932 933
static int
virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
934
                                      virDomainDefPtr def,
935
                                      bool migrated)
936 937
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
938
    virSecurityLabelDefPtr secdef;
939
    size_t i;
940 941
    int rc = 0;

942
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
943

944
    if (!priv->dynamicOwnership || (secdef && !secdef->relabel))
945
        return 0;
946 947

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

950
    for (i = 0; i < def->nhostdevs; i++) {
951
        if (virSecurityDACRestoreSecurityHostdevLabel(mgr,
952
                                                      def,
953 954
                                                      def->hostdevs[i],
                                                      NULL) < 0)
955 956
            rc = -1;
    }
957
    for (i = 0; i < def->ndisks; i++) {
958
        if (virSecurityDACRestoreSecurityImageLabelInt(mgr,
959
                                                       def,
960
                                                       def->disks[i]->src,
961 962 963 964
                                                       migrated) < 0)
            rc = -1;
    }

965
    if (virDomainChrDefForeach(def,
966 967
                               false,
                               virSecurityDACRestoreChardevCallback,
968
                               mgr) < 0)
969 970
        rc = -1;

971 972
    if (def->tpm) {
        if (virSecurityDACRestoreSecurityTPMFileLabel(mgr,
973
                                                      def,
974 975 976 977
                                                      def->tpm) < 0)
            rc = -1;
    }

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

982 983
    if (def->os.kernel &&
        virSecurityDACRestoreSecurityFileLabel(def->os.kernel) < 0)
984 985
        rc = -1;

986 987
    if (def->os.initrd &&
        virSecurityDACRestoreSecurityFileLabel(def->os.initrd) < 0)
988 989
        rc = -1;

O
Olivia Yin 已提交
990 991 992 993
    if (def->os.dtb &&
        virSecurityDACRestoreSecurityFileLabel(def->os.dtb) < 0)
        rc = -1;

994 995 996 997 998
    return rc;
}


static int
999
virSecurityDACSetChardevCallback(virDomainDefPtr def,
1000 1001 1002 1003 1004
                                 virDomainChrDefPtr dev,
                                 void *opaque)
{
    virSecurityManagerPtr mgr = opaque;

1005
    return virSecurityDACSetChardevLabel(mgr, def, dev, &dev->source);
1006 1007 1008 1009 1010
}


static int
virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
1011
                                  virDomainDefPtr def,
1012 1013 1014
                                  const char *stdin_path ATTRIBUTE_UNUSED)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
1015
    virSecurityLabelDefPtr secdef;
1016
    size_t i;
1017 1018
    uid_t user;
    gid_t group;
1019

1020 1021
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

1022
    if (!priv->dynamicOwnership || (secdef && !secdef->relabel))
1023 1024
        return 0;

1025
    for (i = 0; i < def->ndisks; i++) {
1026
        /* XXX fixme - we need to recursively label the entire tree :-( */
E
Eric Blake 已提交
1027
        if (virDomainDiskGetType(def->disks[i]) == VIR_STORAGE_TYPE_DIR)
1028
            continue;
1029 1030 1031
        if (virSecurityDACSetSecurityDiskLabel(mgr,
                                               def,
                                               def->disks[i]) < 0)
1032 1033
            return -1;
    }
1034
    for (i = 0; i < def->nhostdevs; i++) {
1035
        if (virSecurityDACSetSecurityHostdevLabel(mgr,
1036
                                                  def,
1037 1038
                                                  def->hostdevs[i],
                                                  NULL) < 0)
1039 1040 1041
            return -1;
    }

1042
    if (virDomainChrDefForeach(def,
1043 1044
                               true,
                               virSecurityDACSetChardevCallback,
1045
                               mgr) < 0)
1046 1047
        return -1;

1048 1049 1050 1051 1052 1053 1054
    if (def->tpm) {
        if (virSecurityDACSetSecurityTPMFileLabel(mgr,
                                                  def,
                                                  def->tpm) < 0)
            return -1;
    }

1055
    if (virSecurityDACGetImageIds(secdef, priv, &user, &group))
1056 1057
        return -1;

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

1062
    if (def->os.kernel &&
1063
        virSecurityDACSetOwnership(def->os.kernel, user, group) < 0)
1064 1065
        return -1;

1066
    if (def->os.initrd &&
1067
        virSecurityDACSetOwnership(def->os.initrd, user, group) < 0)
1068 1069
        return -1;

O
Olivia Yin 已提交
1070 1071 1072 1073
    if (def->os.dtb &&
        virSecurityDACSetOwnership(def->os.dtb, user, group) < 0)
        return -1;

1074 1075 1076 1077 1078 1079
    return 0;
}


static int
virSecurityDACSetSavedStateLabel(virSecurityManagerPtr mgr,
1080
                                 virDomainDefPtr def,
1081 1082
                                 const char *savefile)
{
1083 1084
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1085 1086
    uid_t user;
    gid_t group;
1087

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

    if (virSecurityDACGetImageIds(secdef, priv, &user, &group) < 0)
1091 1092 1093
        return -1;

    return virSecurityDACSetOwnership(savefile, user, group);
1094 1095 1096 1097 1098
}


static int
virSecurityDACRestoreSavedStateLabel(virSecurityManagerPtr mgr,
1099
                                     virDomainDefPtr def ATTRIBUTE_UNUSED,
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
                                     const char *savefile)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    if (!priv->dynamicOwnership)
        return 0;

    return virSecurityDACRestoreSecurityFileLabel(savefile);
}


static int
virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr,
1113
                              virDomainDefPtr def)
1114
{
1115 1116
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1117 1118
    uid_t user;
    gid_t group;
1119 1120
    gid_t *groups;
    int ngroups;
1121

1122 1123 1124
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

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

1127 1128
    VIR_DEBUG("Dropping privileges of DEF to %u:%u, %d supplemental groups",
              (unsigned int) user, (unsigned int) group, ngroups);
1129

1130
    if (virSetUIDGID(user, group, groups, ngroups) < 0)
1131 1132 1133
        return -1;

    return 0;
1134 1135 1136
}


1137 1138
static int
virSecurityDACSetChildProcessLabel(virSecurityManagerPtr mgr,
1139
                                   virDomainDefPtr def,
1140 1141
                                   virCommandPtr cmd)
{
1142 1143
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1144 1145 1146
    uid_t user;
    gid_t group;

1147 1148 1149
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (virSecurityDACGetIds(secdef, priv, &user, &group, NULL, NULL))
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
        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;
}


1161 1162 1163 1164 1165 1166 1167 1168
static int
virSecurityDACVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                     virDomainDefPtr def ATTRIBUTE_UNUSED)
{
    return 0;
}

static int
1169 1170
virSecurityDACGenLabel(virSecurityManagerPtr mgr,
                       virDomainDefPtr def)
1171
{
1172 1173 1174 1175 1176
    int rc = -1;
    virSecurityLabelDefPtr seclabel;
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
1177
    if (seclabel == NULL)
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
        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;
    }

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

1228
    if (seclabel->relabel && !seclabel->imagelabel &&
1229 1230 1231
        VIR_STRDUP(seclabel->imagelabel, seclabel->label) < 0) {
        VIR_FREE(seclabel->label);
        return rc;
1232 1233
    }

1234 1235 1236 1237 1238
    return 0;
}

static int
virSecurityDACReleaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1239
                           virDomainDefPtr def ATTRIBUTE_UNUSED)
1240 1241 1242 1243 1244 1245
{
    return 0;
}

static int
virSecurityDACReserveLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1246 1247
                           virDomainDefPtr def ATTRIBUTE_UNUSED,
                           pid_t pid ATTRIBUTE_UNUSED)
1248 1249 1250 1251
{
    return 0;
}

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
#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
J
Ján Tomko 已提交
1309 1310
virSecurityDACGetProcessLabelInternal(pid_t pid ATTRIBUTE_UNUSED,
                                      virSecurityLabelPtr seclabel ATTRIBUTE_UNUSED)
1311 1312 1313 1314 1315 1316 1317
{
    virReportSystemError(ENOSYS, "%s",
                         _("Cannot get process uid and gid on this platform"));
    return -1;
}
#endif

1318 1319
static int
virSecurityDACGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1320
                              virDomainDefPtr def,
1321
                              pid_t pid,
1322
                              virSecurityLabelPtr seclabel)
1323
{
1324 1325 1326
    virSecurityLabelDefPtr secdef =
        virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

1327 1328 1329 1330 1331 1332 1333 1334
    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;
    }
1335 1336

    if (secdef->label)
1337 1338
        ignore_value(virStrcpy(seclabel->label, secdef->label,
                               VIR_SECURITY_LABEL_BUFLEN));
1339

1340 1341 1342 1343
    return 0;
}

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


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


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

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

1374 1375 1376 1377 1378 1379 1380 1381
static int
virSecurityDACSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                            virDomainDefPtr def ATTRIBUTE_UNUSED,
                            int fd ATTRIBUTE_UNUSED)
{
    return 0;
}

O
Osier Yang 已提交
1382 1383 1384 1385
static char *
virSecurityDACGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                              virDomainDefPtr vm ATTRIBUTE_UNUSED)
{
1386 1387 1388
    return NULL;
}

1389 1390 1391 1392 1393 1394 1395 1396
static const char *
virSecurityDACGetBaseLabel(virSecurityManagerPtr mgr,
                           int virt ATTRIBUTE_UNUSED)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    return priv->baselabel;
}

1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414
static int
virSecurityDACDomainSetDirLabel(virSecurityManagerPtr mgr,
                                virDomainDefPtr def,
                                const char *path)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr seclabel;
    uid_t user;
    gid_t group;

    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (virSecurityDACGetIds(seclabel, priv, &user, &group, NULL, NULL) < 0)
        return -1;

    return virSecurityDACSetOwnership(path, user, group);
}

1415
virSecurityDriver virSecurityDriverDAC = {
1416
    .privateDataLen                     = sizeof(virSecurityDACData),
1417
    .name                               = SECURITY_DAC_NAME,
1418 1419 1420
    .probe                              = virSecurityDACProbe,
    .open                               = virSecurityDACOpen,
    .close                              = virSecurityDACClose,
1421

1422 1423
    .getModel                           = virSecurityDACGetModel,
    .getDOI                             = virSecurityDACGetDOI,
1424

1425 1426
    .preFork                            = virSecurityDACPreFork,

1427
    .domainSecurityVerify               = virSecurityDACVerify,
1428

1429
    .domainSetSecurityDiskLabel         = virSecurityDACSetSecurityDiskLabel,
1430
    .domainRestoreSecurityDiskLabel     = virSecurityDACRestoreSecurityDiskLabel,
1431

1432
    .domainSetSecurityImageLabel        = virSecurityDACSetSecurityImageLabel,
1433 1434
    .domainRestoreSecurityImageLabel    = virSecurityDACRestoreSecurityImageLabel,

1435 1436 1437
    .domainSetSecurityDaemonSocketLabel = virSecurityDACSetDaemonSocketLabel,
    .domainSetSecuritySocketLabel       = virSecurityDACSetSocketLabel,
    .domainClearSecuritySocketLabel     = virSecurityDACClearSocketLabel,
1438

1439 1440 1441
    .domainGenSecurityLabel             = virSecurityDACGenLabel,
    .domainReserveSecurityLabel         = virSecurityDACReserveLabel,
    .domainReleaseSecurityLabel         = virSecurityDACReleaseLabel,
1442

1443 1444
    .domainGetSecurityProcessLabel      = virSecurityDACGetProcessLabel,
    .domainSetSecurityProcessLabel      = virSecurityDACSetProcessLabel,
1445
    .domainSetSecurityChildProcessLabel = virSecurityDACSetChildProcessLabel,
1446

1447 1448
    .domainSetSecurityAllLabel          = virSecurityDACSetSecurityAllLabel,
    .domainRestoreSecurityAllLabel      = virSecurityDACRestoreSecurityAllLabel,
1449

1450 1451
    .domainSetSecurityHostdevLabel      = virSecurityDACSetSecurityHostdevLabel,
    .domainRestoreSecurityHostdevLabel  = virSecurityDACRestoreSecurityHostdevLabel,
1452

1453 1454
    .domainSetSavedStateLabel           = virSecurityDACSetSavedStateLabel,
    .domainRestoreSavedStateLabel       = virSecurityDACRestoreSavedStateLabel,
1455

1456
    .domainSetSecurityImageFDLabel      = virSecurityDACSetImageFDLabel,
1457
    .domainSetSecurityTapFDLabel        = virSecurityDACSetTapFDLabel,
1458

1459
    .domainGetSecurityMountOptions      = virSecurityDACGetMountOptions,
1460 1461

    .getBaseLabel                       = virSecurityDACGetBaseLabel,
1462 1463

    .domainSetDirLabel                  = virSecurityDACDomainSetDirLabel,
1464
};