~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages

« back to all changes in this revision

Viewing changes to .pc/ubuntu/skip-labelling-network-disks.patch/src/security/security_selinux.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-05-13 15:44:12 UTC
  • mfrom: (1.2.13)
  • Revision ID: package-import@ubuntu.com-20120513154412-fgmn5sxqdzgnzlx3
Tags: 0.9.12-0ubuntu1
* New upstream version:
  * Synchronize with debian packaging:
    - debian/control: Update build depends.
    - debian/libvirt-bin.postrm: Cleanup /var/log/libvirt
      on purge.
    - Bump standards verson (no changes).
    - debian/patches/Don-t-fail-if-we-can-t-setup-avahi.patch: Added
  * Dropped patches:
    - debian/patches/Debianize-libvirt-guests.patch
    - debian/patches/rewrite-lxc-controller-eof-handling-yet-again
    - debian/patches/ubuntu/libnl13.patch
    - debian/patches/ubuntu/fix-lxc-startup-error.patch
    - debian/patches/ubuntu/fix-bridge-fd.patch
    - debian/patches/ubuntu/skip-labelling-network-disks.patch
    - debian/patches/ubuntu/xen-xend-shutdown-detection.patch
    - debian/patches/ubuntu/xen-config-no-vfb-for-hvm.patch
    - debian/patches/debian/Disable-daemon-start-test.patch
    - debian/patches/debian/Disable-gnulib-s-test-nonplocking-pipe.sh.patch
    - debian/patches/ubuntu/9006-default-config-test-case.patch
    - debian/patches/fix-block-migration.patch
    - debian/patches/ubuntu/9022-qemu-unescape-HMP-commands-before-converting-them-to.patch
    - debian/patches/ubuntu/9023-qemu-change-rbd-auth_supported-separation-character-.patch
    - debian/patches/ubuntu/9024-qemu-allow-snapshotting-of-sheepdog-and-rbd-disks.patch
    - debian/patches/9025-qemu-change-rbd-auth_supported-separation-character-.patch
    - debian/patches/ubuntu/arm-gcc-workaround.patch
  * Rediffed:
    - debian/patches/Allow-libvirt-group-to-access-the-socket.patch
    - debian/patches/Disable-failing-virnetsockettest.patch
    - debian/patches/dnsmasq-as-priv-user
    - debian/patches/9002-better_default_uri_virsh.patch
  * debian/control: Add libnl-route-3-dev ass a build depends.
  * debian/patches/libnl3-build-fix.patch: Fix build with libnl3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2008-2011 Red Hat, Inc.
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2.1 of the License, or (at your option) any later version.
8
 
 *
9
 
 * Authors:
10
 
 *     James Morris <jmorris@namei.org>
11
 
 *     Dan Walsh <dwalsh@redhat.com>
12
 
 *
13
 
 * SELinux security driver.
14
 
 */
15
 
#include <config.h>
16
 
#include <selinux/selinux.h>
17
 
#include <selinux/context.h>
18
 
#include <sys/types.h>
19
 
#include <sys/stat.h>
20
 
#include <fcntl.h>
21
 
#if HAVE_SELINUX_LABEL_H
22
 
# include <selinux/label.h>
23
 
#endif
24
 
 
25
 
#include "security_driver.h"
26
 
#include "security_selinux.h"
27
 
#include "virterror_internal.h"
28
 
#include "util.h"
29
 
#include "memory.h"
30
 
#include "logging.h"
31
 
#include "pci.h"
32
 
#include "hostusb.h"
33
 
#include "storage_file.h"
34
 
#include "virfile.h"
35
 
 
36
 
#define VIR_FROM_THIS VIR_FROM_SECURITY
37
 
 
38
 
static char default_domain_context[1024];
39
 
static char default_content_context[1024];
40
 
static char default_image_context[1024];
41
 
#define SECURITY_SELINUX_VOID_DOI       "0"
42
 
#define SECURITY_SELINUX_NAME "selinux"
43
 
 
44
 
/* TODO
45
 
   The data struct of used mcs should be replaced with a better data structure in the future
46
 
*/
47
 
 
48
 
struct MCS {
49
 
    char *mcs;
50
 
    struct MCS *next;
51
 
};
52
 
static struct MCS *mcsList = NULL;
53
 
 
54
 
static int
55
 
mcsAdd(const char *mcs)
56
 
{
57
 
    struct MCS *ptr;
58
 
 
59
 
    for (ptr = mcsList; ptr; ptr = ptr->next) {
60
 
        if (STREQ(ptr->mcs, mcs))
61
 
            return -1;
62
 
    }
63
 
    if (VIR_ALLOC(ptr) < 0)
64
 
        return -1;
65
 
    ptr->mcs = strdup(mcs);
66
 
    ptr->next = mcsList;
67
 
    mcsList = ptr;
68
 
    return 0;
69
 
}
70
 
 
71
 
static int
72
 
mcsRemove(const char *mcs)
73
 
{
74
 
    struct MCS *prevptr = NULL;
75
 
    struct MCS *ptr = NULL;
76
 
 
77
 
    for (ptr = mcsList; ptr; ptr = ptr->next) {
78
 
        if (STREQ(ptr->mcs, mcs)) {
79
 
            if (prevptr)
80
 
                prevptr->next = ptr->next;
81
 
            else {
82
 
                mcsList = ptr->next;
83
 
            }
84
 
            VIR_FREE(ptr->mcs);
85
 
            VIR_FREE(ptr);
86
 
            return 0;
87
 
        }
88
 
        prevptr = ptr;
89
 
    }
90
 
    return -1;
91
 
}
92
 
 
93
 
static char *
94
 
SELinuxGenNewContext(const char *oldcontext, const char *mcs)
95
 
{
96
 
    char *newcontext = NULL;
97
 
    char *scontext = strdup(oldcontext);
98
 
    context_t con;
99
 
    if (!scontext) goto err;
100
 
    con = context_new(scontext);
101
 
    if (!con) goto err;
102
 
    context_range_set(con, mcs);
103
 
    newcontext = strdup(context_str(con));
104
 
    context_free(con);
105
 
err:
106
 
    freecon(scontext);
107
 
    return (newcontext);
108
 
}
109
 
 
110
 
static int
111
 
SELinuxInitialize(void)
112
 
