security_dac.c 44.0 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
    int rc;

246
    VIR_INFO("Setting DAC user and group on '%s' to '%ld:%ld'",
247 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;
    } else {
258 259
        struct stat sb;

260 261 262 263 264 265 266 267 268 269
        if (!path) {
            if (!src || !src->path)
                return 0;

            if (!virStorageSourceIsLocalStorage(src))
                return 0;

            path = src->path;
        }

270 271 272 273
        if (stat(path, &sb) < 0) {
            virReportSystemError(errno, _("unable to stat: %s"), path);
            return -1;
        }
274

275 276 277
        if (sb.st_uid == uid && sb.st_gid == gid) {
            /* nothing to chown */
            return 0;
278
        }
279 280

        rc = chown(path, uid, gid);
281
    }
282

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

307

308
static int
309 310 311 312
virSecurityDACSetOwnership(virSecurityDACDataPtr priv,
                           const char *path,
                           uid_t uid,
                           gid_t gid)
313
{
M
Michal Privoznik 已提交
314
    /* XXX record previous ownership */
315
    return virSecurityDACSetOwnershipInternal(priv, NULL, path, uid, gid);
316 317 318 319 320 321 322
}


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

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


static int
333 334
virSecurityDACRestoreSecurityFileLabel(virSecurityDACDataPtr priv,
                                       const char *path)
335
{
336
    return virSecurityDACRestoreSecurityFileLabelInternal(priv, 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
        return -1;

479
    return virSecurityDACSetOwnership(priv, 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
                                      const char *file,
618
                                      void *opaque)
619
{
620 621 622
    virSecurityManagerPtr mgr = opaque;
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    return virSecurityDACRestoreSecurityFileLabel(priv, file);
623 624 625 626
}


static int
627 628
virSecurityDACRestoreSecurityUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
                                      const char *file,
629
                                      void *opaque)
630
{
631 632 633
    virSecurityManagerPtr mgr = opaque;
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    return virSecurityDACRestoreSecurityFileLabel(priv, file);
634 635 636
}


637 638 639
static int
virSecurityDACRestoreSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
                                       const char *file,
640
                                       void *opaque)
641
{
642 643 644
    virSecurityManagerPtr mgr = opaque;
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    return virSecurityDACRestoreSecurityFileLabel(priv, file);
645 646 647
}


648 649
static int
virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
650
                                          virDomainDefPtr def,
651 652
                                          virDomainHostdevDefPtr dev,
                                          const char *vroot)
653 654 655

{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
656
    virSecurityLabelDefPtr secdef;
657
    virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
658
    virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
659
    virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
660 661
    int ret = -1;

662 663
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

664
    if (!priv->dynamicOwnership || (secdef && !secdef->relabel))
665 666 667 668 669
        return 0;

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

670 671 672
    /* Like virSecurityDACRestoreSecurityImageLabelInt() for a networked disk,
     * do nothing for an iSCSI hostdev
     */
673 674
    if (dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
        scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
675 676
        return 0;

677
    switch ((virDomainHostdevSubsysType) dev->source.subsys.type) {
678
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
679
        virUSBDevicePtr usb;
680 681 682

        if (dev->missing)
            return 0;
683

684
        if (!(usb = virUSBDeviceNew(usbsrc->bus, usbsrc->device, vroot)))
685 686
            goto done;

687 688
        ret = virUSBDeviceFileIterate(usb, virSecurityDACRestoreSecurityUSBLabel, mgr);
        virUSBDeviceFree(usb);
689 690 691 692 693

        break;
    }

    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
694
        virPCIDevicePtr pci =
695 696
            virPCIDeviceNew(pcisrc->addr.domain, pcisrc->addr.bus,
                            pcisrc->addr.slot, pcisrc->addr.function);
697 698 699 700

        if (!pci)
            goto done;

701
        if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
702
            char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
703

704 705
            if (!vfioGroupDev) {
                virPCIDeviceFree(pci);
706
                goto done;
707
            }
708 709 710 711 712
            ret = virSecurityDACRestoreSecurityPCILabel(pci, vfioGroupDev, mgr);
            VIR_FREE(vfioGroupDev);
        } else {
            ret = virPCIDeviceFileIterate(pci, virSecurityDACRestoreSecurityPCILabel, mgr);
        }
713
        virPCIDeviceFree(pci);
714 715 716
        break;
    }

