~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_apparmor.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
 
 * AppArmor security driver for libvirt
3
 
 * Copyright (C) 2011 Red Hat, Inc.
4
 
 * Copyright (C) 2009-2010 Canonical Ltd.
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2.1 of the License, or (at your option) any later version.
10
 
 *
11
 
 * Author:
12
 
 *   Jamie Strandboge <jamie@canonical.com>
13
 
 *   Based on security_selinux.c by James Morris <jmorris@namei.org>
14
 
 *
15
 
 * AppArmor security driver.
16
 
 */
17
 
 
18
 
#include <config.h>
19
 
 
20
 
#include <sys/types.h>
21
 
#include <sys/stat.h>
22
 
#include <fcntl.h>
23
 
#include <sys/apparmor.h>
24
 
#include <errno.h>
25
 
#include <unistd.h>
26
 
#include <wait.h>
27
 
 
28
 
#include "internal.h"
29
 
 
30
 
#include "security_apparmor.h"
31
 
#include "util.h"
32
 
#include "memory.h"
33
 
#include "virterror_internal.h"
34
 
#include "datatypes.h"
35
 
#include "uuid.h"
36
 
#include "pci.h"
37
 
#include "hostusb.h"
38
 
#include "virfile.h"
39
 
#include "configmake.h"
40
 
#include "command.h"
41
 
#include "logging.h"
42
 
 
43
 
#define VIR_FROM_THIS VIR_FROM_SECURITY
44
 
#define SECURITY_APPARMOR_VOID_DOI      "0"
45
 
#define SECURITY_APPARMOR_NAME          "apparmor"
46
 
#define VIRT_AA_HELPER LIBEXECDIR "/virt-aa-helper"
47
 
 
48
 
/* Data structure to pass to *FileIterate so we have everything we need */
49
 
struct SDPDOP {
50
 
    virSecurityManagerPtr mgr;
51
 
    virDomainObjPtr vm;
52
 
};
53
 
 
54
 
/*
55
 
 * profile_status returns '-1' on error, '0' if loaded
56
 
 *
57
 
 * If check_enforcing is set to '1', then returns '-1' on error, '0' if
58
 
 * loaded in complain mode, and '1' if loaded in enforcing mode.
59
 
 */
60
 
static int
61
 
profile_status(const char *str, const int check_enforcing)
62
 
{
63
 
    char *content = NULL;
64
 
    char *tmp = NULL;
65
 
    char *etmp = NULL;
66
 
    int rc = -1;
67
 
 
68
 
    /* create string that is '<str> \0' for accurate matching */
69
 
    if (virAsprintf(&tmp, "%s ", str) == -1) {
70
 
        virReportOOMError();
71
 
        return rc;
72
 
    }
73
 
 
74
 
    if (check_enforcing != 0) {
75
 
        /* create string that is '<str> (enforce)\0' for accurate matching */
76
 
        if (virAsprintf(&etmp, "%s (enforce)", str) == -1) {
77
 
            VIR_FREE(tmp);
78
 
            virReportOOMError();
79
 
            return rc;
80
 
        }
81
 
    }
82
 
 
83
 
    if (virFileReadAll(APPARMOR_PROFILES_PATH, MAX_FILE_LEN, &content) < 0) {
84
 
        virReportSystemError(errno,
85
 
                             _("Failed to read AppArmor profiles list "
86
 
                             "\'%s\'"), APPARMOR_PROFILES_PATH);
87
 
        goto clean;
88
 
    }
89
 
 
90
 
    if (strstr(content, tmp) != NULL)
91
 
        rc = 0;
92
 
    if (check_enforcing != 0) {
93
 
        if (rc == 0 && strstr(content, etmp) != NULL)
94
 
            rc = 1;                 /* return '1' if loaded and enforcing */
95
 
    }
96
 
 
97
 
    VIR_FREE(content);
98
 
  clean:
99
 
    VIR_FREE(tmp);
100
 
    VIR_FREE(etmp);
101
 
 
102
 
    return rc;
103
 
}
104
 
 
105
 
static int
106
 
profile_loaded(const char *str)
107
 
{
108
 
    return profile_status(str, 0);
109
 
}
110
 
 
111
 
/*
112
 
 * profile_status_file returns '-1' on error, '0' if file on disk is in
113
 
 * complain mode and '1' if file on disk is in enforcing mode
114
 
 */