{
113
 
    char *ptr = NULL;
114
 
    int fd = 0;
115
 
 
116
 
    fd = open(selinux_virtual_domain_context_path(), O_RDONLY);
117
 
    if (fd < 0) {
118
 
        virReportSystemError(errno,
119
 
                             _("cannot open SELinux virtual domain context file '%s'"),
120
 
                             selinux_virtual_domain_context_path());
121
 
        return -1;
122
 
    }
123
 
 
124
 
    if (saferead(fd, default_domain_context, sizeof(default_domain_context)) < 0) {
125
 
        virReportSystemError(errno,
126
 
                             _("cannot read SELinux virtual domain context file %s"),
127
 
                             selinux_virtual_domain_context_path());
128
 
        VIR_FORCE_CLOSE(fd);
129
 
        return -1;
130
 
    }
131
 
    VIR_FORCE_CLOSE(fd);
132
 
 
133
 
    ptr = strchrnul(default_domain_context, '\n');
134
 
    *ptr = '\0';
135
 
 
136
 
    if ((fd = open(selinux_virtual_image_context_path(), O_RDONLY)) < 0) {
137
 
        virReportSystemError(errno,
138
 
                             _("cannot open SELinux virtual image context file %s"),
139
 
                             selinux_virtual_image_context_path());
140
 
        return -1;
141
 
    }
142
 
 
143
 
    if (saferead(fd, default_image_context, sizeof(default_image_context)) < 0) {
144
 
        virReportSystemError(errno,
145
 
                             _("cannot read SELinux virtual image context file %s"),
146
 
                             selinux_virtual_image_context_path());
147
 
        VIR_FORCE_CLOSE(fd);
148
 
        return -1;
149
 
    }
150
 
    VIR_FORCE_CLOSE(fd);
151
 
 
152
 
    ptr = strchrnul(default_image_context, '\n');
153
 
    if (*ptr == '\n') {
154
 
        *ptr = '\0';
155
 
        strcpy(default_content_context, ptr+1);
156
 
        ptr = strchrnul(default_content_context, '\n');
157
 
        if (*ptr == '\n')
158
 
            *ptr = '\0';
159
 
    }
160
 
    return 0;
161
 
}
162
 
 
163
 
static int
164
 
SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
165
 
                        virDomainObjPtr vm)
166
 
{
167
 
    int rc = -1;
168
 
    char *mcs = NULL;
169
 
    char *scontext = NULL;
170
 
    int c1 = 0;
171
 
    int c2 = 0;
172
 
    context_t ctx = NULL;
173
 
 
174
 
    if ((vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) &&
175
 
        !vm->def->seclabel.baselabel &&
176
 
        vm->def->seclabel.model) {
177
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
178
 
                               "%s", _("security model already defined for VM"));
179
 
        return rc;
180
 
    }
181
 
 
182
 
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
183
 
        vm->def->seclabel.label) {
184
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
185
 
                               "%s", _("security label already defined for VM"));
186
 
        return rc;
187
 
    }
188
 
 
189
 
    if (vm->def->seclabel.imagelabel) {
190
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
191
 
                               "%s", _("security image label already defined for VM"));
192
 
        return rc;
193
 
    }
194
 
 
195
 
    if (vm->def->seclabel.model &&
196
 
        STRNEQ(vm->def->seclabel.model, SECURITY_SELINUX_NAME)) {
197
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
198
 
                               _("security label model %s is not supported with selinux"),
199
 
                               vm->def->seclabel.model);
200
 
        return rc;
201
 
    }
202
 
 
203
 
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC) {
204
 
        if (!(ctx = context_new(vm->def->seclabel.label)) ) {
205
 
            virReportSystemError(errno,
206
 
                                 _("unable to allocate socket security context '%s'"),
207
 
                                 vm->def->seclabel.label);
208
 
            return rc;
209
 
        }
210
 
 
211
 
        const char *range = context_range_get(ctx);
212
 
        if (!range ||
213
 
            !(mcs = strdup(range))) {
214
 
            virReportOOMError();
215
 
            goto cleanup;
216
 
        }
217
 
    } else {
218
 
        do {
219
 
            c1 = virRandom(1024);
220
 
            c2 = virRandom(1024);
221
 
 
222
 
            if ( c1 == c2 ) {
223
 
                if (virAsprintf(&mcs, "s0:c%d", c1) < 0) {
224
 
                    virReportOOMError();
225
 
                    goto cleanup;
226
 
                }
227
 
            } else {
228
 
                if (c1 > c2) {
229
 
                    c1 ^= c2;
230
 
                    c2 ^= c1;
231
 
                    c1 ^= c2;
232
 
                }
233
 
                if (virAsprintf(&mcs, "s0:c%d,c%d", c1, c2) < 0) {
234
 
                    virReportOOMError();
235
 
                    goto cleanup;
236
 
                }
237
 
            }
238
 
        } while (mcsAdd(mcs) == -1);
239
 
 
240
 
        vm->def->seclabel.label =
241
 
            SELinuxGenNewContext(vm->def->seclabel.baselabel ?
242
 
                                 vm->def->seclabel.baselabel :
243
 
                                 default_domain_context, mcs);
244
 
        if (! vm->def->seclabel.label)  {
245
 
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
246
 
                                   _("cannot generate selinux context for %s"), mcs);
247
 
            goto cleanup;
248
 
        }
249
 
    }
250
 
    vm->def->seclabel.imagelabel = SELinuxGenNewContext(default_image_context, mcs);
251
 
    if (!vm->def->seclabel.imagelabel)  {
252
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
253
 
                               _("cannot generate selinux context for %s"), mcs);
254
 
        goto cleanup;
255
 
    }
256
 
 
257
 
    if (!vm->def->seclabel.model &&
258
 
        !(vm->def->seclabel.model = strdup(SECURITY_SELINUX_NAME))) {
259
 
        virReportOOMError();
260
 
        goto cleanup;
261
 
    }
262
 
 
263
 
    rc = 0;
264
 
 
265
 
cleanup:
266
 
    if (rc != 0) {
267
 
        if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)
268
 
            VIR_FREE(vm->def->seclabel.label);
269
 
        VIR_FREE(vm->def->seclabel.imagelabel);
270
 
        if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
271
 
            !vm->def->seclabel.baselabel)
272
 
            VIR_FREE(vm->def->seclabel.model);
273
 
    }
274
 
 
275
 
    if (ctx)
276
 
        context_free(ctx);
277
 
    VIR_FREE(scontext);
278
 
    VIR_FREE(mcs);
279
 
 
280
 
    VIR_DEBUG("model=%s label=%s imagelabel=%s baselabel=%s",
281
 
              NULLSTR(vm->def->seclabel.model),
282
 
              NULLSTR(vm->def->seclabel.label),
283
 
              NULLSTR(vm->def->seclabel.imagelabel),
284
 
              NULLSTR(vm->def->seclabel.baselabel));
