security_selinux.c 40.9 KB
Newer Older
1
/*
2
 * Copyright (C) 2008-2011 Red Hat, Inc.
3 4 5 6 7 8 9 10
 *
 * 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.
 *
 * Authors:
 *     James Morris <jmorris@namei.org>
11
 *     Dan Walsh <dwalsh@redhat.com>
12 13 14 15 16 17 18 19 20
 *
 * SELinux security driver.
 */
#include <config.h>
#include <selinux/selinux.h>
#include <selinux/context.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
E
Eric Blake 已提交
21 22 23
#if HAVE_SELINUX_LABEL_H
# include <selinux/label.h>
#endif
24

25
#include "security_driver.h"
26 27 28 29
#include "security_selinux.h"
#include "virterror_internal.h"
#include "util.h"
#include "memory.h"
30
#include "logging.h"
31 32
#include "pci.h"
#include "hostusb.h"
33
#include "storage_file.h"
E
Eric Blake 已提交
34
#include "virfile.h"
35
#include "virrandom.h"
D
Daniel P. Berrange 已提交
36 37 38

#define VIR_FROM_THIS VIR_FROM_SECURITY

39
static char default_domain_context[1024];
40
static char default_content_context[1024];
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
static char default_image_context[1024];
#define SECURITY_SELINUX_VOID_DOI       "0"
#define SECURITY_SELINUX_NAME "selinux"

/* TODO
   The data struct of used mcs should be replaced with a better data structure in the future
*/

struct MCS {
    char *mcs;
    struct MCS *next;
};
static struct MCS *mcsList = NULL;

static int
mcsAdd(const char *mcs)
{
    struct MCS *ptr;

    for (ptr = mcsList; ptr; ptr = ptr->next) {
D
Daniel P. Berrange 已提交
61
        if (STREQ(ptr->mcs, mcs))
62 63
            return -1;
    }
D
Daniel P. Berrange 已提交
64 65
    if (VIR_ALLOC(ptr) < 0)
        return -1;
66 67 68 69 70 71 72 73 74 75 76 77 78
    ptr->mcs = strdup(mcs);
    ptr->next = mcsList;
    mcsList = ptr;
    return 0;
}

static int
mcsRemove(const char *mcs)
{
    struct MCS *prevptr = NULL;
    struct MCS *ptr = NULL;

    for (ptr = mcsList; ptr; ptr = ptr->next) {
D
Daniel P. Berrange 已提交
79
        if (STREQ(ptr->mcs, mcs)) {
80 81 82 83 84
            if (prevptr)
                prevptr->next = ptr->next;
            else {
                mcsList = ptr->next;
            }
85 86
            VIR_FREE(ptr->mcs);
            VIR_FREE(ptr);
87 88 89 90 91 92 93 94 95 96 97 98
            return 0;
        }
        prevptr = ptr;
    }
    return -1;
}

static char *
SELinuxGenNewContext(const char *oldcontext, const char *mcs)
{
    char *newcontext = NULL;
    char *scontext = strdup(oldcontext);
99
    context_t con;
100
    if (!scontext) goto err;
101
    con = context_new(scontext);
102 103 104 105 106 107 108 109 110 111
    if (!con) goto err;
    context_range_set(con, mcs);
    newcontext = strdup(context_str(con));
    context_free(con);
err:
    freecon(scontext);
    return (newcontext);
}

static int
112
SELinuxInitialize(void)
113 114 115 116 117 118
{
    char *ptr = NULL;
    int fd = 0;

    fd = open(selinux_virtual_domain_context_path(), O_RDONLY);
    if (fd < 0) {
119
        virReportSystemError(errno,
120 121
                             _("cannot open SELinux virtual domain context file '%s'"),
                             selinux_virtual_domain_context_path());
122 123 124 125
        return -1;
    }

    if (saferead(fd, default_domain_context, sizeof(default_domain_context)) < 0) {
126
        virReportSystemError(errno,
127 128
                             _("cannot read SELinux virtual domain context file %s"),
                             selinux_virtual_domain_context_path());
129
        VIR_FORCE_CLOSE(fd);
130 131
        return -1;
    }
132
    VIR_FORCE_CLOSE(fd);
133 134 135 136 137

    ptr = strchrnul(default_domain_context, '\n');
    *ptr = '\0';

    if ((fd = open(selinux_virtual_image_context_path(), O_RDONLY)) < 0) {
138
        virReportSystemError(errno,
139 140
                             _("cannot open SELinux virtual image context file %s"),
                             selinux_virtual_image_context_path());
141 142 143 144
        return -1;
    }

    if (saferead(fd, default_image_context, sizeof(default_image_context)) < 0) {
145
        virReportSystemError(errno,
146 147
                             _("cannot read SELinux virtual image context file %s"),
                             selinux_virtual_image_context_path());
148
        VIR_FORCE_CLOSE(fd);
149 150
        return -1;
    }
151
    VIR_FORCE_CLOSE(fd);
152 153

    ptr = strchrnul(default_image_context, '\n');
154 155 156 157 158 159 160
    if (*ptr == '\n') {
        *ptr = '\0';
        strcpy(default_content_context, ptr+1);
        ptr = strchrnul(default_content_context, '\n');
        if (*ptr == '\n')
            *ptr = '\0';
    }
161 162 163 164
    return 0;
}

static int
165
SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
166
                        virDomainDefPtr def)