115
 
static int
116
 
profile_status_file(const char *str)
117
 
{
118
 
    char *profile = NULL;
119
 
    char *content = NULL;
120
 
    char *tmp = NULL;
121
 
    int rc = -1;
122
 
    int len;
123
 
 
124
 
    if (virAsprintf(&profile, "%s/%s", APPARMOR_DIR "/libvirt", str) == -1) {
125
 
        virReportOOMError();
126
 
        return rc;
127
 
    }
128
 
 
129
 
    if (!virFileExists(profile))
130
 
        goto failed;
131
 
 
132
 
    if ((len = virFileReadAll(profile, MAX_FILE_LEN, &content)) < 0) {
133
 
        virReportSystemError(errno,
134
 
                             _("Failed to read \'%s\'"), profile);
135
 
        goto failed;
136
 
    }
137
 
 
138
 
    /* create string that is ' <str> flags=(complain)\0' */
139
 
    if (virAsprintf(&tmp, " %s flags=(complain)", str) == -1) {
140
 
        virReportOOMError();
141
 
        goto failed;
142
 
    }
143
 
 
144
 
    if (strstr(content, tmp) != NULL)
145
 
        rc = 0;
146
 
    else
147
 
        rc = 1;
148
 
 
149
 
  failed:
150
 
    VIR_FREE(tmp);
151
 
    VIR_FREE(profile);
152
 
    VIR_FREE(content);
153
 
 
154
 
    return rc;
155
 
}
156
 
 
157
 
/*
158
 
 * load (add) a profile. Will create one if necessary
159
 
 */
160
 
static int
161
 
load_profile(virSecurityManagerPtr mgr,
162
 
             const char *profile,
163
 
             virDomainObjPtr vm,
164
 
             const char *fn,
165
 
             bool append)
166
 
{
167
 
    int rc = -1;
168
 
    bool create = true;
169
 
    char *xml = NULL;
170
 
    virCommandPtr cmd;
171
 
    const char *probe = virSecurityManagerGetAllowDiskFormatProbing(mgr)
172
 
        ? "1" : "0";
173
 
 
174
 
    xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
175
 
    if (!xml)
176
 
        goto clean;
177
 
 
178
 
    if (profile_status_file(profile) >= 0)
179
 
        create = false;
180
 
 
181
 
    cmd = virCommandNewArgList(VIRT_AA_HELPER, "-p", probe,
182
 
                               create ? "-c" : "-r",
183
 
                               "-u", profile, NULL);
184
 
    if (!create && fn) {
185
 
        if (append) {
186
 
            virCommandAddArgList(cmd, "-F", fn, NULL);
187
 
        } else {
188
 
            virCommandAddArgList(cmd, "-f", fn, NULL);
189
 
        }
190
 
    }
191
 
 
192
 
    virCommandSetInputBuffer(cmd, xml);
193
 
    rc = virCommandRun(cmd, NULL);
194
 
 
195
 
  clean:
196
 
    VIR_FREE(xml);
197
 
 
198
 
    return rc;
199
 
}
200
 
 
201
 
static int
202
 
remove_profile(const char *profile)
203
 
{
204
 
    int rc = -1;
205
 
    const char * const argv[] = {
206
 
        VIRT_AA_HELPER, "-R", "-u", profile, NULL
207
 
    };
208
 
 
209
 
    if (virRun(argv, NULL) == 0)
210
 
        rc = 0;
211
 
 
212
 
    return rc;
213
 
}
214
 
 
215
 
static char *
216
 
get_profile_name(virDomainObjPtr vm)
217
 
{
218
 
    char uuidstr[VIR_UUID_STRING_BUFLEN];
219
 
    char *name = NULL;
220
 
 
221
 
    virUUIDFormat(vm->def->uuid, uuidstr);
222
 
    if (virAsprintf(&name, "%s%s", AA_PREFIX, uuidstr) < 0) {
223
 
        virReportOOMError();
224
 
        return NULL;
225
 
    }
226
 
 
227
 
    return name;
228
 
}
229
 
 
230
 
/* returns -1 on error or profile for libvirtd is unconfined, 0 if complain
231
 
 * mode and 1 if enforcing. This is required because at present you cannot
232
 
 * aa_change_profile() from a process that is unconfined.
233
 
 */