285
 
 
286
 
    return rc;
287
 
}
288
 
 
289
 
static int
290
 
SELinuxReserveSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
291
 
                            virDomainObjPtr vm)
292
 
{
293
 
    security_context_t pctx;
294
 
    context_t ctx = NULL;
295
 
    const char *mcs;
296
 
 
297
 
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
298
 
        return 0;
299
 
 
300
 
    if (getpidcon(vm->pid, &pctx) == -1) {
301
 
        virReportSystemError(errno,
302
 
                             _("unable to get PID %d security context"), vm->pid);
303
 
        return -1;
304
 
    }
305
 
 
306
 
    ctx = context_new(pctx);
307
 
    freecon(pctx);
308
 
    if (!ctx)
309
 
        goto err;
310
 
 
311
 
    mcs = context_range_get(ctx);
312
 
    if (!mcs)
313
 
        goto err;
314
 
 
315
 
    mcsAdd(mcs);
316
 
 
317
 
    context_free(ctx);
318
 
 
319
 
    return 0;
320
 
 
321
 
err:
322
 
    context_free(ctx);
323
 
    return -1;
324
 
}
325
 
 
326
 
 
327
 
 
328
 
static int
329
 
SELinuxSecurityDriverProbe(void)
330
 
{
331
 
    return is_selinux_enabled() ? SECURITY_DRIVER_ENABLE : SECURITY_DRIVER_DISABLE;
332
 
}
333
 
 
334
 
static int
335
 
SELinuxSecurityDriverOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
336
 
{
337
 
    return SELinuxInitialize();
338
 
}
339
 
 
340
 
static int
341
 
SELinuxSecurityDriverClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
342
 
{
343
 
    return 0;
344
 
}
345
 
 
346
 
 
347
 
static const char *SELinuxSecurityGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
348
 
{
349
 
    return SECURITY_SELINUX_NAME;
350
 
}
351
 
 
352
 
static const char *SELinuxSecurityGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
353
 
{
354
 
    /*
355
 
     * Where will the DOI come from?  SELinux configuration, or qemu
356
 
     * configuration? For the moment, we'll just set it to "0".
357
 
     */
358
 
    return SECURITY_SELINUX_VOID_DOI;
359
 
}
360
 
 
361
 
static int
362
 
SELinuxGetSecurityProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
363
 
                               virDomainObjPtr vm,
364
 
                               virSecurityLabelPtr sec)
365
 
{
366
 
    security_context_t ctx;
367
 
 
368
 
    if (getpidcon(vm->pid, &ctx) == -1) {
369
 
        virReportSystemError(errno,
370
 
                             _("unable to get PID %d security context"),
371
 
                             vm->pid);
372
 
        return -1;
373
 
    }
374
 
 
375
 
    if (strlen((char *) ctx) >= VIR_SECURITY_LABEL_BUFLEN) {
376
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
377
 
                               _("security label exceeds "
378
 
                                 "maximum length: %d"),
379
 
                               VIR_SECURITY_LABEL_BUFLEN - 1);
380
 
        freecon(ctx);
381
 
        return -1;
382
 
    }
383
 
 
384
 
    strcpy(sec->label, (char *) ctx);
385
 
    freecon(ctx);
386
 
 
387
 
    sec->enforcing = security_getenforce();
388
 
    if (sec->enforcing == -1) {
389
 
        virReportSystemError(errno, "%s",
390
 
                             _("error calling security_getenforce()"));
391
 
        return -1;
392
 
    }
393
 
 
394
 
    return 0;
395
 
}
396
 
 
397
 
static int
398
 
SELinuxSetFilecon(const char *path, char *tcon)
399
 
{
400
 
    security_context_t econ;
401
 
 
402
 
    VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon);
403
 
 
404
 
    if (setfilecon(path, tcon) < 0) {
405
 
        int setfilecon_errno = errno;
406
 
 
407
 
        if (getfilecon(path, &econ) >= 0) {
408
 
            if (STREQ(tcon, econ)) {
409
 
                freecon(econ);
410
 
                /* It's alright, there's nothing to change anyway. */
411
 
                return 0;
412
 
            }
413
 
            freecon(econ);
414
 
        }
415
 
 
416
 
        /* if the error complaint is related to an image hosted on
417
 
         * an nfs mount, or a usbfs/sysfs filesystem not supporting
418
 
         * labelling, then just ignore it & hope for the best.
419
 
         * The user hopefully set one of the necessary SELinux
420
 
         * virt_use_{nfs,usb,pci}  boolean tunables to allow it...
421
 
         */
422
 
        if (setfilecon_errno != EOPNOTSUPP && setfilecon_errno != ENOTSUP) {
423
 
            virReportSystemError(setfilecon_errno,
424
 
                                 _("unable to set security context '%s' on '%s'"),
425
 
                                 tcon, path);
426
 
            if (security_getenforce() == 1)
427
 
                return -1;
428
 
        } else {
429
 
            const char *msg;
430
 
            if ((virStorageFileIsSharedFSType(path,
431
 
                                              VIR_STORAGE_FILE_SHFS_NFS) == 1) &&
432
 
                security_get_boolean_active("virt_use_nfs") != 1) {
433
 
                msg = _("Setting security context '%s' on '%s' not supported. "
434
 
                        "Consider setting virt_use_nfs");
435
 
               if (security_getenforce() == 1)
436
 
                   VIR_WARN(msg, tcon, path);
437
 
               else
438
 
                   VIR_INFO(msg, tcon, path);
439
 
            } else {
440
 
                VIR_INFO("Setting security context '%s' on '%s' not supported",
441
 
                         tcon, path);
442
 
            }
443
 
        }
444
 
    }
445
 
    return 0;
446
 
}
447
 
 
448
 
static int
449
 
SELinuxFSetFilecon(int fd, char *tcon)
450
 