167 168
{
    int rc = -1;
169
    char *mcs = NULL;
170 171 172
    char *scontext = NULL;
    int c1 = 0;
    int c2 = 0;
173
    context_t ctx = NULL;
174
    const char *range;
175

176 177 178
    if ((def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) &&
        !def->seclabel.baselabel &&
        def->seclabel.model) {
179 180 181 182 183
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("security model already defined for VM"));
        return rc;
    }

184 185
    if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
        def->seclabel.label) {
186
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
187
                               "%s", _("security label already defined for VM"));
188
        return rc;
D
Daniel P. Berrange 已提交
189
    }
190

191
    if (def->seclabel.imagelabel) {
192 193 194 195 196
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("security image label already defined for VM"));
        return rc;
    }

197 198
    if (def->seclabel.model &&
        STRNEQ(def->seclabel.model, SECURITY_SELINUX_NAME)) {
199 200
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               _("security label model %s is not supported with selinux"),
201
                               def->seclabel.model);
202 203 204
        return rc;
    }

205 206
    switch (def->seclabel.type) {
    case VIR_DOMAIN_SECLABEL_STATIC:
207
        if (!(ctx = context_new(def->seclabel.label)) ) {
208 209
            virReportSystemError(errno,
                                 _("unable to allocate socket security context '%s'"),
210
                                 def->seclabel.label);
211
            return rc;
212 213
        }

214
        range = context_range_get(ctx);
215 216 217 218 219
        if (!range ||
            !(mcs = strdup(range))) {
            virReportOOMError();
            goto cleanup;
        }
220 221 222
        break;

    case VIR_DOMAIN_SECLABEL_DYNAMIC:
223
        do {
224 225
            c1 = virRandomBits(10);
            c2 = virRandomBits(10);
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244

            if ( c1 == c2 ) {
                if (virAsprintf(&mcs, "s0:c%d", c1) < 0) {
                    virReportOOMError();
                    goto cleanup;
                }
            } else {
                if (c1 > c2) {
                    c1 ^= c2;
                    c2 ^= c1;
                    c1 ^= c2;
                }
                if (virAsprintf(&mcs, "s0:c%d,c%d", c1, c2) < 0) {
                    virReportOOMError();
                    goto cleanup;
                }
            }
        } while (mcsAdd(mcs) == -1);

245 246 247
        def->seclabel.label =
            SELinuxGenNewContext(def->seclabel.baselabel ?
                                 def->seclabel.baselabel :
248
                                 default_domain_context, mcs);
249
        if (! def->seclabel.label)  {
250 251 252 253
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("cannot generate selinux context for %s"), mcs);
            goto cleanup;
        }
254 255 256 257 258 259 260
        break;

    case VIR_DOMAIN_SECLABEL_NONE:
        /* no op */
        break;

    default:
261
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
262 263
                               _("unexpected security label type '%s'"),
                               virDomainSeclabelTypeToString(def->seclabel.type));
264
        goto cleanup;
D
Daniel P. Berrange 已提交
265
    }
266

267 268 269 270 271 272 273 274 275
    if (!def->seclabel.norelabel) {
        def->seclabel.imagelabel = SELinuxGenNewContext(default_image_context, mcs);
        if (!def->seclabel.imagelabel)  {
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("cannot generate selinux context for %s"), mcs);
            goto cleanup;
        }
    }

276 277
    if (!def->seclabel.model &&
        !(def->seclabel.model = strdup(SECURITY_SELINUX_NAME))) {
278
        virReportOOMError();
279
        goto cleanup;
D
Daniel P. Berrange 已提交
280 281
    }

282
    rc = 0;
283 284 285

cleanup:
    if (rc != 0) {
286 287 288 289 290 291
        if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)
            VIR_FREE(def->seclabel.label);
        VIR_FREE(def->seclabel.imagelabel);
        if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
            !def->seclabel.baselabel)
            VIR_FREE(def->seclabel.model);
292 293 294 295
    }

    if (ctx)
        context_free(ctx);
D
Daniel P. Berrange 已提交
296
    VIR_FREE(scontext);
297 298 299
    VIR_FREE(mcs);

    VIR_DEBUG("model=%s label=%s imagelabel=%s baselabel=%s",
300 301 302 303
              NULLSTR(def->seclabel.model),
              NULLSTR(def->seclabel.label),
              NULLSTR(def->seclabel.imagelabel),
              NULLSTR(def->seclabel.baselabel));
304

305 306 307
    return rc;
}

308
static int
309
SELinuxReserveSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
310 311
                            virDomainDefPtr def,
                            pid_t pid)
312 313 314 315 316
{
    security_context_t pctx;
    context_t ctx = NULL;
    const char *mcs;

317
    if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
318 319
        return 0;

320
    if (getpidcon(pid, &pctx) == -1) {
321
        virReportSystemError(errno,
322
                             _("unable to get PID %d security context"), pid);
323 324 325 326
        return -1;
    }

    ctx = context_new(pctx);
327
    freecon(pctx);
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
    if (!ctx)
        goto err;

    mcs = context_range_get(ctx);
    if (!mcs)
        goto err;

    mcsAdd(mcs);

    context_free(ctx);

    return 0;

err:
    context_free(ctx);
    return -1;
}



348 349 350 351 352 353 354
static int
SELinuxSecurityDriverProbe(void)
{
    return is_selinux_enabled() ? SECURITY_DRIVER_ENABLE : SECURITY_DRIVER_DISABLE;
}