234
 
static int
235
 
use_apparmor(void)
236
 
{
237
 
    int rc = -1;
238
 
    char *libvirt_daemon = NULL;
239
 
 
240
 
    if (virFileResolveLink("/proc/self/exe", &libvirt_daemon) < 0) {
241
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
242
 
                               "%s", _("could not find libvirtd"));
243
 
        return rc;
244
 
    }
245
 
 
246
 
    if (access(APPARMOR_PROFILES_PATH, R_OK) != 0)
247
 
        goto cleanup;
248
 
 
249
 
    rc = profile_status(libvirt_daemon, 1);
250
 
 
251
 
cleanup:
252
 
    VIR_FREE(libvirt_daemon);
253
 
    return rc;
254
 
}
255
 
 
256
 
/* reload the profile, adding read/write file specified by fn if it is not
257
 
 * NULL.
258
 
 */
259
 
static int
260
 
reload_profile(virSecurityManagerPtr mgr,
261
 
               virDomainObjPtr vm,
262
 
               const char *fn,
263
 
               bool append)
264
 
{
265
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
266
 
    int rc = -1;
267
 
    char *profile_name = NULL;
268
 
 
269
 
    if (secdef->norelabel)
270
 
        return 0;
271
 
 
272
 
    if ((profile_name = get_profile_name(vm)) == NULL)
273
 
        return rc;
274
 
 
275
 
    /* Update the profile only if it is loaded */
276
 
    if (profile_loaded(secdef->imagelabel) >= 0) {
277
 
        if (load_profile(mgr, secdef->imagelabel, vm, fn, append) < 0) {
278
 
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
279
 
                                   _("cannot update AppArmor profile "
280
 
                                     "\'%s\'"),
281
 
                                   secdef->imagelabel);
282
 
            goto clean;
283
 
        }
284
 
    }
285
 
 
286
 
    rc = 0;
287
 
  clean:
288
 
    VIR_FREE(profile_name);
289
 
 
290
 
    return rc;
291
 
}
292
 
 
293
 
static int
294
 
AppArmorSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
295
 
                           const char *file, void *opaque)
296
 
{
297
 
    struct SDPDOP *ptr = opaque;
298
 
    virDomainObjPtr vm = ptr->vm;
299
 
 
300
 
    if (reload_profile(ptr->mgr, vm, file, true) < 0) {
301
 
        const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
302
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
303
 
                               _("cannot update AppArmor profile "
304
 
                                 "\'%s\'"),
305
 
                               secdef->imagelabel);
306
 
        return -1;
307
 
    }
308
 
    return 0;
309
 
}
310
 
 
311
 
static int
312
 
AppArmorSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
313
 
                           const char *file, void *opaque)
314
 
{
315
 
    struct SDPDOP *ptr = opaque;
316
 
    virDomainObjPtr vm = ptr->vm;
317
 
 
318
 
    if (reload_profile(ptr->mgr, vm, file, true) < 0) {
319
 
        const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
320
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
321
 
                               _("cannot update AppArmor profile "
322
 
                                 "\'%s\'"),
323
 
                               secdef->imagelabel);
324
 
        return -1;
325
 
    }
326
 
    return 0;
327
 
}
328
 
 
329
 
/* Called on libvirtd startup to see if AppArmor is available */
330
 
static int
331
 
AppArmorSecurityManagerProbe(void)
332
 
{
333
 
    char *template = NULL;
334
 
    int rc = SECURITY_DRIVER_DISABLE;
335
 
 
336
 
    if (use_apparmor() < 0)
337
 
        return rc;
338
 
 
339
 
    /* see if template file exists */
340
 
    if (virAsprintf(&template, "%s/TEMPLATE",
341
 
                               APPARMOR_DIR "/libvirt") == -1) {
342
 
        virReportOOMError();
343
 
        return rc;
344
 
    }
345
 
 
346
 
    if (!virFileExists(template)) {
347
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
348
 
                               _("template \'%s\' does not exist"), template);
349
 
        goto clean;
350
 
    }
351
 
    rc = SECURITY_DRIVER_ENABLE;
352
 
 
353
 
  clean:
354
 
    VIR_FREE(template);
355
 
 
356
 
    return rc;
357
 
}
358
 
 
359
 
