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

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

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

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

#define VIR_FROM_THIS VIR_FROM_SECURITY
44 45 46

VIR_LOG_INIT("security.security_dac");

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

typedef struct _virSecurityDACData virSecurityDACData;
typedef virSecurityDACData *virSecurityDACDataPtr;

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

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

struct _virSecurityDACCallbackData {
    virSecurityManagerPtr manager;
    virSecurityLabelDefPtr secdef;
};

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

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

    return 0;
86 87
}

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

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

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

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

    return 0;
}

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

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

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

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

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

    return 0;
146 147
}

148 149

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

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

    return 0;
}

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

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

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

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

    return 0;
185 186 187
}


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

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

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


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

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

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
static int
virSecurityDACPreFork(virSecurityManagerPtr mgr)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    int ngroups;

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

237
static int
238 239 240 241 242
virSecurityDACSetOwnershipInternal(virSecurityDACDataPtr priv,
                                   virStorageSourcePtr src,
                                   const char *path,
                                   uid_t uid,
                                   gid_t gid)
243
{
244 245
    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
virSecurityDACSetOwnership(virSecurityDACDataPtr priv,
310
                           virStorageSourcePtr src,
311 312 313
                           const char *path,
                           uid_t uid,
                           gid_t gid)
314
{
M
Michal Privoznik 已提交
315
    /* XXX record previous ownership */
316
    return virSecurityDACSetOwnershipInternal(priv, src, path, uid, gid);
317 318 319 320 321 322 323
}


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
    return virSecurityDACSetOwnershipInternal(priv, src, path, 0, 0);
}


static int
334 335
virSecurityDACRestoreSecurityFileLabel(virSecurityDACDataPtr priv,
                                       const char *path)
336
{
337
    return virSecurityDACRestoreSecurityFileLabelInternal(priv, NULL, path);
338 339 340 341
}


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

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

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

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

372
    return virSecurityDACSetOwnership(priv, src, NULL, user, group);
373 374 375 376
}


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

{
382
    virStorageSourcePtr next;
383

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

389
    return 0;
390 391 392 393 394
}


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

    if (!priv->dynamicOwnership)
        return 0;

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

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

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

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

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

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

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

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


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


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


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

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

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


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


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

501

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


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

    if (!priv->dynamicOwnership)
        return 0;

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

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

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

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

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

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

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

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

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

        if (!pci)
            goto done;

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

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

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

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

        if (!scsi)
            goto done;

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

        break;
    }

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

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


static int
617
virSecurityDACRestoreSecurityPCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
618
                                      const char *file,
619
                                      void *opaque)
620
{
621 622 623
    virSecurityManagerPtr mgr = opaque;
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    return virSecurityDACRestoreSecurityFileLabel(priv, file);
624 625 626 627
}


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


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


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

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

663 664
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

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

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

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

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

        if (dev->missing)
            return 0;
684

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

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

        break;
    }

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

        if (!pci)
            goto done;

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

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

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

        if (!scsi)
            goto done;

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

        break;
    }

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

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


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

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

760 761
    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

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

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

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

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

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

812 813 814 815 816 817 818 819 820 821
    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:
822 823 824 825
        ret = 0;
        break;
    }

826
 done:
827 828 829 830 831 832
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}

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

843 844 845 846
    if (dev)
        chr_seclabel = virDomainChrDefGetSecurityLabelDef(dev,
                                                          SECURITY_DAC_NAME);

847
    if (chr_seclabel && !chr_seclabel->relabel)
848 849
        return 0;

850
    switch ((virDomainChrType) dev_source->type) {
851 852
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
853
        ret = virSecurityDACRestoreSecurityFileLabel(priv, dev_source->data.file.path);
854 855 856
        break;

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

871 872 873 874 875 876 877 878 879 880 881
    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:
882 883 884 885
        ret = 0;
        break;
    }

886
 done:
887 888 889 890 891 892 893
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}


