security_apparmor.c 18.6 KB
Newer Older
J
Jamie Strandboge 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

/*
 * AppArmor security driver for libvirt
 * Copyright (C) 2009 Canonical Ltd.
 *
 * 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.
 *
 * Author:
 *   Jamie Strandboge <jamie@canonical.com>
 *   Based on security_selinux.c by James Morris <jmorris@namei.org>
 *
 * AppArmor security driver.
 */

#include <config.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/apparmor.h>
#include <errno.h>
#include <unistd.h>
#include <wait.h>
#include <stdbool.h>

#include "internal.h"

#include "security_driver.h"
#include "security_apparmor.h"
#include "util.h"
#include "memory.h"
#include "virterror_internal.h"
#include "datatypes.h"
#include "uuid.h"

#define VIR_FROM_THIS VIR_FROM_SECURITY
#define SECURITY_APPARMOR_VOID_DOI      "0"
#define SECURITY_APPARMOR_NAME          "apparmor"
#define VIRT_AA_HELPER BINDIR "/virt-aa-helper"

/*
 * profile_status returns '-1' on error, '0' if loaded
 *
 * If check_enforcing is set to '1', then returns '-1' on error, '0' if
 * loaded in complain mode, and '1' if loaded in enforcing mode.
 */
static int
profile_status(const char *str, const int check_enforcing)
{
    char *content = NULL;
    char *tmp = NULL;
    char *etmp = NULL;
    int rc = -1;

    /* create string that is '<str> \0' for accurate matching */
59
    if (virAsprintf(&tmp, "%s ", str) == -1) {
60
        virReportOOMError();
J
Jamie Strandboge 已提交
61
        return rc;
62
    }
J
Jamie Strandboge 已提交
63 64 65 66 67

    if (check_enforcing != 0) {
        /* create string that is '<str> (enforce)\0' for accurate matching */
        if (virAsprintf(&etmp, "%s (enforce)", str) == -1) {
            VIR_FREE(tmp);
68
            virReportOOMError();
J
Jamie Strandboge 已提交
69 70 71 72 73
            return rc;
        }
    }

    if (virFileReadAll(APPARMOR_PROFILES_PATH, MAX_FILE_LEN, &content) < 0) {
74
        virReportSystemError(errno,
J
Jamie Strandboge 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
                             _("Failed to read AppArmor profiles list "
                             "\'%s\'"), APPARMOR_PROFILES_PATH);
        goto clean;
    }

    if (strstr(content, tmp) != NULL)
        rc = 0;
    if (check_enforcing != 0) {
        if (rc == 0 && strstr(content, etmp) != NULL)
            rc = 1;                 /* return '1' if loaded and enforcing */
    }

    VIR_FREE(content);
  clean:
    VIR_FREE(tmp);
J
Jamie Strandboge 已提交
90
    VIR_FREE(etmp);
J
Jamie Strandboge 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

    return rc;
}

static int
profile_loaded(const char *str)
{
    return profile_status(str, 0);
}

/*
 * profile_status_file returns '-1' on error, '0' if file on disk is in
 * complain mode and '1' if file on disk is in enforcing mode
 */