/* Security driver initialization. DOI is for 'Domain of Interpretation' and is
360
 
 * currently not used.
361
 
 */
362
 
static int
363
 
AppArmorSecurityManagerOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
364
 
{
365
 
    return 0;
366
 
}
367
 
 
368
 
static int
369
 
AppArmorSecurityManagerClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
370
 
{
371
 
    return 0;
372
 
}
373
 
 
374
 
static const char *
375
 
AppArmorSecurityManagerGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
376
 
{
377
 
    return SECURITY_APPARMOR_NAME;
378
 
}
379
 
 
380
 
static const char *
381
 
AppArmorSecurityManagerGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
382
 
{
383
 
    return SECURITY_APPARMOR_VOID_DOI;
384
 
}
385
 
 
386
 
 
387
 
/* Currently called in qemudStartVMDaemon to setup a 'label'. We look for and
388
 
 * use a profile based on the UUID, otherwise create one based on a template.
389
 
 * Keep in mind that this is called on 'start' with RestoreSecurityLabel being
390
 
 * called on shutdown.
391
 
*/
392
 
static int
393
 
AppArmorGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
394
 
                         virDomainObjPtr vm)
395
 
{
396
 
    int rc = -1;
397
 
    char *profile_name = NULL;
398
 
 
399
 
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
400
 
        return 0;
401
 
 
402
 
    if (vm->def->seclabel.baselabel) {
403
 
        virSecurityReportError(VIR_ERR_CONFIG_UNSUPPORTED,
404
 
                               "%s", _("Cannot set a base label with AppArmour"));
405
 
        return rc;
406
 
    }
407
 
 
408
 
    if ((vm->def->seclabel.label) ||
409
 
        (vm->def->seclabel.model) || (vm->def->seclabel.imagelabel)) {
410
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
411
 
                               "%s",
412
 
                               _("security label already defined for VM"));
413
 
        return rc;
414
 
    }
415
 
 
416
 
    if ((profile_name = get_profile_name(vm)) == NULL)
417
 
        return rc;
418
 
 
419
 
    vm->def->seclabel.label = strndup(profile_name, strlen(profile_name));
420
 
    if (!vm->def->seclabel.label) {
421
 
        virReportOOMError();
422
 
        goto clean;
423
 
    }
424
 
 
425
 
    /* set imagelabel the same as label (but we won't use it) */
426
 
    vm->def->seclabel.imagelabel = strndup(profile_name,
427
 
                                           strlen(profile_name));
428
 
    if (!vm->def->seclabel.imagelabel) {
429
 
        virReportOOMError();
430
 
        goto err;
431
 
    }
432
 
 
433
 
    vm->def->seclabel.model = strdup(SECURITY_APPARMOR_NAME);
434
 
    if (!vm->def->seclabel.model) {
435
 
        virReportOOMError();
436
 
        goto err;
437
 
    }
438
 
 
439
 
    /* Now that we have a label, load the profile into the kernel. */
440
 
    if (load_profile(mgr, vm->def->seclabel.label, vm, NULL, false) < 0) {
441
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
442
 
                               _("cannot load AppArmor profile "
443
 
                               "\'%s\'"), vm->def->seclabel.label);
444
 
        goto err;
445
 
    }
446
 
 
447
 
    rc = 0;
448
 
    goto clean;
449
 
 
450
 
  err:
451
 
    VIR_FREE(vm->def->seclabel.label);
452
 
    VIR_FREE(vm->def->seclabel.imagelabel);
453
 
    VIR_FREE(vm->def->seclabel.model);
454
 
 
455
 
  clean:
456
 
    VIR_FREE(profile_name);
457
 
 
458
 
    return rc;
459
 
}
460
 
 
461
 
static int
462
 
AppArmorSetSecurityAllLabel(virSecurityManagerPtr mgr,
463
 
                            virDomainObjPtr vm, const char *stdin_path)
464
 
{
465
 
    if (vm->def->seclabel.norelabel)
466
 
        return 0;
467
 
 
468
 
    /* Reload the profile if stdin_path is specified. Note that
469
 
       GenSecurityLabel() will have already been run. */
470
 
    if (stdin_path)
471
 
        return reload_profile(mgr, vm, stdin_path, true);
472
 
 
473
 
    return 0;
474
 
}
475
 
 
476
 