static int
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
SELinuxSecurityDriverOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
{
    return SELinuxInitialize();
}

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


static const char *SELinuxSecurityGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
{
    return SECURITY_SELINUX_NAME;
}

static const char *SELinuxSecurityGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
373 374 375 376 377
{
    /*
     * Where will the DOI come from?  SELinux configuration, or qemu
     * configuration? For the moment, we'll just set it to "0".
     */
378
    return SECURITY_SELINUX_VOID_DOI;
379 380 381
}

static int
382
SELinuxGetSecurityProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
383 384
                               virDomainDefPtr def ATTRIBUTE_UNUSED,
                               pid_t pid,
385
                               virSecurityLabelPtr sec)
386 387 388
{
    security_context_t ctx;

389
    if (getpidcon(pid, &ctx) == -1) {
390
        virReportSystemError(errno,
391
                             _("unable to get PID %d security context"),
392
                             pid);
393 394 395 396
        return -1;
    }

    if (strlen((char *) ctx) >= VIR_SECURITY_LABEL_BUFLEN) {
397
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
398
                               _("security label exceeds "
C
Cole Robinson 已提交
399
                                 "maximum length: %d"),
400
                               VIR_SECURITY_LABEL_BUFLEN - 1);
401
        freecon(ctx);
402 403 404 405
        return -1;
    }

    strcpy(sec->label, (char *) ctx);
406
    freecon(ctx);
407 408 409

    sec->enforcing = security_getenforce();
    if (sec->enforcing == -1) {
410
        virReportSystemError(errno, "%s",
411
                             _("error calling security_getenforce()"));
412 413 414 415 416 417
        return -1;
    }

    return 0;
}

418 419 420
/* Attempt to change the label of PATH to TCON.  If OPTIONAL is true,
 * return 1 if labelling was not possible.  Otherwise, require a label
 * change, and return 0 for success, -1 for failure.  */
421
static int
422
SELinuxSetFileconHelper(const char *path, char *tcon, bool optional)
423
{
424
    security_context_t econ;
425

426 427
    VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon);

428
    if (setfilecon(path, tcon) < 0) {
429 430
        int setfilecon_errno = errno;

431 432 433 434
        if (getfilecon(path, &econ) >= 0) {
            if (STREQ(tcon, econ)) {
                freecon(econ);
                /* It's alright, there's nothing to change anyway. */
435
                return optional ? 1 : 0;
436 437 438
            }
            freecon(econ);
        }
439 440

        /* if the error complaint is related to an image hosted on
441 442
         * an nfs mount, or a usbfs/sysfs filesystem not supporting
         * labelling, then just ignore it & hope for the best.
443
         * The user hopefully set one of the necessary SELinux
444
         * virt_use_{nfs,usb,pci}  boolean tunables to allow it...
445
         */
446
        if (setfilecon_errno != EOPNOTSUPP && setfilecon_errno != ENOTSUP) {
447
            virReportSystemError(setfilecon_errno,
448
                                 _("unable to set security context '%s' on '%s'"),
449
                                 tcon, path);
450 451
            if (security_getenforce() == 1)
                return -1;
452
        } else {
453 454 455 456 457 458 459 460 461 462 463 464 465 466
            const char *msg;
            if ((virStorageFileIsSharedFSType(path,
                                              VIR_STORAGE_FILE_SHFS_NFS) == 1) &&
                security_get_boolean_active("virt_use_nfs") != 1) {
                msg = _("Setting security context '%s' on '%s' not supported. "
                        "Consider setting virt_use_nfs");
               if (security_getenforce() == 1)
                   VIR_WARN(msg, tcon, path);
               else
                   VIR_INFO(msg, tcon, path);
            } else {
                VIR_INFO("Setting security context '%s' on '%s' not supported",
                         tcon, path);
            }
467 468
            if (optional)
                return 1;
469
        }
470 471 472 473
    }
    return 0;
}

474 475 476 477 478 479 480 481 482 483 484 485
static int
SELinuxSetFileconOptional(const char *path, char *tcon)
{
    return SELinuxSetFileconHelper(path, tcon, true);
}

static int
SELinuxSetFilecon(const char *path, char *tcon)
{
    return SELinuxSetFileconHelper(path, tcon, false);
}

486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
static int
SELinuxFSetFilecon(int fd, char *tcon)
{
    security_context_t econ;

    VIR_INFO("Setting SELinux context on fd %d to '%s'", fd, tcon);

    if (fsetfilecon(fd, tcon) < 0) {
        int fsetfilecon_errno = errno;

        if (fgetfilecon(fd, &econ) >= 0) {
            if (STREQ(tcon, econ)) {
                freecon(econ);
                /* It's alright, there's nothing to change anyway. */
                return 0;
            }
            freecon(econ);
        }

        /* if the error complaint is related to an image hosted on
         * an nfs mount, or a usbfs/sysfs filesystem not supporting
         * labelling, then just ignore it & hope for the best.
         * The user hopefully set one of the necessary SELinux
         * virt_use_{nfs,usb,pci}  boolean tunables to allow it...
         */
        if (fsetfilecon_errno != EOPNOTSUPP) {
            virReportSystemError(fsetfilecon_errno,
                                 _("unable to set security context '%s' on fd %d"),
                                 tcon, fd);
            if (security_getenforce() == 1)
                return -1;
        } else {
            VIR_INFO("Setting security context '%s' on fd %d not supported",
                     tcon, fd);
        }
    }
    return 0;
}