static int
profile_status_file(const char *str)
{
J
Jamie Strandboge 已提交
108
    char *profile = NULL;
J
Jamie Strandboge 已提交
109 110 111 112 113
    char *content = NULL;
    char *tmp = NULL;
    int rc = -1;
    int len;

J
Jamie Strandboge 已提交
114
    if (virAsprintf(&profile, "%s/%s", APPARMOR_DIR "/libvirt", str) == -1) {
115
        virReportOOMError();
J
Jamie Strandboge 已提交
116 117 118
        return rc;
    }

J
Jamie Strandboge 已提交
119 120 121
    if (!virFileExists(profile))
        goto failed;

J
Jamie Strandboge 已提交
122
    if ((len = virFileReadAll(profile, MAX_FILE_LEN, &content)) < 0) {
123
        virReportSystemError(errno,
J
Jamie Strandboge 已提交
124
                             _("Failed to read \'%s\'"), profile);
J
Jamie Strandboge 已提交
125
        goto failed;
J
Jamie Strandboge 已提交
126 127 128 129
    }

    /* create string that is ' <str> flags=(complain)\0' */
    if (virAsprintf(&tmp, " %s flags=(complain)", str) == -1) {
130
        virReportOOMError();
J
Jamie Strandboge 已提交
131
        goto failed;
J
Jamie Strandboge 已提交
132 133 134 135 136 137 138
    }

    if (strstr(content, tmp) != NULL)
        rc = 0;
    else
        rc = 1;

J
Jamie Strandboge 已提交
139
  failed:
J
Jamie Strandboge 已提交
140
    VIR_FREE(tmp);
J
Jamie Strandboge 已提交
141
    VIR_FREE(profile);
J
Jamie Strandboge 已提交
142 143 144 145 146 147 148 149 150
    VIR_FREE(content);

    return rc;
}

/*
 * load (add) a profile. Will create one if necessary
 */
static int
151 152
load_profile(virSecurityDriverPtr drv,
             const char *profile, virDomainObjPtr vm,
153
             const char *fn)
J
Jamie Strandboge 已提交
154 155 156 157 158 159 160 161
{
    int rc = -1, status, ret;
    bool create = true;
    char *xml = NULL;
    int pipefd[2];
    pid_t child;

    if (pipe(pipefd) < -1) {
162
        virReportSystemError(errno, "%s", _("unable to create pipe"));
J
Jamie Strandboge 已提交
163 164 165
        return rc;
    }

166
    xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
J
Jamie Strandboge 已提交
167
    if (!xml)
J
Jamie Strandboge 已提交
168
        goto clean;
J
Jamie Strandboge 已提交
169 170 171 172 173 174 175 176

    if (profile_status_file(profile) >= 0)
        create = false;

    if (create) {
        const char *const argv[] = {
            VIRT_AA_HELPER, "-c", "-u", profile, NULL
        };
177
        ret = virExec(argv, NULL, NULL, &child,
178
                      pipefd[0], NULL, NULL, VIR_EXEC_NONE);
179
    } else if (fn) {
J
Jamie Strandboge 已提交
180
        const char *const argv[] = {
181
            VIRT_AA_HELPER, "-r", "-u", profile, "-f", fn, NULL
J
Jamie Strandboge 已提交
182
        };
183
        ret = virExec(argv, NULL, NULL, &child,
184
                      pipefd[0], NULL, NULL, VIR_EXEC_NONE);
J
Jamie Strandboge 已提交
185 186 187 188
    } else {
        const char *const argv[] = {
            VIRT_AA_HELPER, "-r", "-u", profile, NULL
        };
189
        ret = virExec(argv, NULL, NULL, &child,
190
                      pipefd[0], NULL, NULL, VIR_EXEC_NONE);
J
Jamie Strandboge 已提交
191 192 193 194 195 196
    }
    if (ret < 0)
        goto clean;

    /* parent continues here */
    if (safewrite(pipefd[1], xml, strlen(xml)) < 0) {
197
        virReportSystemError(errno, "%s", _("unable to write to pipe"));
J
Jamie Strandboge 已提交
198 199 200 201 202 203 204 205 206 207
        goto clean;
    }
    close(pipefd[1]);
    rc = 0;

  rewait:
    if (waitpid(child, &status, 0) != child) {
        if (errno == EINTR)
            goto rewait;

208
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
                               _("Unexpected exit status from virt-aa-helper "
                               "%d pid %lu"),
                               WEXITSTATUS(status), (unsigned long)child);
        rc = -1;
    }

  clean:
    VIR_FREE(xml);

    if (pipefd[0] > 0)
        close(pipefd[0]);
    if (pipefd[1] > 0)
        close(pipefd[1]);

    return rc;
}