/* Seen with 'virsh dominfo <vm>'. This function only called if the VM is
477
 
 * running.
478
 
 */
479
 
static int
480
 
AppArmorGetSecurityProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
481
 
                                virDomainObjPtr vm,
482
 
                                virSecurityLabelPtr sec)
483
 
{
484
 
    int rc = -1;
485
 
    char *profile_name = NULL;
486
 
 
487
 
    if ((profile_name = get_profile_name(vm)) == NULL)
488
 
        return rc;
489
 
 
490
 
    if (virStrcpy(sec->label, profile_name,
491
 
        VIR_SECURITY_LABEL_BUFLEN) == NULL) {
492
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
493
 
                               "%s", _("error copying profile name"));
494
 
        goto clean;
495
 
    }
496
 
 
497
 
    if ((sec->enforcing = profile_status(profile_name, 1)) < 0) {
498
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
499
 
                               "%s", _("error calling profile_status()"));
500
 
        goto clean;
501
 
    }
502
 
    rc = 0;
503
 
 
504
 
  clean:
505
 
    VIR_FREE(profile_name);
506
 
 
507
 
    return rc;
508
 
}
509
 
 
510
 
/* Called on VM shutdown and destroy. See AppArmorGenSecurityLabel (above) for
511
 
 * more details. Currently called via qemudShutdownVMDaemon.
512
 
 */
513
 
static int
514
 
AppArmorReleaseSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
515
 
                             virDomainObjPtr vm)
516
 
{
517
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
518
 
 
519
 
    VIR_FREE(secdef->model);
520
 
    VIR_FREE(secdef->label);
521
 
    VIR_FREE(secdef->imagelabel);
522
 
 
523
 
    return 0;
524
 
}
525
 
 
526
 
 
527
 
static int
528
 
AppArmorRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
529
 
                                virDomainObjPtr vm,
530
 
                                int migrated ATTRIBUTE_UNUSED)
531
 
{
532
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
533
 
    int rc = 0;
534
 
 
535
 
    if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
536
 
        if ((rc = remove_profile(secdef->label)) != 0) {
537
 
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
538
 
                                   _("could not remove profile for \'%s\'"),
539
 
                                   secdef->label);
540
 
        }
541
 
    }
542
 
    return rc;
543
 
}
544
 
 
545
 
/* Called via virCommand hook. Output goes to
546
 
 * LOCALSTATEDIR/log/libvirt/qemu/<vm name>.log
547
 
 */
548
 
static int
549
 
AppArmorSetSecurityProcessLabel(virSecurityManagerPtr mgr, virDomainObjPtr vm)
550
 
{
551
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
552
 
    int rc = -1;
553
 
    char *profile_name = NULL;
554
 
 
555
 
    if ((profile_name = get_profile_name(vm)) == NULL)
556
 
        return rc;
557
 
 
558
 
    if (STRNEQ(virSecurityManagerGetModel(mgr), secdef->model)) {
559
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
560
 
                               _("security label driver mismatch: "
561
 
                               "\'%s\' model configured for domain, but "
562
 
                               "hypervisor driver is \'%s\'."),
563
 
                               secdef->model, virSecurityManagerGetModel(mgr));
564
 
        if (use_apparmor() > 0)
565
 
            goto clean;
566
 
    }
567
 
 
568
 
    if (aa_change_profile(profile_name) < 0) {
569
 
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s",
570
 
                               _("error calling aa_change_profile()"));
571
 
        goto clean;
572
 
    }
573
 
    rc = 0;
574
 
 
575
 
  clean:
576
 
    VIR_FREE(profile_name);
577
 
 
578
 
    return rc;
579
 
}
580
 
 
581
 
static int
582
 
AppArmorSetSecurityDaemonSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
583
 
                                     virDomainObjPtr vm ATTRIBUTE_UNUSED)
584
 
{
585
 
    return 0;
586
 
}
587
 
 
588
 
static int
589
 
AppArmorSetSecuritySocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
590
 
                               virDomainObjPtr vm ATTRIBUTE_UNUSED)
591
 
{
592
 
    return 0;
593
 
}
594
 
 
595
 
static int
596
 
AppArmorClearSecuritySocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
597
 
                                 virDomainObjPtr vm ATTRIBUTE_UNUSED)