{
451
 
    security_context_t econ;
452
 
 
453
 
    VIR_INFO("Setting SELinux context on fd %d to '%s'", fd, tcon);
454
 
 
455
 
    if (fsetfilecon(fd, tcon) < 0) {
456
 
        int fsetfilecon_errno = errno;
457
 
 
458
 
        if (fgetfilecon(fd, &econ) >= 0) {
459
 
            if (STREQ(tcon, econ)) {
460
 
                freecon(econ);
461
 
                /* It's alright, there's nothing to change anyway. */
462
 
                return 0;
463
 
            }
464
 
            freecon(econ);
465
 
        }
466
 
 
467
 
        /* if the error complaint is related to an image hosted on
468
 
         * an nfs mount, or a usbfs/sysfs filesystem not supporting
469
 
         * labelling, then just ignore it & hope for the best.
470
 
         * The user hopefully set one of the necessary SELinux
471
 
         * virt_use_{nfs,usb,pci}  boolean tunables to allow it...
472
 
         */
473
 
        if (fsetfilecon_errno != EOPNOTSUPP) {
474
 
            virReportSystemError(fsetfilecon_errno,
475
 
                                 _("unable to set security context '%s' on fd %d"),
476
 
                                 tcon, fd);
477
 
            if (security_getenforce() == 1)
478
 
                return -1;
479
 
        } else {
480
 
            VIR_INFO("Setting security context '%s' on fd %d not supported",
481
 
                     tcon, fd);
482
 
        }
483
 
    }
484
 
    return 0;
485
 
}
486
 
 
487
 
/* Set fcon to the appropriate label for path and mode, or return -1.  */
488
 
static int
489
 
getContext(const char *newpath, mode_t mode, security_context_t *fcon)
490
 
{
491
 
#if HAVE_SELINUX_LABEL_H
492
 
    struct selabel_handle *handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
493
 
    int ret;
494
 
 
495
 
    if (handle == NULL)
496
 
        return -1;
497
 
 
498
 
    ret = selabel_lookup(handle, fcon, newpath, mode);
499
 
    selabel_close(handle);
500
 
    return ret;
501
 
#else
502
 
    return matchpathcon(newpath, mode, fcon);
503
 
#endif
504
 
}
505
 
 
506
 
 
507
 
/* This method shouldn't raise errors, since they'll overwrite
508
 
 * errors that the caller(s) are already dealing with */
509
 
static int
510
 
SELinuxRestoreSecurityFileLabel(const char *path)
511
 
{
512
 
    struct stat buf;
513
 
    security_context_t fcon = NULL;
514
 
    int rc = -1;
515
 
    char *newpath = NULL;
516
 
    char ebuf[1024];
517
 
 
518
 
    VIR_INFO("Restoring SELinux context on '%s'", path);
519
 
 
520
 
    if (virFileResolveLink(path, &newpath) < 0) {
521
 
        VIR_WARN("cannot resolve symlink %s: %s", path,
522
 
                 virStrerror(errno, ebuf, sizeof(ebuf)));
523
 
        goto err;
524
 
    }
525
 
 
526
 
    if (stat(newpath, &buf) != 0) {
527
 
        VIR_WARN("cannot stat %s: %s", newpath,
528
 
                 virStrerror(errno, ebuf, sizeof(ebuf)));
529
 
        goto err;
530
 
    }
531
 
 
532
 
    if (getContext(newpath, buf.st_mode, &fcon) < 0) {
533
 
        VIR_WARN("cannot lookup default selinux label for %s", newpath);
534
 
    } else {
535
 
        rc = SELinuxSetFilecon(newpath, fcon);
536
 
    }
537
 
 
538
 
err:
539
 
    freecon(fcon);
540
 
    VIR_FREE(newpath);
541
 
    return rc;
542
 
}
543
 
 
544
 
static int
545
 
SELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
546
 
                                    virDomainObjPtr vm,
547
 
                                    virDomainDiskDefPtr disk,
548
 
                                    int migrated)
549
 
{
550
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
551
 
 
552
 
    if (secdef->norelabel)
553
 
        return 0;
554
 
 
555
 
    /* Don't restore labels on readoly/shared disks, because
556
 
     * other VMs may still be accessing these
557
 
     * Alternatively we could iterate over all running
558
 
     * domains and try to figure out if it is in use, but
559
 
     * this would not work for clustered filesystems, since
560
 
     * we can't see running VMs using the file on other nodes
561
 
     * Safest bet is thus to skip the restore step.
562
 
     */
563
 
    if (disk->readonly || disk->shared)
564
 
        return 0;
565
 
 
566
 
    if (!disk->src || disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK)
567
 
        return 0;
568
 
 
569
 
    /* If we have a shared FS & doing migrated, we must not
570
 
     * change ownership, because that kills access on the
571
 
     * destination host which is sub-optimal for the guest
572
 
     * VM's I/O attempts :-)
573
 
     */
574
 
    if (migrated) {
575
 
        int rc = virStorageFileIsSharedFS(disk->src);
576
 
        if (rc < 0)
577
 
            return -1;
578
 
        if (rc == 1) {
579
 
            VIR_DEBUG("Skipping image label restore on %s because FS is shared",
580
 
                      disk->src);
581
 
            return 0;
582
 
        }
583
 
    }
584
 
 
585
 
    return SELinuxRestoreSecurityFileLabel(disk->src);
586
 
}
587
 
 
588
 
 
589
 
static int
590
 
SELinuxRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
591
 
                                 virDomainObjPtr vm,
592
 
                                 virDomainDiskDefPtr disk)
593
 
{
594
 
    return SELinuxRestoreSecurityImageLabelInt(mgr, vm, disk, 0);
595
 
}
596
 
 
597
 
 
598
 
static int
599
 
SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
600
 
                            const char *path,
601
 
                            size_t depth,
602
 
                            void *opaque)
603
 
{
604
 
    const virSecurityLabelDefPtr secdef = opaque;
605
 
    int ret;
606
 
 
607
 
    if (depth == 0) {
608
 
        if (disk->shared) {
609
 
            ret = SELinuxSetFilecon(path, default_image_context);
610
 
        } else if (disk->readonly) {
611
 
            ret = SELinuxSetFilecon(path, default_content_context);
612
 
        } else if (secdef->imagelabel) {
613
 
            ret = SELinuxSetFilecon(path, secdef->imagelabel);
614
 
        } else {
615
 
            ret = 0;
616
 
        }
617
 
    } else {
618
 
        ret = SELinuxSetFilecon(path, default_content_context);
619
 
    }
620
 
    if (ret < 0 &&
621
 
        virStorageFileIsSharedFSType(path,
622
 
                                     VIR_STORAGE_FILE_SHFS_NFS) == 1)
623
 
       ret = 0;
624
 
    return ret;
625
 
}
626
 
 
627
 
static int
628
 
SELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr,
629
 
                             virDomainObjPtr vm,
630
 
                             virDomainDiskDefPtr disk)
631
 
 
632
 
{
633
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
634
 
    bool allowDiskFormatProbing = virSecurityManagerGetAllowDiskFormatProbing(mgr);
635
 
 
636
 
    if (secdef->norelabel)
637
 
        return 0;
638
 
 
639
 
    return virDomainDiskDefForeachPath(disk,
640
 
                                       allowDiskFormatProbing,
641
 
                                       true,
642
 
                                       SELinuxSetSecurityFileLabel,
643
 
                                       secdef);
644
 
}
645
 
 
646
 
 
647
 