717
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
718
        virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
719
        virSCSIDevicePtr scsi =
720
            virSCSIDeviceNew(NULL,
721 722
                             scsihostsrc->adapter, scsihostsrc->bus,
                             scsihostsrc->target, scsihostsrc->unit,
723
                             dev->readonly, dev->shareable);
724 725 726 727 728 729 730 731 732 733

        if (!scsi)
            goto done;

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

        break;
    }

734
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
735 736 737 738
        ret = 0;
        break;
    }

739
 done:
740 741 742 743 744 745
    return ret;
}


static int
virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr,
746
                              virDomainDefPtr def,
747 748
                              virDomainChrDefPtr dev,
                              virDomainChrSourceDefPtr dev_source)
749 750 751

{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
752
    virSecurityLabelDefPtr seclabel;
753
    virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
754 755
    char *in = NULL, *out = NULL;
    int ret = -1;
756 757 758
    uid_t user;
    gid_t group;

759 760
    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

761 762 763 764
    if (dev)
        chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev,
                                                          SECURITY_DAC_NAME);

765
    if (chr_seclabel && !chr_seclabel->relabel)
766 767 768 769 770 771 772 773 774
        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;
    }
775

776
    switch ((virDomainChrType) dev_source->type) {
777 778
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
779
        ret = virSecurityDACSetOwnership(priv, dev_source->data.file.path,
780
                                         user, group);
781 782 783
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
784 785
        if ((virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0) ||
            (virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0))
786 787
            goto done;
        if (virFileExists(in) && virFileExists(out)) {
788 789
            if ((virSecurityDACSetOwnership(priv, in, user, group) < 0) ||
                (virSecurityDACSetOwnership(priv, out, user, group) < 0)) {
790
                goto done;
791
            }
792
        } else if (virSecurityDACSetOwnership(priv, dev_source->data.file.path,
793
                                              user, group) < 0) {
794
            goto done;
795 796 797 798
        }
        ret = 0;
        break;

799 800
    case VIR_DOMAIN_CHR_TYPE_UNIX:
        if (!dev_source->data.nix.listen) {
801
            if (virSecurityDACSetOwnership(priv, dev_source->data.nix.path,
802 803 804 805 806 807
                                           user, group) < 0)
                goto done;
        }
        ret = 0;
        break;

808 809 810 811 812 813 814 815 816 817
    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:
818 819 820 821
        ret = 0;
        break;
    }

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

static int
829
virSecurityDACRestoreChardevLabel(virSecurityManagerPtr mgr,
830
                                  virDomainDefPtr def ATTRIBUTE_UNUSED,
831 832
                                  virDomainChrDefPtr dev,
                                  virDomainChrSourceDefPtr dev_source)
833
{
834
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
835
    virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
836 837 838
    char *in = NULL, *out = NULL;
    int ret = -1;

839 840 841 842
    if (dev)
        chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev,
                                                          SECURITY_DAC_NAME);

843
    if (chr_seclabel && !chr_seclabel->relabel)
844 845
        return 0;

846
    switch ((virDomainChrType) dev_source->type) {
847 848
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
849
        ret = virSecurityDACRestoreSecurityFileLabel(priv, dev_source->data.file.path);
850 851 852
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
853 854
        if ((virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0) ||
            (virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0))
855
            goto done;
856
        if (virFileExists(in) && virFileExists(out)) {
857 858
            if ((virSecurityDACRestoreSecurityFileLabel(priv, out) < 0) ||
                (virSecurityDACRestoreSecurityFileLabel(priv, in) < 0)) {
J
Jim Fehlig 已提交
859
                goto done;
860
            }
861
        } else if (virSecurityDACRestoreSecurityFileLabel(priv, dev_source->data.file.path) < 0) {
862 863
            goto done;
        }
864 865 866
        ret = 0;
        break;

867 868 869 870 871 872 873 874 875 876 877
    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:
878 879 880 881
        ret = 0;
        break;
    }

882
 done:
883 884 885 886 887 888 889
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}