static int
894
virSecurityDACRestoreChardevCallback(virDomainDefPtr def,
895 896 897 898 899
                                     virDomainChrDefPtr dev,
                                     void *opaque)
{
    virSecurityManagerPtr mgr = opaque;

900
    return virSecurityDACRestoreChardevLabel(mgr, def, dev, &dev->source);
901 902 903
}


904 905 906 907 908 909 910 911 912
static int
virSecurityDACSetSecurityTPMFileLabel(virSecurityManagerPtr mgr,
                                      virDomainDefPtr def,
                                      virDomainTPMDefPtr tpm)
{
    int ret = 0;

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

    return ret;
}


static int
O
Osier Yang 已提交
925
virSecurityDACRestoreSecurityTPMFileLabel(virSecurityManagerPtr mgr,
926
                                          virDomainDefPtr def,
O
Osier Yang 已提交
927
                                          virDomainTPMDefPtr tpm)
928 929 930 931 932
{
    int ret = 0;

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

    return ret;
}


944 945
static int
virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
946
                                      virDomainDefPtr def,
947
                                      bool migrated)
948 949
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
950
    virSecurityLabelDefPtr secdef;
951
    size_t i;
952 953
    int rc = 0;

954
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
955

956
    if (!priv->dynamicOwnership || (secdef && !secdef->relabel))
957
        return 0;
958 959

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

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

977
    if (virDomainChrDefForeach(def,
978 979
                               false,
                               virSecurityDACRestoreChardevCallback,
980
                               mgr) < 0)
981 982
        rc = -1;

983 984
    if (def->tpm) {
        if (virSecurityDACRestoreSecurityTPMFileLabel(mgr,
985
                                                      def,
986 987 988 989
                                                      def->tpm) < 0)
            rc = -1;
    }

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

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

998
    if (def->os.initrd &&
999
        virSecurityDACRestoreSecurityFileLabel(priv, def->os.initrd) < 0)
1000 1001
        rc = -1;

O
Olivia Yin 已提交
1002
    if (def->os.dtb &&
1003
        virSecurityDACRestoreSecurityFileLabel(priv, def->os.dtb) < 0)
O
Olivia Yin 已提交
1004 1005
        rc = -1;

1006 1007 1008 1009 1010
    return rc;
}


static int
1011
virSecurityDACSetChardevCallback(virDomainDefPtr def,
1012 1013 1014 1015 1016
                                 virDomainChrDefPtr dev,
                                 void *opaque)
{
    virSecurityManagerPtr mgr = opaque;

1017
    return virSecurityDACSetChardevLabel(mgr, def, dev, &dev->source);
1018 1019 1020 1021 1022
}


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

1032 1033
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

1034
    if (!priv->dynamicOwnership || (secdef && !secdef->relabel))
1035 1036
        return 0;

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

1054
    if (virDomainChrDefForeach(def,
1055 1056
                               true,
                               virSecurityDACSetChardevCallback,
1057
                               mgr) < 0)
1058 1059
        return -1;

1060 1061 1062 1063 1064 1065 1066
    if (def->tpm) {
        if (virSecurityDACSetSecurityTPMFileLabel(mgr,
                                                  def,
                                                  def->tpm) < 0)
            return -1;
    }

1067
    if (virSecurityDACGetImageIds(secdef, priv, &user, &group))
1068 1069
        return -1;

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

1075
    if (def->os.kernel &&
1076 1077
        virSecurityDACSetOwnership(priv, NULL,
                                   def->os.kernel, user, group) < 0)
1078 1079
        return -1;

1080
    if (def->os.initrd &&
1081 1082
        virSecurityDACSetOwnership(priv, NULL,
                                   def->os.initrd, user, group) < 0)
1083 1084
        return -1;

O
Olivia Yin 已提交
1085
    if (def->os.dtb &&
1086 1087
        virSecurityDACSetOwnership(priv, NULL,
                                   def->os.dtb, user, group) < 0)
O
Olivia Yin 已提交
1088 1089
        return -1;

1090 1091 1092 1093 1094 1095
    return 0;
}