static int
remove_profile(const char *profile)
{
    int rc = -1;
    const char * const argv[] = {
        VIRT_AA_HELPER, "-R", "-u", profile, NULL
    };

234
    if (virRun(argv, NULL) == 0)
J
Jamie Strandboge 已提交
235 236 237 238 239 240
        rc = 0;

    return rc;
}

static char *
241
get_profile_name(virDomainObjPtr vm)
J
Jamie Strandboge 已提交
242 243 244 245 246 247
{
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    char *name = NULL;

    virUUIDFormat(vm->def->uuid, uuidstr);
    if (virAsprintf(&name, "%s%s", AA_PREFIX, uuidstr) < 0) {
248
        virReportOOMError();
J
Jamie Strandboge 已提交
249 250 251 252 253 254 255 256 257 258 259 260 261 262
        return NULL;
    }

    return name;
}

/* returns -1 on error or profile for libvirtd is unconfined, 0 if complain
 * mode and 1 if enforcing. This is required because at present you cannot
 * aa_change_profile() from a process that is unconfined.
 */
static int
use_apparmor(void)
{
    int rc = -1;
263
    char *libvirt_daemon = NULL;
J
Jamie Strandboge 已提交
264

265
    if (virFileResolveLink("/proc/self/exe", &libvirt_daemon) < 0) {
266
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
267 268 269 270 271
                               "%s", _("could not find libvirtd"));
        return rc;
    }

    if (access(APPARMOR_PROFILES_PATH, R_OK) != 0)
272 273 274
        goto cleanup;

    rc = profile_status(libvirt_daemon, 1);
J
Jamie Strandboge 已提交
275

276 277 278
cleanup:
    VIR_FREE(libvirt_daemon);
    return rc;
J
Jamie Strandboge 已提交
279 280
}

281 282 283 284
/* reload the profile, adding read/write file specified by fn if it is not
 * NULL.
 */
static int
285 286
reload_profile(virSecurityDriverPtr drv,
               virDomainObjPtr vm, const char *fn)
287 288 289 290 291 292 293 294 295 296 297 298 299
{
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
    int rc = -1;
    char *profile_name = NULL;

    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
        return 0;

    if ((profile_name = get_profile_name(vm)) == NULL)
        return rc;

    /* Update the profile only if it is loaded */
    if (profile_loaded(secdef->imagelabel) >= 0) {
300
        if (load_profile(drv, secdef->imagelabel, vm, fn) < 0) {
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("cannot update AppArmor profile "
                                     "\'%s\'"),
                                   secdef->imagelabel);
            goto clean;
        }
    }

    rc = 0;
  clean:
    VIR_FREE(profile_name);

    return rc;
}

J
Jamie Strandboge 已提交
316 317 318 319
/* Called on libvirtd startup to see if AppArmor is available */
static int
AppArmorSecurityDriverProbe(void)
{
J
Jamie Strandboge 已提交
320 321
    char *template = NULL;
    int rc = SECURITY_DRIVER_DISABLE;
J
Jamie Strandboge 已提交
322 323

    if (use_apparmor() < 0)
J
Jamie Strandboge 已提交
324
        return rc;
J
Jamie Strandboge 已提交
325 326

    /* see if template file exists */
J
Jamie Strandboge 已提交
327 328
    if (virAsprintf(&template, "%s/TEMPLATE",
                               APPARMOR_DIR "/libvirt") == -1) {
329
        virReportOOMError();
J
Jamie Strandboge 已提交
330
        return rc;
J
Jamie Strandboge 已提交
331 332 333
    }

    if (!virFileExists(template)) {
334
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
335
                               _("template \'%s\' does not exist"), template);
J
Jamie Strandboge 已提交
336
        goto clean;
J
Jamie Strandboge 已提交
337
    }
J
Jamie Strandboge 已提交
338
    rc = SECURITY_DRIVER_ENABLE;
J
Jamie Strandboge 已提交
339

J
Jamie Strandboge 已提交
340 341 342 343
  clean:
    VIR_FREE(template);

    return rc;
J
Jamie Strandboge 已提交
344 345 346 347 348 349
}