598
 
{
599
 
    return 0;
600
 
}
601
 
 
602
 
 
603
 
/* Called when hotplugging */
604
 
static int
605
 
AppArmorRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
606
 
                                  virDomainObjPtr vm,
607
 
                                  virDomainDiskDefPtr disk ATTRIBUTE_UNUSED)
608
 
{
609
 
    return reload_profile(mgr, vm, NULL, false);
610
 
}
611
 
 
612
 
/* Called when hotplugging */
613
 
static int
614
 
AppArmorSetSecurityImageLabel(virSecurityManagerPtr mgr,
615
 
                              virDomainObjPtr vm, virDomainDiskDefPtr disk)
616
 
{
617
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
618
 
    int rc = -1;
619
 
    char *profile_name;
620
 
 
621
 
    if (secdef->norelabel)
622
 
        return 0;
623
 
 
624
 
    if (!disk->src || disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK)
625
 
        return 0;
626
 
 
627
 
    if (secdef->imagelabel) {
628
 
        /* if the device doesn't exist, error out */
629
 
        if (!virFileExists(disk->src)) {
630
 
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
631
 
                                   _("\'%s\' does not exist"), disk->src);
632
 
            return rc;
633
 
        }
634
 
 
635
 
        if ((profile_name = get_profile_name(vm)) == NULL)
636
 
            return rc;
637
 
 
638
 
        /* update the profile only if it is loaded */
639
 
        if (profile_loaded(secdef->imagelabel) >= 0) {
640
 
            if (load_profile(mgr, secdef->imagelabel, vm, disk->src,
641
 
                             false) < 0) {
642
 
                virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
643
 
                                     _("cannot update AppArmor profile "
644
 
                                     "\'%s\'"),
645
 
                                     secdef->imagelabel);
646
 
                goto clean;
647
 
            }
648
 
        }
649
 
    }
650
 
    rc = 0;
651
 
 
652
 
  clean:
653
 
    VIR_FREE(profile_name);
654
 
 
655
 
    return rc;
656
 
}
657
 
 
658
 
static int
659
 
AppArmorSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
660
 
                       virDomainDefPtr def)
661
 
{
662
 
    const virSecurityLabelDefPtr secdef = &def->seclabel;
663
 
 
664
 
    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) {
665
 
        if (use_apparmor() < 0 || profile_status(secdef->label, 0) < 0) {
666
 
            virSecurityReportError(VIR_ERR_XML_ERROR,
667
 
                                   _("Invalid security label \'%s\'"),
668
 
                                   secdef->label);
669
 
            return -1;
670
 
        }
671
 
    }
672
 
    return 0;
673
 
}
674
 
 
675
 
static int
676
 
AppArmorReserveSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
677
 
                             virDomainObjPtr vm ATTRIBUTE_UNUSED)
678
 
{
679
 
    /* NOOP. Nothing to reserve with AppArmor */
680
 
    return 0;
681
 
}
682
 
 
683
 
static int
684
 
AppArmorSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
685
 
                                virDomainObjPtr vm,
686
 
                                virDomainHostdevDefPtr dev)
687
 
 
688
 
{
689
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
690
 
    struct SDPDOP *ptr;
691
 
    int ret = -1;
692
 
 
693
 
    if (secdef->norelabel)
694
 
        return 0;
695
 
 
696
 
    if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
697
 
        return 0;
698
 
 
699
 
    if (profile_loaded(secdef->imagelabel) < 0)
700
 
        return 0;
701
 
 
702
 
    if (VIR_ALLOC(ptr) < 0)
703
 
        return -1;
704
 
    ptr->mgr = mgr;
705
 
    ptr->vm = vm;
706
 
 
707
 
    switch (dev->source.subsys.type) {
708
 
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
709
 
        usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
710
 
                                      dev->source.subsys.u.usb.device);
711
 
 
712
 
        if (!usb)
713
 
            goto done;
714
 
 
715
 
        ret = usbDeviceFileIterate(usb, AppArmorSetSecurityUSBLabel, ptr);
716
 
        usbFreeDevice(usb);
717
 
        break;
718
 
    }
719
 
 
720
 
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
721
 
        pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
722
 
                                      dev->source.subsys.u.pci.bus,
723
 
                                      dev->source.subsys.u.pci.slot,