static int
648
 
SELinuxSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
649
 
                           const char *file, void *opaque)
650
 
{
651
 
    virDomainObjPtr vm = opaque;
652
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
653
 
 
654
 
    return SELinuxSetFilecon(file, secdef->imagelabel);
655
 
}
656
 
 
657
 
static int
658
 
SELinuxSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
659
 
                           const char *file, void *opaque)
660
 
{
661
 
    virDomainObjPtr vm = opaque;
662
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
663
 
 
664
 
    return SELinuxSetFilecon(file, secdef->imagelabel);
665
 
}
666
 
 
667
 
static int
668
 
SELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
669
 
                               virDomainObjPtr vm,
670
 
                               virDomainHostdevDefPtr dev)
671
 
 
672
 
{
673
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
674
 
    int ret = -1;
675
 
 
676
 
    if (secdef->norelabel)
677
 
        return 0;
678
 
 
679
 
    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
680
 
        return 0;
681
 
 
682
 
    switch (dev->source.subsys.type) {
683
 
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
684
 
        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
685
 
                                      dev->source.subsys.u.usb.device);
686
 
 
687
 
        if (!usb)
688
 
            goto done;
689
 
 
690
 
        ret = usbDeviceFileIterate(usb, SELinuxSetSecurityUSBLabel, vm);
691
 
        usbFreeDevice(usb);
692
 
        break;
693
 
    }
694
 
 
695
 
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
696
 
        pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
697
 
                                      dev->source.subsys.u.pci.bus,
698
 
                                      dev->source.subsys.u.pci.slot,
699
 
                                      dev->source.subsys.u.pci.function);
700
 
 
701
 
        if (!pci)
702
 
            goto done;
703
 
 
704
 
        ret = pciDeviceFileIterate(pci, SELinuxSetSecurityPCILabel, vm);
705
 
        pciFreeDevice(pci);
706
 
 
707
 
        break;
708
 
    }
709
 
 
710
 
    default:
711
 
        ret = 0;
712
 
        break;
713
 
    }
714
 
 
715
 
done:
716
 
    return ret;
717
 
}
718
 
 
719
 
 
720
 
static int
721
 
SELinuxRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
722
 
                               const char *file,
723
 
                               void *opaque ATTRIBUTE_UNUSED)
724
 
{
725
 
    return SELinuxRestoreSecurityFileLabel(file);
726
 
}
727
 
 
728
 
static int
729
 
SELinuxRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
730
 
                               const char *file,
731
 
                               void *opaque ATTRIBUTE_UNUSED)
732
 
{
733
 
    return SELinuxRestoreSecurityFileLabel(file);
734
 
}
735
 
 
736
 
static int
737
 
SELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
738
 
                                   virDomainObjPtr vm,
739
 
                                   virDomainHostdevDefPtr dev)
740
 
 
741
 
{
742
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
743
 
    int ret = -1;
744
 
 
745
 
    if (secdef->norelabel)
746
 
        return 0;
747
 
 
748
 
    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
749
 
        return 0;
750
 
 
751
 
    switch (dev->source.subsys.type) {
752
 
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
753
 
        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
754
 
                                      dev->source.subsys.u.usb.device);
755
 
 
756
 
        if (!usb)
757
 
            goto done;
758
 
 
759
 
        ret = usbDeviceFileIterate(usb, SELinuxRestoreSecurityUSBLabel, NULL);
760
 
        usbFreeDevice(usb);
761
 
 
762
 
        break;
763
 
    }
764
 
 
765
 
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
766
 
        pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
767
 
                                      dev->source.subsys.u.pci.bus,
768
 
                                      dev->source.subsys.u.pci.slot,
769
 
                                      dev->source.subsys.u.pci.function);
770
 
 
771
 
        if (!pci)
772
 
            goto done;
773
 
 
774
 
        ret = pciDeviceFileIterate(pci, SELinuxRestoreSecurityPCILabel, NULL);
775
 
        pciFreeDevice(pci);
776
 
 
777
 
        break;
778
 
    }
779
 
 
780
 
    default:
781
 
        ret = 0;
782
 
        break;
783
 
    }
784
 
 
785
 
done:
786
 
    return ret;
787
 
}
788
 
 
789
 
 
790
 
static int
791
 
SELinuxSetSecurityChardevLabel(virDomainObjPtr vm,
792
 
                               virDomainChrSourceDefPtr dev)
793
 
 
794
 
{
795
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
796
 
    char *in = NULL, *out = NULL;
797
 
    int ret = -1;
798
 
 
799
 
    if (secdef->norelabel)
800
 
        return 0;
801
 
 
802
 
    switch (dev->type) {
803
 
    case VIR_DOMAIN_CHR_TYPE_DEV:
804
 
    case VIR_DOMAIN_CHR_TYPE_FILE:
805
 
        ret = SELinuxSetFilecon(dev->data.file.path, secdef->imagelabel);
806
 
        break;
807
 
 
808
 
    case VIR_DOMAIN_CHR_TYPE_PIPE:
809
 
        if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) ||
810
 
            (virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) {
811
 
            virReportOOMError();
812
 
            goto done;
813
 
        }
814
 
        if (virFileExists(in) && virFileExists(out)) {
815
 
            if ((SELinuxSetFilecon(in, secdef->imagelabel) < 0) ||
816
 
                (SELinuxSetFilecon(out, secdef->imagelabel) < 0)) {
817
 
                goto done;
818
 
            }
819
 
        } else if (SELinuxSetFilecon(dev->data.file.path, secdef->imagelabel) < 0) {
820
 
            goto done;
821
 
        }
822
 
        ret = 0;
823
 
        break;
824
 
 
825
 
    default:
826
 
        ret = 0;
827
 
        break;
828
 
    }
829
 
 
830
 
done:
831
 
    VIR_FREE(in);
832
 
    VIR_FREE(out);
833
 
    return ret;
834
 
}
835
 
 
836
 
static int
837
 
SELinuxRestoreSecurityChardevLabel(virDomainObjPtr vm,
838
 
                                   virDomainChrSourceDefPtr dev)
839
 
 
840
 