/* Security driver initialization. DOI is for 'Domain of Interpretation' and is
 * currently not used.
 */
static int
350
AppArmorSecurityDriverOpen(virSecurityDriverPtr drv)
J
Jamie Strandboge 已提交
351
{
352
    virSecurityDriverSetDOI(drv, SECURITY_APPARMOR_VOID_DOI);
J
Jamie Strandboge 已提交
353 354 355 356 357 358 359 360 361
    return 0;
}

/* Currently called in qemudStartVMDaemon to setup a 'label'. We look for and
 * use a profile based on the UUID, otherwise create one based on a template.
 * Keep in mind that this is called on 'start' with RestoreSecurityLabel being
 * called on shutdown.
*/
static int
362 363
AppArmorGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                         virDomainObjPtr vm)
J
Jamie Strandboge 已提交
364 365 366 367
{
    int rc = -1;
    char *profile_name = NULL;

368 369 370
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
        return 0;

J
Jamie Strandboge 已提交
371 372
    if ((vm->def->seclabel.label) ||
        (vm->def->seclabel.model) || (vm->def->seclabel.imagelabel)) {
373
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
374 375 376 377 378
                               "%s",
                               _("security label already defined for VM"));
        return rc;
    }

379
    if ((profile_name = get_profile_name(vm)) == NULL)
J
Jamie Strandboge 已提交
380 381 382 383
        return rc;

    vm->def->seclabel.label = strndup(profile_name, strlen(profile_name));
    if (!vm->def->seclabel.label) {
384
        virReportOOMError();
J
Jamie Strandboge 已提交
385 386 387 388 389 390 391
        goto clean;
    }

    /* set imagelabel the same as label (but we won't use it) */
    vm->def->seclabel.imagelabel = strndup(profile_name,
                                           strlen(profile_name));
    if (!vm->def->seclabel.imagelabel) {
392
        virReportOOMError();
J
Jamie Strandboge 已提交
393 394 395 396 397
        goto err;
    }

    vm->def->seclabel.model = strdup(SECURITY_APPARMOR_NAME);
    if (!vm->def->seclabel.model) {
398
        virReportOOMError();
J
Jamie Strandboge 已提交
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
        goto err;
    }

    rc = 0;
    goto clean;

  err:
    VIR_FREE(vm->def->seclabel.label);
    VIR_FREE(vm->def->seclabel.imagelabel);
    VIR_FREE(vm->def->seclabel.model);

  clean:
    VIR_FREE(profile_name);

    return rc;
}

416
static int
417 418
AppArmorSetSecurityAllLabel(virSecurityDriverPtr drv,
                            virDomainObjPtr vm, const char *stdin_path)
419 420 421 422 423 424
{
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
        return 0;

    /* if the profile is not already loaded, then load one */
    if (profile_loaded(vm->def->seclabel.label) < 0) {
425
        if (load_profile(drv, vm->def->seclabel.label, vm, stdin_path) < 0) {
426
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
427 428 429 430 431 432 433 434 435
                                   _("cannot generate AppArmor profile "
                                   "\'%s\'"), vm->def->seclabel.label);
            return -1;
        }
    }

    return 0;
}

J
Jamie Strandboge 已提交
436 437 438 439
/* Seen with 'virsh dominfo <vm>'. This function only called if the VM is
 * running.
 */
static int
440 441 442
AppArmorGetSecurityProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                                virDomainObjPtr vm,
                                virSecurityLabelPtr sec)
J
Jamie Strandboge 已提交
443 444 445 446
{
    int rc = -1;
    char *profile_name = NULL;

447
    if ((profile_name = get_profile_name(vm)) == NULL)
J
Jamie Strandboge 已提交
448 449 450 451
        return rc;

    if (virStrcpy(sec->label, profile_name,
        VIR_SECURITY_LABEL_BUFLEN) == NULL) {
452
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
453 454 455 456 457
                               "%s", _("error copying profile name"));
        goto clean;
    }

    if ((sec->enforcing = profile_status(profile_name, 1)) < 0) {
458
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
                               "%s", _("error calling profile_status()"));
        goto clean;
    }
    rc = 0;

  clean:
    VIR_FREE(profile_name);

    return rc;
}

