security_dac.c 43.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
virSecurityDACSetOwnership(const char *path, uid_t uid, gid_t gid)
{
M
Michal Privoznik 已提交
315
    /* XXX record previous ownership */
316 317 318 319 320 321 322 323
    return virSecurityDACSetOwnershipInternal(NULL, NULL, path, uid, gid);
}


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

M
Michal Privoznik 已提交
328
    /* XXX recall previous ownership */
329 330 331 332 333 334 335 336
    return virSecurityDACSetOwnershipInternal(priv, src, path, 0, 0);
}


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


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

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

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

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

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


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

{
381
    virStorageSourcePtr next;
382

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

388
    return 0;
389 390 391 392 393
}


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

    if (!priv->dynamicOwnership)
        return 0;

405 406 407 408 409 410 411
    /* 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;
412

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

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

422 423 424
    /* 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 :-) */
425
    if (migrated) {
426 427 428 429 430 431 432 433 434 435
        int rc = 1;

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

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

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

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


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


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


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

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

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


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


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

500

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


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

    if (!priv->dynamicOwnership)
        return 0;

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

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

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

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

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

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

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

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

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

        if (!pci)
            goto done;

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

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

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

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

        if (!scsi)
            goto done;

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

        break;
    }

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

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


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


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


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


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

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

656 657
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

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

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

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

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

        if (dev->missing)
            return 0;
677

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

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

        break;
    }

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

        if (!pci)
            goto done;

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

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

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

        if (!scsi)
            goto done;

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

        break;
    }

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

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


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

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

753 754
    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

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

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

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

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

793 794 795 796 797 798 799 800 801
    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;

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

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

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

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

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

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

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

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

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


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

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


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

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

    return ret;
}


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

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

    return ret;
}


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

943
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
944

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

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

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

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

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

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

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

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

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

995 996 997 998 999
    return rc;
}


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

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


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

1021 1022
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

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

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

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

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

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

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

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

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

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

1075 1076 1077 1078 1079 1080
    return 0;
}


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

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

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

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


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

    if (!priv->dynamicOwnership)
        return 0;

    return virSecurityDACRestoreSecurityFileLabel(savefile);
}


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

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

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

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

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

    return 0;
1135 1136 1137
}


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

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

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


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

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

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

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

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

1235 1236 1237 1238 1239
    return 0;
}

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

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

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

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

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

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

1341 1342 1343 1344
    return 0;
}

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


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


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

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

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

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

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

1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
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);
}

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

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

1426 1427
    .preFork                            = virSecurityDACPreFork,

1428
    .domainSecurityVerify               = virSecurityDACVerify,
1429

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

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

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

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

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

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

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

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

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

1460
    .domainGetSecurityMountOptions      = virSecurityDACGetMountOptions,
1461 1462

    .getBaseLabel                       = virSecurityDACGetBaseLabel,
1463 1464

    .domainSetDirLabel                  = virSecurityDACDomainSetDirLabel,
1465
};