{
841
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
842
 
    char *in = NULL, *out = NULL;
843
 
    int ret = -1;
844
 
 
845
 
    if (secdef->norelabel)
846
 
        return 0;
847
 
 
848
 
    switch (dev->type) {
849
 
    case VIR_DOMAIN_CHR_TYPE_DEV:
850
 
    case VIR_DOMAIN_CHR_TYPE_FILE:
851
 
        if (SELinuxRestoreSecurityFileLabel(dev->data.file.path) < 0)
852
 
            goto done;
853
 
        ret = 0;
854
 
        break;
855
 
    case VIR_DOMAIN_CHR_TYPE_PIPE:
856
 
        if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) ||
857
 
            (virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) {
858
 
            virReportOOMError();
859
 
            goto done;
860
 
        }
861
 
        if (virFileExists(in) && virFileExists(out)) {
862
 
            if ((SELinuxRestoreSecurityFileLabel(out) < 0) ||
863
 
                (SELinuxRestoreSecurityFileLabel(in) < 0)) {
864
 
                goto done;
865
 
            }
866
 
        } else if (SELinuxRestoreSecurityFileLabel(dev->data.file.path) < 0) {
867
 
            goto done;
868
 
        }
869
 
        ret = 0;
870
 
        break;
871
 
 
872
 
    default:
873
 
        ret = 0;
874
 
        break;
875
 
    }
876
 
 
877
 
done:
878
 
    VIR_FREE(in);
879
 
    VIR_FREE(out);
880
 
    return ret;
881
 
}
882
 
 
883
 
 
884
 
static int
885
 
SELinuxRestoreSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
886
 
                                      virDomainChrDefPtr dev,
887
 
                                      void *opaque)
888
 
{
889
 
    virDomainObjPtr vm = opaque;
890
 
 
891
 
    /* This is taken care of by processing of def->serials */
892
 
    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
893
 
        dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
894
 
        return 0;
895
 
 
896
 
    return SELinuxRestoreSecurityChardevLabel(vm, &dev->source);
897
 
}
898
 
 
899
 
 
900
 
static int
901
 
SELinuxRestoreSecuritySmartcardCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
902
 
                                        virDomainSmartcardDefPtr dev,
903
 
                                        void *opaque)
904
 
{
905
 
    virDomainObjPtr vm = opaque;
906
 
    const char *database;
907
 
 
908
 
    switch (dev->type) {
909
 
    case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
910
 
        break;
911
 
 
912
 
    case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
913
 
        database = dev->data.cert.database;
914
 
        if (!database)
915
 
            database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
916
 
        return SELinuxRestoreSecurityFileLabel(database);
917
 
 
918
 
    case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
919
 
        return SELinuxRestoreSecurityChardevLabel(vm, &dev->data.passthru);
920
 
 
921
 
    default:
922
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
923
 
                               _("unknown smartcard type %d"),
924
 
                               dev->type);
925
 
        return -1;
926
 
    }
927
 
 
928
 
    return 0;
929
 
}
930
 
 
931
 
 
932
 
static int
933
 
SELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
934
 
                               virDomainObjPtr vm,
935
 
                               int migrated ATTRIBUTE_UNUSED)
936
 
{
937
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
938
 
    int i;
939
 
    int rc = 0;
940
 
 
941
 
    VIR_DEBUG("Restoring security label on %s", vm->def->name);
942
 
 
943
 
    if (secdef->norelabel)
944
 
        return 0;
945
 
 
946
 
    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
947
 
        if (SELinuxRestoreSecurityHostdevLabel(mgr,
948
 
                                               vm,
949
 
                                               vm->def->hostdevs[i]) < 0)
950
 
            rc = -1;
951
 
    }
952
 
    for (i = 0 ; i < vm->def->ndisks ; i++) {
953
 
        if (SELinuxRestoreSecurityImageLabelInt(mgr,
954
 
                                                vm,
955
 
                                                vm->def->disks[i],
956
 
                                                migrated) < 0)
957
 
            rc = -1;
958
 
    }
959
 
 
960
 
    if (virDomainChrDefForeach(vm->def,
961
 
                               false,
962
 
                               SELinuxRestoreSecurityChardevCallback,
963
 
                               vm) < 0)
964
 
        rc = -1;
965
 
 
966
 
    if (virDomainSmartcardDefForeach(vm->def,
967
 
                                     false,
968
 
                                     SELinuxRestoreSecuritySmartcardCallback,
969
 
                                     vm) < 0)
970
 
        rc = -1;
971
 
 
972
 
    if (vm->def->os.kernel &&
973
 
        SELinuxRestoreSecurityFileLabel(vm->def->os.kernel) < 0)
974
 
        rc = -1;
975
 
 
976
 
    if (vm->def->os.initrd &&
977
 
        SELinuxRestoreSecurityFileLabel(vm->def->os.initrd) < 0)
978
 
        rc = -1;
979
 
 
980
 
    return rc;
981
 
}
982
 
 
983
 
static int
984
 
SELinuxReleaseSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
985
 
                            virDomainObjPtr vm)
986
 
{
987
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
988
 
 
989
 
    if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
990
 
        if (secdef->label != NULL) {
991
 
            context_t con = context_new(secdef->label);
992
 
            if (con) {
993
 
                mcsRemove(context_range_get(con));
994
 
                context_free(con);
995
 
            }
996
 
        }
997
 
        VIR_FREE(secdef->label);
998
 
        if (!secdef->baselabel)
999
 
            VIR_FREE(secdef->model);
1000
 
    }
1001
 
    VIR_FREE(secdef->imagelabel);
1002
 
 
1003
 
    return 0;
1004
 
}
1005
 
 
1006
 
 
1007
 
static int
1008
 
SELinuxSetSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1009
 
                          virDomainObjPtr vm,
1010
 
                          const char *savefile)
1011
 
{
1012
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
1013
 
 
1014
 
    if (secdef->norelabel)
1015
 
        return 0;
1016
 
 
1017
 
    return SELinuxSetFilecon(savefile, secdef->imagelabel);
1018
 
}
1019
 
 
1020
 
 
1021
 
static int
1022
 
SELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1023
 
                              virDomainObjPtr vm,
1024
 
                              const char *savefile)
1025
 
{
1026
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
1027
 
 
1028
 
    if (secdef->norelabel)
1029
 
        return 0;
1030
 
 
1031
 
    return SELinuxRestoreSecurityFileLabel(savefile);
1032
 
}
1033
 
 
1034
 
 
1035
 
static int
1036
 
SELinuxSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1037
 
                      virDomainDefPtr def)
1038
 
{
1039
 
    const virSecurityLabelDefPtr secdef = &def->seclabel;
1040
 
    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
1041
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
1042
 
                               _("security label driver mismatch: "
1043
 
                                 "'%s' model configured for domain, but "
1044
 
                                 "hypervisor driver is '%s'."),
1045
 
                               secdef->model, virSecurityManagerGetModel(mgr));