static int
virSecurityDACSetSavedStateLabel(virSecurityManagerPtr mgr,
1096
                                 virDomainDefPtr def,
1097 1098
                                 const char *savefile)
{
1099 1100
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1101 1102
    uid_t user;
    gid_t group;
1103

1104 1105 1106
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

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

1109
    return virSecurityDACSetOwnership(priv, NULL, savefile, user, group);
1110 1111 1112 1113 1114
}


static int
virSecurityDACRestoreSavedStateLabel(virSecurityManagerPtr mgr,
1115
                                     virDomainDefPtr def ATTRIBUTE_UNUSED,
1116 1117 1118 1119 1120 1121 1122
                                     const char *savefile)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    if (!priv->dynamicOwnership)
        return 0;

1123
    return virSecurityDACRestoreSecurityFileLabel(priv, savefile);
1124 1125 1126 1127 1128
}


static int
virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr,
1129
                              virDomainDefPtr def)
1130
{
1131 1132
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1133 1134
    uid_t user;
    gid_t group;
1135 1136
    gid_t *groups;
    int ngroups;
1137

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

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

1143 1144
    VIR_DEBUG("Dropping privileges of DEF to %u:%u, %d supplemental groups",
              (unsigned int) user, (unsigned int) group, ngroups);
1145

1146
    if (virSetUIDGID(user, group, groups, ngroups) < 0)
1147 1148 1149
        return -1;

    return 0;
1150 1151 1152
}


1153 1154
static int
virSecurityDACSetChildProcessLabel(virSecurityManagerPtr mgr,
1155
                                   virDomainDefPtr def,
1156 1157
                                   virCommandPtr cmd)
{
1158 1159
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    virSecurityLabelDefPtr secdef;
1160 1161 1162
    uid_t user;
    gid_t group;

1163 1164 1165
    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

    if (virSecurityDACGetIds(secdef, priv, &user, &group, NULL, NULL))
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
        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;
}


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

static int
1185 1186
virSecurityDACGenLabel(virSecurityManagerPtr mgr,
                       virDomainDefPtr def)
1187
{
1188 1189 1190 1191 1192
    int rc = -1;
    virSecurityLabelDefPtr seclabel;
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);

    seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
1193
    if (seclabel == NULL)
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211
        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;
    }

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

1244
    if (seclabel->relabel && !seclabel->imagelabel &&
1245 1246 1247
        VIR_STRDUP(seclabel->imagelabel, seclabel->label) < 0) {
        VIR_FREE(seclabel->label);
        return rc;
1248 1249
    }

1250 1251 1252 1253 1254
    return 0;
}

static int
virSecurityDACReleaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1255
                           virDomainDefPtr def ATTRIBUTE_UNUSED)
1256 1257 1258 1259 1260 1261
{
    return 0;
}

static int
virSecurityDACReserveLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1262 1263
                           virDomainDefPtr def ATTRIBUTE_UNUSED,
                           pid_t pid ATTRIBUTE_UNUSED)
1264 1265 1266 1267
{
    return 0;
}

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 1317 1318 1319 1320 1321 1322 1323 1324
#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 已提交
1325 1326
virSecurityDACGetProcessLabelInternal(pid_t pid ATTRIBUTE_UNUSED,
                                      virSecurityLabelPtr seclabel ATTRIBUTE_UNUSED)
1327 1328 1329 1330 1331 1332 1333
{
    virReportSystemError(ENOSYS, "%s",
                         _("Cannot get process uid and gid on this platform"));
    return -1;
}
#endif

1334 1335
static int
virSecurityDACGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1336
                              virDomainDefPtr def,
1337
                              pid_t pid,
1338
                              virSecurityLabelPtr seclabel)
1339
{
1340 1341 1342
    virSecurityLabelDefPtr secdef =
        virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);

1343 1344 1345 1346 1347 1348 1349 1350
    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;
    }
1351 1352

    if (secdef->label)
1353 1354
        ignore_value(virStrcpy(seclabel->label, secdef->label,
                               VIR_SECURITY_LABEL_BUFLEN));
1355