static int
890
virSecurityDACRestoreChardevCallback(virDomainDefPtr def,
891 892 893 894 895
                                     virDomainChrDefPtr dev,
                                     void *opaque)
{
    virSecurityManagerPtr mgr = opaque;

896
    return virSecurityDACRestoreChardevLabel(mgr, def, dev, &dev->source);
897 898 899
}


900 901 902 903 904 905 906 907 908
static int
virSecurityDACSetSecurityTPMFileLabel(virSecurityManagerPtr mgr,
                                      virDomainDefPtr def,
                                      virDomainTPMDefPtr tpm)
{
    int ret = 0;

    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
909
        ret = virSecurityDACSetChardevLabel(mgr, def, NULL,
910 911 912 913 914 915 916 917 918 919 920
                                            &tpm->data.passthrough.source);
        break;
    case VIR_DOMAIN_TPM_TYPE_LAST:
        break;
    }

    return ret;
}


static int
O
Osier Yang 已提交
921
virSecurityDACRestoreSecurityTPMFileLabel(virSecurityManagerPtr mgr,
922
                                          virDomainDefPtr def,
O
Osier Yang 已提交
923
                                          virDomainTPMDefPtr tpm)
924 925 926 927 928
{
    int ret = 0;

    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
929
        ret = virSecurityDACRestoreChardevLabel(mgr, def, NULL,
930 931 932 933 934 935 936 937 938 939
                                          &tpm->data.passthrough.source);
        break;
    case VIR_DOMAIN_TPM_TYPE_LAST:
        break;
    }

    return ret;
}


940 941
static int
virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
942
                                      virDomainDefPtr def,
943
                                      bool migrated)
944 945
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
946
    virSecurityLabelDefPtr secdef;
947
    size_t i;
948 949
    int rc = 0;

950
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
951

952
    if (!priv->dynamicOwnership || (secdef && !secdef->relabel))
953
        return 0;
954 955

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

958
    for (i = 0; i < def->nhostdevs; i++) {
959
        if (virSecurityDACRestoreSecurityHostdevLabel(mgr,
960
                                                      def,
961 962
                                                      def->hostdevs[i],
                                                      NULL) < 0)
963 964
            rc = -1;
    }
965
    for (i = 0; i < def->ndisks; i++) {
966
        if (virSecurityDACRestoreSecurityImageLabelInt(mgr,
967
                                                       def,
968
                                                       def->disks[i]->src,
969 970 971 972
                                                       migrated) < 0)
            rc = -1;
    }

973
    if (virDomainChrDefForeach(def,
974 975
                               false,
                               virSecurityDACRestoreChardevCallback,
976
                               mgr) < 0)
977 978
        rc = -1;

979 980
    if (def->tpm) {
        if (virSecurityDACRestoreSecurityTPMFileLabel(mgr,
981
                                                      def,
982 983 984 985
                                                      def->tpm) < 0)
            rc = -1;
    }

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

990
    if (def->os.kernel &&
991
        virSecurityDACRestoreSecurityFileLabel(priv, def->os.kernel) < 0)
992 993
        rc = -1;

994
    if (def->os.initrd &&
995
        virSecurityDACRestoreSecurityFileLabel(priv, def->os.initrd) < 0)
996 997
        rc = -1;

O
Olivia Yin 已提交
998
    if (def->os.dtb &&
999
        virSecurityDACRestoreSecurityFileLabel(priv, def->os.dtb) < 0)
O
Olivia Yin 已提交
1000 1001
        rc = -1;

1002 1003 1004 1005 1006
    return rc;
}


static int
1007
virSecurityDACSetChardevCallback(virDomainDefPtr def,
1008 1009 1010 1011 1012
                                 virDomainChrDefPtr dev,
                                 void *opaque)
{
    virSecurityManagerPtr mgr = opaque;

1013
    return virSecurityDACSetChardevLabel(mgr, def, dev, &dev->source);
1014 1015 1016 1017 1018
}


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

1028 1029
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

1030
    if (!priv->dynamicOwnership || (secdef && !secdef->relabel))
1031 1032
        return 0;

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

1050
    if (virDomainChrDefForeach(def,
1051 1052
                               true,
                               virSecurityDACSetChardevCallback,
1053
                               mgr) < 0)
1054 1055
        return -1;