E
Eric Blake 已提交
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
/* Set fcon to the appropriate label for path and mode, or return -1.  */
static int
getContext(const char *newpath, mode_t mode, security_context_t *fcon)
{
#if HAVE_SELINUX_LABEL_H
    struct selabel_handle *handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
    int ret;

    if (handle == NULL)
        return -1;

    ret = selabel_lookup(handle, fcon, newpath, mode);
    selabel_close(handle);
    return ret;
#else
    return matchpathcon(newpath, mode, fcon);
#endif
}

544 545 546

/* This method shouldn't raise errors, since they'll overwrite
 * errors that the caller(s) are already dealing with */
547
static int
548
SELinuxRestoreSecurityFileLabel(const char *path)
549
{
550 551 552 553
    struct stat buf;
    security_context_t fcon = NULL;
    int rc = -1;
    char *newpath = NULL;
554
    char ebuf[1024];
555

556 557
    VIR_INFO("Restoring SELinux context on '%s'", path);

558
    if (virFileResolveLink(path, &newpath) < 0) {
559 560
        VIR_WARN("cannot resolve symlink %s: %s", path,
                 virStrerror(errno, ebuf, sizeof(ebuf)));
D
Daniel P. Berrange 已提交
561
        goto err;
562
    }
563

564
    if (stat(newpath, &buf) != 0) {
565 566
        VIR_WARN("cannot stat %s: %s", newpath,
                 virStrerror(errno, ebuf, sizeof(ebuf)));
D
Daniel P. Berrange 已提交
567
        goto err;
568
    }
D
Daniel P. Berrange 已提交
569

E
Eric Blake 已提交
570
    if (getContext(newpath, buf.st_mode, &fcon) < 0) {
571
        VIR_WARN("cannot lookup default selinux label for %s", newpath);
572
    } else {
573
        rc = SELinuxSetFilecon(newpath, fcon);
574
    }
575

576
err:
577
    freecon(fcon);
578 579
    VIR_FREE(newpath);
    return rc;
580 581
}

582
static int
583
SELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
584
                                    virDomainDefPtr def,
585 586
                                    virDomainDiskDefPtr disk,
                                    int migrated)
587
{
588
    const virSecurityLabelDefPtr secdef = &def->seclabel;
589

590
    if (secdef->norelabel || (disk->seclabel && disk->seclabel->norelabel))
591 592
        return 0;

593 594 595 596 597 598 599 600 601 602 603
    /* 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 (disk->readonly || disk->shared)
        return 0;

604
    if (!disk->src || disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK)
605 606
        return 0;

607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
    /* If we have a shared FS & doing migrated, 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 :-)
     */
    if (migrated) {
        int rc = virStorageFileIsSharedFS(disk->src);
        if (rc < 0)
            return -1;
        if (rc == 1) {
            VIR_DEBUG("Skipping image label restore on %s because FS is shared",
                      disk->src);
            return 0;
        }
    }

623
    return SELinuxRestoreSecurityFileLabel(disk->src);
624 625
}

626 627

static int
628
SELinuxRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
629
                                 virDomainDefPtr def,
630 631
                                 virDomainDiskDefPtr disk)
{
632
    return SELinuxRestoreSecurityImageLabelInt(mgr, def, disk, 0);
633 634 635
}


636 637 638 639 640 641 642
static int
SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
                            const char *path,
                            size_t depth,
                            void *opaque)
{
    const virSecurityLabelDefPtr secdef = opaque;
643
    int ret;
644

645 646 647 648 649 650 651
    if (disk->seclabel && disk->seclabel->norelabel)
        return 0;

    if (disk->seclabel && !disk->seclabel->norelabel &&
        disk->seclabel->label) {
        ret = SELinuxSetFilecon(path, disk->seclabel->label);
    } else if (depth == 0) {
652
        if (disk->shared) {
653
            ret = SELinuxSetFileconOptional(path, default_image_context);
654
        } else if (disk->readonly) {
655
            ret = SELinuxSetFileconOptional(path, default_content_context);
656
        } else if (secdef->imagelabel) {
657
            ret = SELinuxSetFileconOptional(path, secdef->imagelabel);
658
        } else {
659
            ret = 0;
660 661
        }
    } else {
662 663 664 665 666 667 668 669 670 671 672
        ret = SELinuxSetFileconOptional(path, default_content_context);
    }
    if (ret == 1 && !disk->seclabel) {
        /* If we failed to set a label, but virt_use_nfs let us
         * proceed anyway, then we don't need to relabel later.  */
        if (VIR_ALLOC(disk->seclabel) < 0) {
            virReportOOMError();
            return -1;
        }
        disk->seclabel->norelabel = true;
        ret = 0;
673
    }
674
    return ret;
675 676
}

677
static int
678
SELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr,
679
                             virDomainDefPtr def,
680
                             virDomainDiskDefPtr disk)
681 682

{
683
    const virSecurityLabelDefPtr secdef = &def->seclabel;
684
    bool allowDiskFormatProbing = virSecurityManagerGetAllowDiskFormatProbing(mgr);
685

686
    if (secdef->norelabel)
687 688
        return 0;

689 690 691
    if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK)
        return 0;

692
    return virDomainDiskDefForeachPath(disk,
693
                                       allowDiskFormatProbing,
694
                                       true,
695 696
                                       SELinuxSetSecurityFileLabel,
                                       secdef);
697 698
}