724
 
                                      dev->source.subsys.u.pci.function);
725
 
 
726
 
        if (!pci)
727
 
            goto done;
728
 
 
729
 
        ret = pciDeviceFileIterate(pci, AppArmorSetSecurityPCILabel, ptr);
730
 
        pciFreeDevice(pci);
731
 
        break;
732
 
    }
733
 
 
734
 
    default:
735
 
        ret = 0;
736
 
        break;
737
 
    }
738
 
 
739
 
done:
740
 
    VIR_FREE(ptr);
741
 
    return ret;
742
 
}
743
 
 
744
 
 
745
 
static int
746
 
AppArmorRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
747
 
                                    virDomainObjPtr vm,
748
 
                                    virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)
749
 
 
750
 
{
751
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
752
 
    if (secdef->norelabel)
753
 
        return 0;
754
 
 
755
 
    return reload_profile(mgr, vm, NULL, false);
756
 
}
757
 
 
758
 
static int
759
 
AppArmorSetSavedStateLabel(virSecurityManagerPtr mgr,
760
 
                           virDomainObjPtr vm,
761
 
                           const char *savefile)
762
 
{
763
 
    return reload_profile(mgr, vm, savefile, true);
764
 
}
765
 
 
766
 
 
767
 
static int
768
 
AppArmorRestoreSavedStateLabel(virSecurityManagerPtr mgr,
769
 
                               virDomainObjPtr vm,
770
 
                               const char *savefile ATTRIBUTE_UNUSED)
771
 
{
772
 
    return reload_profile(mgr, vm, NULL, false);
773
 
}
774
 
 
775
 
static int
776
 
AppArmorSetImageFDLabel(virSecurityManagerPtr mgr,
777
 
                        virDomainObjPtr vm,
778
 
                        int fd)
779
 
{
780
 
    int rc = -1;
781
 
    char *proc = NULL;
782
 
    char *fd_path = NULL;
783
 
 
784
 
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
785
 
 
786
 
    if (secdef->imagelabel == NULL)
787
 
        return 0;
788
 
 
789
 
    if (virAsprintf(&proc, "/proc/self/fd/%d", fd) == -1) {
790
 
        virReportOOMError();
791
 
        return rc;
792
 
    }
793
 
 
794
 
    if (virFileResolveLink(proc, &fd_path) < 0) {
795
 
        /* it's a deleted file, presumably.  Ignore? */
796
 
        VIR_WARN("could not find path for descriptor %s, skipping", proc);
797
 
        return 0;
798
 
    }
799
 
 
800
 
    return reload_profile(mgr, vm, fd_path, true);
801
 
}
802
 
 
803
 
virSecurityDriver virAppArmorSecurityDriver = {
804
 
    0,
805
 
    SECURITY_APPARMOR_NAME,
806
 
    AppArmorSecurityManagerProbe,
807
 
    AppArmorSecurityManagerOpen,
808
 
    AppArmorSecurityManagerClose,
809
 
 
810
 
    AppArmorSecurityManagerGetModel,
811
 
    AppArmorSecurityManagerGetDOI,
812
 
 
813
 
    AppArmorSecurityVerify,
814
 
 
815
 
    AppArmorSetSecurityImageLabel,
816
 
    AppArmorRestoreSecurityImageLabel,
817
 
 
818
 
    AppArmorSetSecurityDaemonSocketLabel,
819
 
    AppArmorSetSecuritySocketLabel,
820
 
    AppArmorClearSecuritySocketLabel,
821
 
 
822
 
    AppArmorGenSecurityLabel,
823
 
    AppArmorReserveSecurityLabel,
824
 
    AppArmorReleaseSecurityLabel,
825
 
 
826
 
    AppArmorGetSecurityProcessLabel,
827
 
    AppArmorSetSecurityProcessLabel,
828
 
 
829
 
    AppArmorSetSecurityAllLabel,
830
 
    AppArmorRestoreSecurityAllLabel,
831
 
 
832
 
    AppArmorSetSecurityHostdevLabel,
833
 
    AppArmorRestoreSecurityHostdevLabel,
834
 
 
835
 
    AppArmorSetSavedStateLabel,
836
 
    AppArmorRestoreSavedStateLabel,
837
 
 
838
 
    AppArmorSetImageFDLabel,
839
 
};