/* Called on VM shutdown and destroy. See AppArmorGenSecurityLabel (above) for
 * more details. Currently called via qemudShutdownVMDaemon.
 */
static int
474 475
AppArmorReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                             virDomainObjPtr vm)
476 477 478 479 480 481 482 483 484 485 486 487
{
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;

    VIR_FREE(secdef->model);
    VIR_FREE(secdef->label);
    VIR_FREE(secdef->imagelabel);

    return 0;
}


static int
488 489
AppArmorRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                                virDomainObjPtr vm,
490
                                int migrated ATTRIBUTE_UNUSED)
J
Jamie Strandboge 已提交
491 492 493 494
{
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
    int rc = 0;

495
    if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
J
Jamie Strandboge 已提交
496
        if ((rc = remove_profile(secdef->label)) != 0) {
497
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
498 499 500 501 502 503 504 505 506 507 508
                                   _("could not remove profile for \'%s\'"),
                                   secdef->label);
        }
    }
    return rc;
}

/* Called via virExecWithHook. Output goes to
 * LOCAL_STATE_DIR/log/libvirt/qemu/<vm name>.log
 */
static int
509
AppArmorSetSecurityProcessLabel(virSecurityDriverPtr drv, virDomainObjPtr vm)
J
Jamie Strandboge 已提交
510 511 512 513 514
{
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
    int rc = -1;
    char *profile_name = NULL;

515
    if ((profile_name = get_profile_name(vm)) == NULL)
J
Jamie Strandboge 已提交
516 517 518
        return rc;

    if (STRNEQ(drv->name, secdef->model)) {
519
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
520 521 522 523 524 525 526 527 528
                               _("security label driver mismatch: "
                               "\'%s\' model configured for domain, but "
                               "hypervisor driver is \'%s\'."),
                               secdef->model, drv->name);
        if (use_apparmor() > 0)
            goto clean;
    }

    if (aa_change_profile(profile_name) < 0) {
529
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s",
J
Jamie Strandboge 已提交
530 531 532 533 534 535 536 537 538 539 540 541 542 543
                               _("error calling aa_change_profile()"));
        goto clean;
    }
    rc = 0;

  clean:
    VIR_FREE(profile_name);

    return rc;
}


/* Called when hotplugging */
static int
544 545
AppArmorRestoreSecurityImageLabel(virSecurityDriverPtr drv,
                                  virDomainObjPtr vm,
J
Jamie Strandboge 已提交
546 547
                                  virDomainDiskDefPtr disk ATTRIBUTE_UNUSED)
{
548
    return reload_profile(drv, vm, NULL);
J
Jamie Strandboge 已提交
549 550 551 552
}

/* Called when hotplugging */
static int
553 554
AppArmorSetSecurityImageLabel(virSecurityDriverPtr drv,
                              virDomainObjPtr vm, virDomainDiskDefPtr disk)
J
Jamie Strandboge 已提交
555 556 557 558 559
{
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
    int rc = -1;
    char *profile_name;

560 561 562
    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
        return 0;

J
Jamie Strandboge 已提交
563 564 565 566 567 568
    if (!disk->src)
        return 0;

    if (secdef->imagelabel) {
        /* if the device doesn't exist, error out */
        if (!virFileExists(disk->src)) {
569
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
570 571 572 573
                                   _("\'%s\' does not exist"), disk->src);
            return rc;
        }

574
        if ((profile_name = get_profile_name(vm)) == NULL)
J
Jamie Strandboge 已提交
575 576 577 578
            return rc;

        /* update the profile only if it is loaded */
        if (profile_loaded(secdef->imagelabel) >= 0) {
579
            if (load_profile(drv, secdef->imagelabel, vm, disk->src) < 0) {
580
                virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
                                     _("cannot update AppArmor profile "
                                     "\'%s\'"),
                                     secdef->imagelabel);
                goto clean;
            }
        }
    }
    rc = 0;

  clean:
    VIR_FREE(profile_name);

    return rc;
}