699 700

static int
701
SELinuxSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
702 703
                           const char *file, void *opaque)
{
704 705
    virDomainDefPtr def = opaque;
    const virSecurityLabelDefPtr secdef = &def->seclabel;
706

707
    return SELinuxSetFilecon(file, secdef->imagelabel);
708 709 710
}

static int
711
SELinuxSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
712 713
                           const char *file, void *opaque)
{
714 715
    virDomainDefPtr def = opaque;
    const virSecurityLabelDefPtr secdef = &def->seclabel;
716

717
    return SELinuxSetFilecon(file, secdef->imagelabel);
718 719 720
}

static int
721
SELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
722
                               virDomainDefPtr def,
723 724 725
                               virDomainHostdevDefPtr dev)

{
726
    const virSecurityLabelDefPtr secdef = &def->seclabel;
727 728
    int ret = -1;

729
    if (secdef->norelabel)
730 731
        return 0;

732 733 734 735 736
    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
        return 0;

    switch (dev->source.subsys.type) {
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
737
        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
738
                                      dev->source.subsys.u.usb.device);
739

740 741
        if (!usb)
            goto done;
742

743
        ret = usbDeviceFileIterate(usb, SELinuxSetSecurityUSBLabel, def);
744
        usbFreeDevice(usb);
M
Mark McLoughlin 已提交
745
        break;
746 747 748
    }

    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
749
        pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
750 751 752 753 754 755 756
                                      dev->source.subsys.u.pci.bus,
                                      dev->source.subsys.u.pci.slot,
                                      dev->source.subsys.u.pci.function);

        if (!pci)
            goto done;

757
        ret = pciDeviceFileIterate(pci, SELinuxSetSecurityPCILabel, def);
758
        pciFreeDevice(pci);
759 760 761 762 763 764 765 766 767 768 769 770 771

        break;
    }

    default:
        ret = 0;
        break;
    }

done:
    return ret;
}

772

773
static int
774
SELinuxRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
775 776 777
                               const char *file,
                               void *opaque ATTRIBUTE_UNUSED)
{
778
    return SELinuxRestoreSecurityFileLabel(file);
779 780 781
}

static int
782
SELinuxRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
783 784 785
                               const char *file,
                               void *opaque ATTRIBUTE_UNUSED)
{
786
    return SELinuxRestoreSecurityFileLabel(file);
787 788 789
}

static int
790
SELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
791
                                   virDomainDefPtr def,
792 793 794
                                   virDomainHostdevDefPtr dev)

{
795
    const virSecurityLabelDefPtr secdef = &def->seclabel;
796 797
    int ret = -1;

798
    if (secdef->norelabel)
799 800
        return 0;

801 802 803 804 805
    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
        return 0;

    switch (dev->source.subsys.type) {
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
806
        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
807
                                      dev->source.subsys.u.usb.device);
808 809 810 811

        if (!usb)
            goto done;

812
        ret = usbDeviceFileIterate(usb, SELinuxRestoreSecurityUSBLabel, NULL);
813
        usbFreeDevice(usb);
814 815 816 817 818

        break;
    }

    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
819
        pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
820 821 822 823 824 825 826
                                      dev->source.subsys.u.pci.bus,
                                      dev->source.subsys.u.pci.slot,
                                      dev->source.subsys.u.pci.function);

        if (!pci)
            goto done;

827
        ret = pciDeviceFileIterate(pci, SELinuxRestoreSecurityPCILabel, NULL);
828
        pciFreeDevice(pci);
829 830 831 832 833 834 835 836 837 838 839 840 841

        break;
    }

    default:
        ret = 0;
        break;
    }

done:
    return ret;
}

842 843

static int
844
SELinuxSetSecurityChardevLabel(virDomainDefPtr def,
845
                               virDomainChrSourceDefPtr dev)
846 847

{
848
    const virSecurityLabelDefPtr secdef = &def->seclabel;
849 850 851
    char *in = NULL, *out = NULL;
    int ret = -1;

852
    if (secdef->norelabel)
853 854 855 856 857 858 859 860 861
        return 0;

    switch (dev->type) {
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
        ret = SELinuxSetFilecon(dev->data.file.path, secdef->imagelabel);
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
862 863 864 865 866 867
        if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) ||
            (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) {
            virReportOOMError();
            goto done;
        }
        if (virFileExists(in) && virFileExists(out)) {
868
            if ((SELinuxSetFilecon(in, secdef->imagelabel) < 0) ||
869
                (SELinuxSetFilecon(out, secdef->imagelabel) < 0)) {
870
                goto done;
871 872 873
            }
        } else if (SELinuxSetFilecon(dev->data.file.path, secdef->imagelabel) < 0) {
            goto done;
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889
        }
        ret = 0;
        break;

    default:
        ret = 0;
        break;
    }

done:
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}

static int
890
SELinuxRestoreSecurityChardevLabel(virDomainDefPtr def,
891
                                   virDomainChrSourceDefPtr dev)
892 893