1046
 
        return -1;
1047
 
    }
1048
 
 
1049
 
    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) {
1050
 
        if (security_check_context(secdef->label) != 0) {
1051
 
            virSecurityReportError(VIR_ERR_XML_ERROR,
1052
 
                                   _("Invalid security label %s"), secdef->label);
1053
 
            return -1;
1054
 
        }
1055
 
    }
1056
 
    return 0;
1057
 
}
1058
 
 
1059
 
static int
1060
 
SELinuxSetSecurityProcessLabel(virSecurityManagerPtr mgr,
1061
 
                               virDomainObjPtr vm)
1062
 
{
1063
 
    /* TODO: verify DOI */
1064
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
1065
 
 
1066
 
    if (vm->def->seclabel.label == NULL)
1067
 
        return 0;
1068
 
 
1069
 
    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
1070
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
1071
 
                               _("security label driver mismatch: "
1072
 
                                 "'%s' model configured for domain, but "
1073
 
                                 "hypervisor driver is '%s'."),
1074
 
                               secdef->model, virSecurityManagerGetModel(mgr));
1075
 
        if (security_getenforce() == 1)
1076
 
            return -1;
1077
 
    }
1078
 
 
1079
 
    if (setexeccon(secdef->label) == -1) {
1080
 
        virReportSystemError(errno,
1081
 
                             _("unable to set security context '%s'"),
1082
 
                             secdef->label);
1083
 
        if (security_getenforce() == 1)
1084
 
            return -1;
1085
 
    }
1086
 
 
1087
 
    return 0;
1088
 
}
1089
 
 
1090
 
static int
1091
 
SELinuxSetSecurityDaemonSocketLabel(virSecurityManagerPtr mgr,
1092
 
                                    virDomainObjPtr vm)
1093
 
{
1094
 
    /* TODO: verify DOI */
1095
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
1096
 
    context_t execcon = NULL;
1097
 
    context_t proccon = NULL;
1098
 
    security_context_t scon = NULL;
1099
 
    int rc = -1;
1100
 
 
1101
 
    if (vm->def->seclabel.label == NULL)
1102
 
        return 0;
1103
 
 
1104
 
    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
1105
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
1106
 
                               _("security label driver mismatch: "
1107
 
                                 "'%s' model configured for domain, but "
1108
 
                                 "hypervisor driver is '%s'."),
1109
 
                               secdef->model, virSecurityManagerGetModel(mgr));
1110
 
        goto done;
1111
 
    }
1112
 
 
1113
 
    if ( !(execcon = context_new(secdef->label)) ) {
1114
 
        virReportSystemError(errno,
1115
 
                             _("unable to allocate socket security context '%s'"),
1116
 
                             secdef->label);
1117
 
        goto done;
1118
 
    }
1119
 
 
1120
 
    if (getcon(&scon) == -1) {
1121
 
        virReportSystemError(errno,
1122
 
                             _("unable to get current process context '%s'"),
1123
 
                             secdef->label);
1124
 
        goto done;
1125
 
    }
1126
 
 
1127
 
    if ( !(proccon = context_new(scon)) ) {
1128
 
        virReportSystemError(errno,
1129
 
                             _("unable to set socket security context '%s'"),
1130
 
                             secdef->label);
1131
 
        goto done;
1132
 
    }
1133
 
 
1134
 
    if (context_range_set(proccon, context_range_get(execcon)) == -1) {
1135
 
        virReportSystemError(errno,
1136
 
                             _("unable to set socket security context range '%s'"),
1137
 
                             secdef->label);
1138
 
        goto done;
1139
 
    }
1140
 
 
1141
 
    VIR_DEBUG("Setting VM %s socket context %s",
1142
 
              vm->def->name, context_str(proccon));
1143
 
    if (setsockcreatecon(context_str(proccon)) == -1) {
1144
 
        virReportSystemError(errno,
1145
 
                             _("unable to set socket security context '%s'"),
1146
 
                             context_str(proccon));
1147
 
        goto done;
1148
 
    }
1149
 
 
1150
 
    rc = 0;
1151
 
done:
1152
 
 
1153
 
    if (security_getenforce() != 1)
1154
 
        rc = 0;
1155
 
    if (execcon) context_free(execcon);
1156
 
    if (proccon) context_free(proccon);
1157
 
    freecon(scon);
1158
 
    return rc;
1159
 
}
1160
 
 
1161
 
static int
1162
 
SELinuxSetSecuritySocketLabel(virSecurityManagerPtr mgr,
1163
 
                              virDomainObjPtr vm)
1164
 
{
1165
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
1166
 
    int rc = -1;
1167
 
 
1168
 
    if (secdef->label == NULL)
1169
 
        return 0;
1170
 
 
1171
 
    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
1172
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
1173
 
                               _("security label driver mismatch: "
1174
 
                                 "'%s' model configured for domain, but "
1175
 
                                 "hypervisor driver is '%s'."),
1176
 
                               secdef->model, virSecurityManagerGetModel(mgr));
1177
 
        goto done;
1178
 
    }
1179
 
 
1180
 
    VIR_DEBUG("Setting VM %s socket context %s",
1181
 
              vm->def->name, secdef->label);
1182
 
    if (setsockcreatecon(secdef->label) == -1) {
1183
 
        virReportSystemError(errno,
1184
 
                             _("unable to set socket security context '%s'"),
1185
 
                             secdef->label);
1186
 
        goto done;
1187
 
    }
1188
 
 
1189
 
    rc = 0;
1190
 
 
1191
 
done:
1192
 
    if (security_getenforce() != 1)
1193
 
        rc = 0;
1194
 
 
1195
 
    return rc;
1196
 
}
1197
 
 
1198
 
static int
1199
 
SELinuxClearSecuritySocketLabel(virSecurityManagerPtr mgr,
1200
 
                                virDomainObjPtr vm)
1201
 
{
1202
 
    /* TODO: verify DOI */
1203
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
1204
 
 
1205
 
    if (vm->def->seclabel.label == NULL)
1206
 
        return 0;
1207
 
 
1208
 
    if (!STREQ(virSecurityManagerGetModel(mgr), secdef->model)) {
1209
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
1210
 
                               _("security label driver mismatch: "
1211
 
                                 "'%s' model configured for domain, but "
1212
 
                                 "hypervisor driver is '%s'."),
1213
 
                               secdef->model, virSecurityManagerGetModel(mgr));
1214
 
        if (security_getenforce() == 1)
1215
 
            return -1;
1216
 
    }