static int
597
AppArmorSecurityVerify(virDomainDefPtr def)
J
Jamie Strandboge 已提交
598 599 600 601 602
{
    const virSecurityLabelDefPtr secdef = &def->seclabel;

    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) {
        if (use_apparmor() < 0 || profile_status(secdef->label, 0) < 0) {
603
            virSecurityReportError(VIR_ERR_XML_ERROR,
J
Jamie Strandboge 已提交
604 605 606 607 608 609 610 611 612
                                   _("Invalid security label \'%s\'"),
                                   secdef->label);
            return -1;
        }
    }
    return 0;
}

static int
613 614
AppArmorReserveSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                             virDomainObjPtr vm ATTRIBUTE_UNUSED)
J
Jamie Strandboge 已提交
615 616 617 618 619 620
{
    /* NOOP. Nothing to reserve with AppArmor */
    return 0;
}

static int
621 622
AppArmorSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                                virDomainObjPtr vm,
J
Jamie Strandboge 已提交
623 624 625
                                virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)

{
626 627 628 629 630
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;

    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
        return 0;

J
Jamie Strandboge 已提交
631 632 633 634 635
    /* TODO: call load_profile with an update vm->def */
    return 0;
}

static int
636 637
AppArmorRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                                    virDomainObjPtr vm,
J
Jamie Strandboge 已提交
638 639 640
                                    virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)

{
641 642 643 644
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
        return 0;

J
Jamie Strandboge 已提交
645 646 647 648
    /* TODO: call load_profile (needs virDomainObjPtr vm) */
    return 0;
}

649
static int
650 651 652
AppArmorSetSavedStateLabel(virSecurityDriverPtr drv,
                           virDomainObjPtr vm,
                           const char *savefile)
653
{
654
    return reload_profile(drv, vm, savefile);
655 656 657 658
}


static int
659 660
AppArmorRestoreSavedStateLabel(virSecurityDriverPtr drv,
                               virDomainObjPtr vm,
661 662
                               const char *savefile ATTRIBUTE_UNUSED)
{
663
    return reload_profile(drv, vm, NULL);
664 665
}

J
Jamie Strandboge 已提交
666 667 668 669 670 671 672 673 674
virSecurityDriver virAppArmorSecurityDriver = {
    .name = SECURITY_APPARMOR_NAME,
    .probe = AppArmorSecurityDriverProbe,
    .open = AppArmorSecurityDriverOpen,
    .domainSecurityVerify = AppArmorSecurityVerify,
    .domainSetSecurityImageLabel = AppArmorSetSecurityImageLabel,
    .domainRestoreSecurityImageLabel = AppArmorRestoreSecurityImageLabel,
    .domainGenSecurityLabel = AppArmorGenSecurityLabel,
    .domainReserveSecurityLabel = AppArmorReserveSecurityLabel,
675 676 677 678 679
    .domainReleaseSecurityLabel = AppArmorReleaseSecurityLabel,
    .domainGetSecurityProcessLabel = AppArmorGetSecurityProcessLabel,
    .domainSetSecurityProcessLabel = AppArmorSetSecurityProcessLabel,
    .domainRestoreSecurityAllLabel = AppArmorRestoreSecurityAllLabel,
    .domainSetSecurityAllLabel = AppArmorSetSecurityAllLabel,
J
Jamie Strandboge 已提交
680 681
    .domainSetSecurityHostdevLabel = AppArmorSetSecurityHostdevLabel,
    .domainRestoreSecurityHostdevLabel = AppArmorRestoreSecurityHostdevLabel,
682 683
    .domainSetSavedStateLabel = AppArmorSetSavedStateLabel,
    .domainRestoreSavedStateLabel = AppArmorRestoreSavedStateLabel,
J
Jamie Strandboge 已提交
684
};