{
894
    const virSecurityLabelDefPtr secdef = &def->seclabel;
895 896 897
    char *in = NULL, *out = NULL;
    int ret = -1;

898
    if (secdef->norelabel)
899 900 901 902 903
        return 0;

    switch (dev->type) {
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
904 905 906
        if (SELinuxRestoreSecurityFileLabel(dev->data.file.path) < 0)
            goto done;
        ret = 0;
907 908 909 910 911 912 913
        break;
    case VIR_DOMAIN_CHR_TYPE_PIPE:
        if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) ||
            (virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) {
            virReportOOMError();
            goto done;
        }
914 915 916 917 918 919
        if (virFileExists(in) && virFileExists(out)) {
            if ((SELinuxRestoreSecurityFileLabel(out) < 0) ||
                (SELinuxRestoreSecurityFileLabel(in) < 0)) {
                goto done;
            }
        } else if (SELinuxRestoreSecurityFileLabel(dev->data.file.path) < 0) {
920
            goto done;
921
        }
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
        ret = 0;
        break;

    default:
        ret = 0;
        break;
    }

done:
    VIR_FREE(in);
    VIR_FREE(out);
    return ret;
}


static int
938
SELinuxRestoreSecurityChardevCallback(virDomainDefPtr def,
939
                                      virDomainChrDefPtr dev,
940
                                      void *opaque ATTRIBUTE_UNUSED)
941
{
942 943 944 945 946
    /* This is taken care of by processing of def->serials */
    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
        dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
        return 0;

947
    return SELinuxRestoreSecurityChardevLabel(def, &dev->source);
948 949 950
}


E
Eric Blake 已提交
951
static int
952
SELinuxRestoreSecuritySmartcardCallback(virDomainDefPtr def,
E
Eric Blake 已提交
953
                                        virDomainSmartcardDefPtr dev,
954
                                        void *opaque ATTRIBUTE_UNUSED)
E
Eric Blake 已提交
955 956 957 958 959 960 961 962 963 964 965 966 967 968
{
    const char *database;

    switch (dev->type) {
    case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
        break;

    case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
        database = dev->data.cert.database;
        if (!database)
            database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
        return SELinuxRestoreSecurityFileLabel(database);

    case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
969
        return SELinuxRestoreSecurityChardevLabel(def, &dev->data.passthru);
E
Eric Blake 已提交
970 971 972 973 974 975 976 977 978 979 980 981

    default:
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unknown smartcard type %d"),
                               dev->type);
        return -1;
    }

    return 0;
}


982
static int
983
SELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
984
                               virDomainDefPtr def,
985
                               int migrated ATTRIBUTE_UNUSED)
986
{
987
    const virSecurityLabelDefPtr secdef = &def->seclabel;
988 989
    int i;
    int rc = 0;
990

991
    VIR_DEBUG("Restoring security label on %s", def->name);
992

993
    if (secdef->norelabel)
994 995
        return 0;

996
    for (i = 0 ; i < def->nhostdevs ; i++) {
997
        if (SELinuxRestoreSecurityHostdevLabel(mgr,
998 999
                                               def,
                                               def->hostdevs[i]) < 0)
1000
            rc = -1;
1001
    }
1002
    for (i = 0 ; i < def->ndisks ; i++) {
1003
        if (SELinuxRestoreSecurityImageLabelInt(mgr,
1004 1005
                                                def,
                                                def->disks[i],
1006
                                                migrated) < 0)
1007 1008
            rc = -1;
    }
1009

1010
    if (virDomainChrDefForeach(def,
1011 1012
                               false,
                               SELinuxRestoreSecurityChardevCallback,
1013
                               NULL) < 0)
1014 1015
        rc = -1;

1016
    if (virDomainSmartcardDefForeach(def,
E
Eric Blake 已提交
1017 1018
                                     false,
                                     SELinuxRestoreSecuritySmartcardCallback,
1019
                                     NULL) < 0)
E
Eric Blake 已提交
1020 1021
        rc = -1;

1022 1023
    if (def->os.kernel &&
        SELinuxRestoreSecurityFileLabel(def->os.kernel) < 0)
1024 1025
        rc = -1;

1026 1027
    if (def->os.initrd &&
        SELinuxRestoreSecurityFileLabel(def->os.initrd) < 0)
1028 1029
        rc = -1;

1030 1031 1032 1033
    return rc;
}

static int
1034
SELinuxReleaseSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1035
                            virDomainDefPtr def)
1036
{
1037
    const virSecurityLabelDefPtr secdef = &def->seclabel;
1038

1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
    if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
        if (secdef->label != NULL) {
            context_t con = context_new(secdef->label);
            if (con) {
                mcsRemove(context_range_get(con));
                context_free(con);
            }
        }
        VIR_FREE(secdef->label);
        if (!secdef->baselabel)
            VIR_FREE(secdef->model);
1050 1051 1052
    }
    VIR_FREE(secdef->imagelabel);

1053
    return 0;
1054 1055
}

1056 1057

static int
1058
SELinuxSetSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1059
                          virDomainDefPtr def,
1060 1061
                          const char *savefile)
{
1062
    const virSecurityLabelDefPtr secdef = &def->seclabel;
1063

1064
    if (secdef->norelabel)
1065 1066
        return 0;

1067
    return SELinuxSetFilecon(savefile, secdef->imagelabel);
1068 1069 1070 1071
}


static int
1072
SELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1073
                              virDomainDefPtr def,
1074 1075
                              const char *savefile)
{
1076
    const virSecurityLabelDefPtr secdef = &def->seclabel;
1077

1078
    if (secdef->norelabel)
1079 1080
        return 0;

1081
    return SELinuxRestoreSecurityFileLabel(savefile);
1082 1083 1084
}