1356 1357 1358 1359
    return 0;
}

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


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


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

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

1390 1391 1392 1393 1394 1395 1396 1397
static int
virSecurityDACSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                            virDomainDefPtr def ATTRIBUTE_UNUSED,
                            int fd ATTRIBUTE_UNUSED)
{
    return 0;
}

O
Osier Yang 已提交
1398 1399 1400 1401
static char *
virSecurityDACGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                              virDomainDefPtr vm ATTRIBUTE_UNUSED)
{
1402 1403 1404
    return NULL;
}

1405 1406 1407 1408 1409 1410 1411 1412
static const char *
virSecurityDACGetBaseLabel(virSecurityManagerPtr mgr,
                           int virt ATTRIBUTE_UNUSED)
{
    virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
    return priv->baselabel;
}

1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
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;

1428
    return virSecurityDACSetOwnership(priv, NULL, path, user, group);
1429 1430
}

1431
virSecurityDriver virSecurityDriverDAC = {
1432
    .privateDataLen                     = sizeof(virSecurityDACData),
1433
    .name                               = SECURITY_DAC_NAME,
1434 1435 1436
    .probe                              = virSecurityDACProbe,
    .open                               = virSecurityDACOpen,
    .close                              = virSecurityDACClose,
1437

1438 1439
    .getModel                           = virSecurityDACGetModel,
    .getDOI                             = virSecurityDACGetDOI,
1440

1441 1442
    .preFork                            = virSecurityDACPreFork,

1443
    .domainSecurityVerify               = virSecurityDACVerify,
1444

1445
    .domainSetSecurityDiskLabel         = virSecurityDACSetSecurityDiskLabel,
1446
    .domainRestoreSecurityDiskLabel     = virSecurityDACRestoreSecurityDiskLabel,
1447

1448
    .domainSetSecurityImageLabel        = virSecurityDACSetSecurityImageLabel,
1449 1450
    .domainRestoreSecurityImageLabel    = virSecurityDACRestoreSecurityImageLabel,

1451 1452 1453
    .domainSetSecurityDaemonSocketLabel = virSecurityDACSetDaemonSocketLabel,
    .domainSetSecuritySocketLabel       = virSecurityDACSetSocketLabel,
    .domainClearSecuritySocketLabel     = virSecurityDACClearSocketLabel,
1454

1455 1456 1457
    .domainGenSecurityLabel             = virSecurityDACGenLabel,
    .domainReserveSecurityLabel         = virSecurityDACReserveLabel,
    .domainReleaseSecurityLabel         = virSecurityDACReleaseLabel,
1458

1459 1460
    .domainGetSecurityProcessLabel      = virSecurityDACGetProcessLabel,
    .domainSetSecurityProcessLabel      = virSecurityDACSetProcessLabel,
1461
    .domainSetSecurityChildProcessLabel = virSecurityDACSetChildProcessLabel,
1462

1463 1464
    .domainSetSecurityAllLabel          = virSecurityDACSetSecurityAllLabel,
    .domainRestoreSecurityAllLabel      = virSecurityDACRestoreSecurityAllLabel,
1465

1466 1467
    .domainSetSecurityHostdevLabel      = virSecurityDACSetSecurityHostdevLabel,
    .domainRestoreSecurityHostdevLabel  = virSecurityDACRestoreSecurityHostdevLabel,
1468

1469 1470
    .domainSetSavedStateLabel           = virSecurityDACSetSavedStateLabel,
    .domainRestoreSavedStateLabel       = virSecurityDACRestoreSavedStateLabel,
1471

1472
    .domainSetSecurityImageFDLabel      = virSecurityDACSetImageFDLabel,
1473
    .domainSetSecurityTapFDLabel        = virSecurityDACSetTapFDLabel,
1474

1475
    .domainGetSecurityMountOptions      = virSecurityDACGetMountOptions,
1476 1477

    .getBaseLabel                       = virSecurityDACGetBaseLabel,
1478 1479

    .domainSetDirLabel                  = virSecurityDACDomainSetDirLabel,
1480
};