1056 1057 1058 1059 1060 1061 1062
    if (def->tpm) {
        if (virSecurityDACSetSecurityTPMFileLabel(mgr,
                                                  def,
                                                  def->tpm) < 0)
            return -1;
    }

1063
    if (virSecurityDACGetImageIds(secdef, priv, &user, &group))
1064 1065
        return -1;

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

1070
    if (def->os.kernel &&
1071
        virSecurityDACSetOwnership(priv, def->os.kernel, user, group) < 0)
1072 1073
        return -1;

1074
    if (def->os.initrd &&
1075
        virSecurityDACSetOwnership(priv, def->os.initrd, user, group) < 0)
1076 1077
        return -1;

O
Olivia Yin 已提交
1078
    if (def->os.dtb &&
1079
        virSecurityDACSetOwnership(priv, def->os.dtb, user, group) < 0)
O
Olivia Yin 已提交
1080 1081
        return -1;

1082 1083 1084 1085 1086 1087
    return 0;
}


static int
virSecurityDACSetSavedStateLabel(virSecurityManagerPtr mgr,
1088
                                 virDomainDefPtr def,
1089 1090
                                 const char *savefile)
{
1091 1092
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1093 1094
    uid_t user;
    gid_t group;
1095

1096 1097 1098
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (virSecurityDACGetImageIds(secdef, priv, &user, &group) < 0)
1099 1100
        return -1;

1101
    return virSecurityDACSetOwnership(priv, savefile, user, group);
1102 1103 1104 1105 1106
}


static int
virSecurityDACRestoreSavedStateLabel(virSecurityManagerPtr mgr,
1107
                                     virDomainDefPtr def ATTRIBUTE_UNUSED,
1108 1109 1110 1111 1112 1113 1114
                                     const char *savefile)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    if (!priv->dynamicOwnership)
        return 0;

1115
    return virSecurityDACRestoreSecurityFileLabel(priv, savefile);
1116 1117 1118 1119 1120
}


static int
virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr,
1121
                              virDomainDefPtr def)
1122
{
1123 1124
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1125 1126
    uid_t user;
    gid_t group;
1127 1128
    gid_t *groups;
    int ngroups;
1129

1130 1131 1132
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

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

1135 1136
    VIR_DEBUG("Dropping privileges of DEF to %u:%u, %d supplemental groups",
              (unsigned int) user, (unsigned int) group, ngroups);
1137

1138
    if (virSetUIDGID(user, group, groups, ngroups) < 0)
1139 1140 1141
        return -1;

    return 0;
1142 1143 1144
}


1145 1146
static int
virSecurityDACSetChildProcessLabel(virSecurityManagerPtr mgr,
1147
                                   virDomainDefPtr def,
1148 1149
                                   virCommandPtr cmd)
{
1150 1151
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1152 1153 1154
    uid_t user;
    gid_t group;

1155 1156 1157
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (virSecurityDACGetIds(secdef, priv, &user, &group, NULL, NULL))
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
        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;
}


1169 1170 1171 1172 1173 1174 1175 1176
static int
virSecurityDACVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                     virDomainDefPtr def ATTRIBUTE_UNUSED)
{
    return 0;
}

static int
1177 1178
virSecurityDACGenLabel(virSecurityManagerPtr mgr,
                       virDomainDefPtr def)
1179
{
1180 1181 1182 1183 1184
    int rc = -1;
    virSecurityLabelDefPtr seclabel;
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
1185
    if (seclabel == NULL)
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
        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;
    }

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

1236
    if (seclabel->relabel && !seclabel->imagelabel &&
1237 1238 1239
        VIR_STRDUP(seclabel->imagelabel, seclabel->label) < 0) {
        VIR_FREE(seclabel->label);
        return rc;
1240 1241
    }

1242 1243 1244 1245 1246
    return 0;
}

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

static int
virSecurityDACReserveLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1254 1255
                           virDomainDefPtr def ATTRIBUTE_UNUSED,
                           pid_t pid ATTRIBUTE_UNUSED)
1256 1257 1258 1259
{
    return 0;
}

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

1326 1327
static int
virSecurityDACGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1328
                              virDomainDefPtr def,
1329
                              pid_t pid,
1330
                              virSecurityLabelPtr seclabel)
1331
{
1332 1333 1334
    virSecurityLabelDefPtr secdef =
        virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

1335 1336 1337 1338 1339 1340 1341 1342
    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;
    }