1085
static int
1086 1087
SELinuxSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                      virDomainDefPtr def)
1088 1089
{
    const virSecurityLabelDefPtr secdef = &def->seclabel;
1090 1091 1092 1093 1094 1095 1096 1097 1098
    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               _("security label driver mismatch: "
                                 "'%s' model configured for domain, but "
                                 "hypervisor driver is '%s'."),
                               secdef->model, virSecurityManagerGetModel(mgr));
        return -1;
    }

1099 1100
    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) {
        if (security_check_context(secdef->label) != 0) {
1101
            virSecurityReportError(VIR_ERR_XML_ERROR,
1102 1103 1104 1105 1106 1107 1108
                                   _("Invalid security label %s"), secdef->label);
            return -1;
        }
    }
    return 0;
}

1109
static int
1110
SELinuxSetSecurityProcessLabel(virSecurityManagerPtr mgr,
1111
                               virDomainDefPtr def)
1112 1113
{
    /* TODO: verify DOI */
1114
    const virSecurityLabelDefPtr secdef = &def->seclabel;
1115

1116
    if (def->seclabel.label == NULL)
1117 1118
        return 0;

1119
    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
1120
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
1121 1122 1123
                               _("security label driver mismatch: "
                                 "'%s' model configured for domain, but "
                                 "hypervisor driver is '%s'."),
1124
                               secdef->model, virSecurityManagerGetModel(mgr));
1125
        if (security_getenforce() == 1)
1126
            return -1;
1127 1128 1129
    }

    if (setexeccon(secdef->label) == -1) {
1130
        virReportSystemError(errno,
1131 1132
                             _("unable to set security context '%s'"),
                             secdef->label);
1133
        if (security_getenforce() == 1)
1134
            return -1;
1135 1136
    }

1137 1138 1139
    return 0;
}

1140
static int
1141
SELinuxSetSecurityDaemonSocketLabel(virSecurityManagerPtr mgr,
1142
                                    virDomainDefPtr def)
1143 1144
{
    /* TODO: verify DOI */
1145
    const virSecurityLabelDefPtr secdef = &def->seclabel;
1146 1147 1148 1149 1150
    context_t execcon = NULL;
    context_t proccon = NULL;
    security_context_t scon = NULL;
    int rc = -1;

1151
    if (def->seclabel.label == NULL)
1152 1153
        return 0;

1154
    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
1155 1156 1157 1158
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               _("security label driver mismatch: "
                                 "'%s' model configured for domain, but "
                                 "hypervisor driver is '%s'."),
1159
                               secdef->model, virSecurityManagerGetModel(mgr));
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191
        goto done;
    }

    if ( !(execcon = context_new(secdef->label)) ) {
        virReportSystemError(errno,
                             _("unable to allocate socket security context '%s'"),
                             secdef->label);
        goto done;
    }

    if (getcon(&scon) == -1) {
        virReportSystemError(errno,
                             _("unable to get current process context '%s'"),
                             secdef->label);
        goto done;
    }

    if ( !(proccon = context_new(scon)) ) {
        virReportSystemError(errno,
                             _("unable to set socket security context '%s'"),
                             secdef->label);
        goto done;
    }

    if (context_range_set(proccon, context_range_get(execcon)) == -1) {
        virReportSystemError(errno,
                             _("unable to set socket security context range '%s'"),
                             secdef->label);
        goto done;
    }

    VIR_DEBUG("Setting VM %s socket context %s",
1192
              def->name, context_str(proccon));
1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
    if (setsockcreatecon(context_str(proccon)) == -1) {
        virReportSystemError(errno,
                             _("unable to set socket security context '%s'"),
                             context_str(proccon));
        goto done;
    }

    rc = 0;
done:

    if (security_getenforce() != 1)
        rc = 0;
    if (execcon) context_free(execcon);
    if (proccon) context_free(proccon);
    freecon(scon);
    return rc;
}

1211 1212
static int
SELinuxSetSecuritySocketLabel(virSecurityManagerPtr mgr,
1213
                              virDomainDefPtr vm)
1214
{
1215
    const virSecurityLabelDefPtr secdef = &vm->seclabel;
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
    int rc = -1;

    if (secdef->label == NULL)
        return 0;

    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               _("security label driver mismatch: "
                                 "'%s' model configured for domain, but "
                                 "hypervisor driver is '%s'."),
                               secdef->model, virSecurityManagerGetModel(mgr));
        goto done;
    }

    VIR_DEBUG("Setting VM %s socket context %s",
1231
              vm->name, secdef->label);
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
    if (setsockcreatecon(secdef->label) == -1) {
        virReportSystemError(errno,
                             _("unable to set socket security context '%s'"),
                             secdef->label);
        goto done;
    }

    rc = 0;

done:
    if (security_getenforce() != 1)
        rc = 0;

    return rc;
}

1248
static int
1249
SELinuxClearSecuritySocketLabel(virSecurityManagerPtr mgr,
1250
                                virDomainDefPtr def)
1251 1252
{
    /* TODO: verify DOI */
1253
    const virSecurityLabelDefPtr secdef = &def->seclabel;
1254

1255
    if (def->seclabel.label == NULL)
1256 1257
        return 0;

1258
    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
1259 1260 1261 1262
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               _("security label driver mismatch: "
                                 "'%s' model configured for domain, but "
                                 "hypervisor driver is '%s'."),
1263
                               secdef->model, virSecurityManagerGetModel(mgr));