1217
 
 
1218
 
    if (setsockcreatecon(NULL) == -1) {
1219
 
        virReportSystemError(errno,
1220
 
                             _("unable to clear socket security context '%s'"),
1221
 
                             secdef->label);
1222
 
        if (security_getenforce() == 1)
1223
 
            return -1;
1224
 
    }
1225
 
    return 0;
1226
 
}
1227
 
 
1228
 
 
1229
 
static int
1230
 
SELinuxSetSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
1231
 
                                  virDomainChrDefPtr dev,
1232
 
                                  void *opaque)
1233
 
{
1234
 
    virDomainObjPtr vm = opaque;
1235
 
 
1236
 
    /* This is taken care of by processing of def->serials */
1237
 
    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
1238
 
        dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
1239
 
        return 0;
1240
 
 
1241
 
    return SELinuxSetSecurityChardevLabel(vm, &dev->source);
1242
 
}
1243
 
 
1244
 
 
1245
 
static int
1246
 
SELinuxSetSecuritySmartcardCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
1247
 
                                    virDomainSmartcardDefPtr dev,
1248
 
                                    void *opaque)
1249
 
{
1250
 
    virDomainObjPtr vm = opaque;
1251
 
    const char *database;
1252
 
 
1253
 
    switch (dev->type) {
1254
 
    case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
1255
 
        break;
1256
 
 
1257
 
    case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
1258
 
        database = dev->data.cert.database;
1259
 
        if (!database)
1260
 
            database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
1261
 
        return SELinuxSetFilecon(database, default_content_context);
1262
 
 
1263
 
    case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
1264
 
        return SELinuxSetSecurityChardevLabel(vm, &dev->data.passthru);
1265
 
 
1266
 
    default:
1267
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
1268
 
                               _("unknown smartcard type %d"),
1269
 
                               dev->type);
1270
 
        return -1;
1271
 
    }
1272
 
 
1273
 
    return 0;
1274
 
}
1275
 
 
1276
 
 
1277
 
static int
1278
 
SELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
1279
 
                           virDomainObjPtr vm,
1280
 
                           const char *stdin_path)
1281
 
{
1282
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
1283
 
    int i;
1284
 
 
1285
 
    if (secdef->norelabel)
1286
 
        return 0;
1287
 
 
1288
 
    for (i = 0 ; i < vm->def->ndisks ; i++) {
1289
 
        /* XXX fixme - we need to recursively label the entire tree :-( */
1290
 
        if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR) {
1291
 
            VIR_WARN("Unable to relabel directory tree %s for disk %s",
1292
 
                     vm->def->disks[i]->src, vm->def->disks[i]->dst);
1293
 
            continue;
1294
 
        }
1295
 
        if (SELinuxSetSecurityImageLabel(mgr,
1296
 
                                         vm, vm->def->disks[i]) < 0)
1297
 
            return -1;
1298
 
    }
1299
 
    /* XXX fixme process  vm->def->fss if relabel == true */
1300
 
 
1301
 
    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
1302
 
        if (SELinuxSetSecurityHostdevLabel(mgr,
1303
 
                                           vm,
1304
 
                                           vm->def->hostdevs[i]) < 0)
1305
 
            return -1;
1306
 
    }
1307
 
 
1308
 
    if (virDomainChrDefForeach(vm->def,
1309
 
                               true,
1310
 
                               SELinuxSetSecurityChardevCallback,
1311
 
                               vm) < 0)
1312
 
        return -1;
1313
 
 
1314
 
    if (virDomainSmartcardDefForeach(vm->def,
1315
 
                                     true,
1316
 
                                     SELinuxSetSecuritySmartcardCallback,
1317
 
                                     vm) < 0)
1318
 
        return -1;
1319
 
 
1320
 
    if (vm->def->os.kernel &&
1321
 
        SELinuxSetFilecon(vm->def->os.kernel, default_content_context) < 0)
1322
 
        return -1;
1323
 
 
1324
 
    if (vm->def->os.initrd &&
1325
 
        SELinuxSetFilecon(vm->def->os.initrd, default_content_context) < 0)
1326
 
        return -1;
1327
 
 
1328
 
    if (stdin_path) {
1329
 
        if (SELinuxSetFilecon(stdin_path, default_content_context) < 0 &&
1330
 
            virStorageFileIsSharedFSType(stdin_path,
1331
 
                                         VIR_STORAGE_FILE_SHFS_NFS) != 1)
1332
 
            return -1;
1333
 
    }
1334
 
 
1335
 
    return 0;
1336
 
}
1337
 
 
1338
 
static int
1339
 
SELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
1340
 
                       virDomainObjPtr vm,
1341
 
                       int fd)
1342
 
{
1343
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
1344
 
 
1345
 
    if (secdef->imagelabel == NULL)
1346
 
        return 0;
1347
 
 
1348
 
    return SELinuxFSetFilecon(fd, secdef->imagelabel);
1349
 
}
1350
 
 
1351
 
virSecurityDriver virSecurityDriverSELinux = {
1352
 
    0,
1353
 
    SECURITY_SELINUX_NAME,
1354
 
    SELinuxSecurityDriverProbe,
1355
 
    SELinuxSecurityDriverOpen,
1356
 
    SELinuxSecurityDriverClose,
1357
 
 
1358
 
    SELinuxSecurityGetModel,
1359
 
    SELinuxSecurityGetDOI,
1360
 
 
1361
 
    SELinuxSecurityVerify,
1362
 
 
1363
 
    SELinuxSetSecurityImageLabel,
1364
 
    SELinuxRestoreSecurityImageLabel,
1365
 
 
1366
 
    SELinuxSetSecurityDaemonSocketLabel,
1367
 
    SELinuxSetSecuritySocketLabel,
1368
 
    SELinuxClearSecuritySocketLabel,
1369
 
 
1370
 
    SELinuxGenSecurityLabel,
1371
 
    SELinuxReserveSecurityLabel,
1372
 
    SELinuxReleaseSecurityLabel,
1373
 
 
1374
 
    SELinuxGetSecurityProcessLabel,
1375
 
    SELinuxSetSecurityProcessLabel,
1376
 
 
1377
 
    SELinuxSetSecurityAllLabel,
1378
 
    SELinuxRestoreSecurityAllLabel,
1379
 
 
1380
 
    SELinuxSetSecurityHostdevLabel,
1381
 
    SELinuxRestoreSecurityHostdevLabel,
1382
 
 
1383
 
    SELinuxSetSavedStateLabel,
1384
 
    SELinuxRestoreSavedStateLabel,
1385
 
 
1386
 
    SELinuxSetImageFDLabel,
1387
 
};