1343 1344

    if (secdef->label)
1345 1346
        ignore_value(virStrcpy(seclabel->label, secdef->label,
                               VIR_SECURITY_LABEL_BUFLEN));
1347

1348 1349 1350 1351
    return 0;
}

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


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


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

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

1382 1383 1384 1385 1386 1387 1388 1389
static int
virSecurityDACSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                            virDomainDefPtr def ATTRIBUTE_UNUSED,
                            int fd ATTRIBUTE_UNUSED)
{
    return 0;
}

O
Osier Yang 已提交
1390 1391 1392 1393
static char *
virSecurityDACGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                              virDomainDefPtr vm ATTRIBUTE_UNUSED)
{
1394 1395 1396
    return NULL;
}

1397 1398 1399 1400 1401 1402 1403 1404
static const char *
virSecurityDACGetBaseLabel(virSecurityManagerPtr mgr,
                           int virt ATTRIBUTE_UNUSED)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    return priv->baselabel;
}

1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419
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;

1420
    return virSecurityDACSetOwnership(priv, path, user, group);
1421 1422
}

1423
virSecurityDriver virSecurityDriverDAC = {
1424
    .privateDataLen                     = sizeof(virSecurityDACData),
1425
    .name                               = SECURITY_DAC_NAME,
1426 1427 1428
    .probe                              = virSecurityDACProbe,
    .open                               = virSecurityDACOpen,
    .close                              = virSecurityDACClose,
1429

1430 1431
    .getModel                           = virSecurityDACGetModel,
    .getDOI                             = virSecurityDACGetDOI,
1432

1433 1434
    .preFork                            = virSecurityDACPreFork,

1435
    .domainSecurityVerify               = virSecurityDACVerify,
1436

1437
    .domainSetSecurityDiskLabel         = virSecurityDACSetSecurityDiskLabel,
1438
    .domainRestoreSecurityDiskLabel     = virSecurityDACRestoreSecurityDiskLabel,
1439

1440
    .domainSetSecurityImageLabel        = virSecurityDACSetSecurityImageLabel,
1441 1442
    .domainRestoreSecurityImageLabel    = virSecurityDACRestoreSecurityImageLabel,

1443 1444 1445
    .domainSetSecurityDaemonSocketLabel = virSecurityDACSetDaemonSocketLabel,
    .domainSetSecuritySocketLabel       = virSecurityDACSetSocketLabel,
    .domainClearSecuritySocketLabel     = virSecurityDACClearSocketLabel,
1446

1447 1448 1449
    .domainGenSecurityLabel             = virSecurityDACGenLabel,
    .domainReserveSecurityLabel         = virSecurityDACReserveLabel,
    .domainReleaseSecurityLabel         = virSecurityDACReleaseLabel,
1450

1451 1452
    .domainGetSecurityProcessLabel      = virSecurityDACGetProcessLabel,
    .domainSetSecurityProcessLabel      = virSecurityDACSetProcessLabel,
1453
    .domainSetSecurityChildProcessLabel = virSecurityDACSetChildProcessLabel,
1454

1455 1456
    .domainSetSecurityAllLabel          = virSecurityDACSetSecurityAllLabel,
    .domainRestoreSecurityAllLabel      = virSecurityDACRestoreSecurityAllLabel,
1457

1458 1459
    .domainSetSecurityHostdevLabel      = virSecurityDACSetSecurityHostdevLabel,
    .domainRestoreSecurityHostdevLabel  = virSecurityDACRestoreSecurityHostdevLabel,
1460

1461 1462
    .domainSetSavedStateLabel           = virSecurityDACSetSavedStateLabel,
    .domainRestoreSavedStateLabel       = virSecurityDACRestoreSavedStateLabel,
1463

1464
    .domainSetSecurityImageFDLabel      = virSecurityDACSetImageFDLabel,
1465
    .domainSetSecurityTapFDLabel        = virSecurityDACSetTapFDLabel,
1466

1467
    .domainGetSecurityMountOptions      = virSecurityDACGetMountOptions,
1468 1469

    .getBaseLabel                       = virSecurityDACGetBaseLabel,
1470 1471

    .domainSetDirLabel                  = virSecurityDACDomainSetDirLabel,
1472
};