1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277
        if (security_getenforce() == 1)
            return -1;
    }

    if (setsockcreatecon(NULL) == -1) {
        virReportSystemError(errno,
                             _("unable to clear socket security context '%s'"),
                             secdef->label);
        if (security_getenforce() == 1)
            return -1;
    }
    return 0;
}

1278 1279

static int
1280
SELinuxSetSecurityChardevCallback(virDomainDefPtr def,
1281
                                  virDomainChrDefPtr dev,
1282
                                  void *opaque ATTRIBUTE_UNUSED)
1283
{
1284 1285 1286 1287 1288
    /* This is taken care of by processing of def->serials */
    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
        dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
        return 0;

1289
    return SELinuxSetSecurityChardevLabel(def, &dev->source);
1290 1291 1292
}


E
Eric Blake 已提交
1293
static int
1294
SELinuxSetSecuritySmartcardCallback(virDomainDefPtr def,
E
Eric Blake 已提交
1295
                                    virDomainSmartcardDefPtr dev,
1296
                                    void *opaque ATTRIBUTE_UNUSED)
E
Eric Blake 已提交
1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
{
    const char *database;

    switch (dev->type) {
    case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
        break;

    case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
        database = dev->data.cert.database;
        if (!database)
            database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
        return SELinuxSetFilecon(database, default_content_context);

    case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
1311
        return SELinuxSetSecurityChardevLabel(def, &dev->data.passthru);
E
Eric Blake 已提交
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323

    default:
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unknown smartcard type %d"),
                               dev->type);
        return -1;
    }

    return 0;
}


1324
static int
1325
SELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
1326
                           virDomainDefPtr def,
1327
                           const char *stdin_path)
1328
{
1329
    const virSecurityLabelDefPtr secdef = &def->seclabel;
1330 1331
    int i;

1332
    if (secdef->norelabel)
1333 1334
        return 0;

1335
    for (i = 0 ; i < def->ndisks ; i++) {
1336
        /* XXX fixme - we need to recursively label the entire tree :-( */
1337
        if (def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR) {
1338
            VIR_WARN("Unable to relabel directory tree %s for disk %s",
1339
                     def->disks[i]->src, def->disks[i]->dst);
1340
            continue;
1341
        }
1342
        if (SELinuxSetSecurityImageLabel(mgr,
1343
                                         def, def->disks[i]) < 0)
1344 1345
            return -1;
    }
1346
    /* XXX fixme process  def->fss if relabel == true */
1347

1348
    for (i = 0 ; i < def->nhostdevs ; i++) {
1349
        if (SELinuxSetSecurityHostdevLabel(mgr,
1350 1351
                                           def,
                                           def->hostdevs[i]) < 0)
1352
            return -1;
1353 1354
    }

1355
    if (virDomainChrDefForeach(def,
1356 1357
                               true,
                               SELinuxSetSecurityChardevCallback,
1358
                               NULL) < 0)
1359 1360
        return -1;

1361
    if (virDomainSmartcardDefForeach(def,
E
Eric Blake 已提交
1362 1363
                                     true,
                                     SELinuxSetSecuritySmartcardCallback,
1364
                                     NULL) < 0)
E
Eric Blake 已提交
1365 1366
        return -1;

1367 1368
    if (def->os.kernel &&
        SELinuxSetFilecon(def->os.kernel, default_content_context) < 0)
1369 1370
        return -1;

1371 1372
    if (def->os.initrd &&
        SELinuxSetFilecon(def->os.initrd, default_content_context) < 0)
1373 1374
        return -1;

1375 1376 1377 1378 1379 1380
    if (stdin_path) {
        if (SELinuxSetFilecon(stdin_path, default_content_context) < 0 &&
            virStorageFileIsSharedFSType(stdin_path,
                                         VIR_STORAGE_FILE_SHFS_NFS) != 1)
            return -1;
    }
1381

1382 1383 1384
    return 0;
}

1385
static int
1386
SELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1387
                       virDomainDefPtr def,
1388
                       int fd)
1389
{
1390
    const virSecurityLabelDefPtr secdef = &def->seclabel;
1391 1392 1393 1394 1395 1396 1397

    if (secdef->imagelabel == NULL)
        return 0;

    return SELinuxFSetFilecon(fd, secdef->imagelabel);
}

1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412
virSecurityDriver virSecurityDriverSELinux = {
    0,
    SECURITY_SELINUX_NAME,
    SELinuxSecurityDriverProbe,
    SELinuxSecurityDriverOpen,
    SELinuxSecurityDriverClose,

    SELinuxSecurityGetModel,
    SELinuxSecurityGetDOI,

    SELinuxSecurityVerify,

    SELinuxSetSecurityImageLabel,
    SELinuxRestoreSecurityImageLabel,

1413
    SELinuxSetSecurityDaemonSocketLabel,
1414
    SELinuxSetSecuritySocketLabel,
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431
    SELinuxClearSecuritySocketLabel,

    SELinuxGenSecurityLabel,
    SELinuxReserveSecurityLabel,
    SELinuxReleaseSecurityLabel,

    SELinuxGetSecurityProcessLabel,
    SELinuxSetSecurityProcessLabel,

    SELinuxSetSecurityAllLabel,
    SELinuxRestoreSecurityAllLabel,

    SELinuxSetSecurityHostdevLabel,
    SELinuxRestoreSecurityHostdevLabel,

    SELinuxSetSavedStateLabel,
    SELinuxRestoreSavedStateLabel,
1432

1433
    SELinuxSetImageFDLabel,
1434
};