security_apparmor.c 18.8 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
{
    int rc = -1, status, ret;
    bool create = true;
    char *xml = NULL;
    int pipefd[2];
    pid_t child;
160 161
    const char *probe = virSecurityDriverGetAllowDiskFormatProbing(drv)
        ? "1" : "0";
J
Jamie Strandboge 已提交
162 163

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

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

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

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

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

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

210
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
                               _("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
    };

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

    return rc;
}

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

    virUUIDFormat(vm->def->uuid, uuidstr);
    if (virAsprintf(&name, "%s%s", AA_PREFIX, uuidstr) < 0) {
250
        virReportOOMError();
J
Jamie Strandboge 已提交
251 252 253 254 255 256 257 258 259 260 261 262 263 264
        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;
265
    char *libvirt_daemon = NULL;
J
Jamie Strandboge 已提交
266

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

    if (access(APPARMOR_PROFILES_PATH, R_OK) != 0)
274 275 276
        goto cleanup;

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

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

283 284 285 286
/* reload the profile, adding read/write file specified by fn if it is not
 * NULL.
 */
static int
287 288
reload_profile(virSecurityDriverPtr drv,
               virDomainObjPtr vm, const char *fn)
289 290 291 292 293 294 295 296 297 298 299 300 301
{
    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) {
302
        if (load_profile(drv, secdef->imagelabel, vm, fn) < 0) {
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
            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 已提交
318 319 320 321
/* Called on libvirtd startup to see if AppArmor is available */
static int
AppArmorSecurityDriverProbe(void)
{
J
Jamie Strandboge 已提交
322 323
    char *template = NULL;
    int rc = SECURITY_DRIVER_DISABLE;
J
Jamie Strandboge 已提交
324 325

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

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

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

J
Jamie Strandboge 已提交
342 343 344 345
  clean:
    VIR_FREE(template);

    return rc;
J
Jamie Strandboge 已提交
346 347 348 349 350 351
}

/* Security driver initialization. DOI is for 'Domain of Interpretation' and is
 * currently not used.
 */
static int
352 353
AppArmorSecurityDriverOpen(virSecurityDriverPtr drv,
                           bool allowDiskFormatProbing)
J
Jamie Strandboge 已提交
354
{
355
    virSecurityDriverSetDOI(drv, SECURITY_APPARMOR_VOID_DOI);
356
    virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing);
J
Jamie Strandboge 已提交
357 358 359 360 361 362 363 364 365
    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
366 367
AppArmorGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                         virDomainObjPtr vm)
J
Jamie Strandboge 已提交
368 369 370 371
{
    int rc = -1;
    char *profile_name = NULL;

372 373 374
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
        return 0;

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

383
    if ((profile_name = get_profile_name(vm)) == NULL)
J
Jamie Strandboge 已提交
384 385 386 387
        return rc;

    vm->def->seclabel.label = strndup(profile_name, strlen(profile_name));
    if (!vm->def->seclabel.label) {
388
        virReportOOMError();
J
Jamie Strandboge 已提交
389 390 391 392 393 394 395
        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) {
396
        virReportOOMError();
J
Jamie Strandboge 已提交
397 398 399 400 401
        goto err;
    }

    vm->def->seclabel.model = strdup(SECURITY_APPARMOR_NAME);
    if (!vm->def->seclabel.model) {
402
        virReportOOMError();
J
Jamie Strandboge 已提交
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
        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;
}

420
static int
421 422
AppArmorSetSecurityAllLabel(virSecurityDriverPtr drv,
                            virDomainObjPtr vm, const char *stdin_path)
423 424 425 426 427 428
{
    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) {
429
        if (load_profile(drv, vm->def->seclabel.label, vm, stdin_path) < 0) {
430
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
431 432 433 434 435 436 437 438 439
                                   _("cannot generate AppArmor profile "
                                   "\'%s\'"), vm->def->seclabel.label);
            return -1;
        }
    }

    return 0;
}

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

451
    if ((profile_name = get_profile_name(vm)) == NULL)
J
Jamie Strandboge 已提交
452 453 454 455
        return rc;

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

    if ((sec->enforcing = profile_status(profile_name, 1)) < 0) {
462
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
                               "%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
478 479
AppArmorReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                             virDomainObjPtr vm)
480 481 482 483 484 485 486 487 488 489 490 491
{
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;

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

    return 0;
}


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

499
    if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
J
Jamie Strandboge 已提交
500
        if ((rc = remove_profile(secdef->label)) != 0) {
501
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
502 503 504 505 506 507 508 509 510 511 512
                                   _("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
513
AppArmorSetSecurityProcessLabel(virSecurityDriverPtr drv, virDomainObjPtr vm)
J
Jamie Strandboge 已提交
514 515 516 517 518
{
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
    int rc = -1;
    char *profile_name = NULL;

519
    if ((profile_name = get_profile_name(vm)) == NULL)
J
Jamie Strandboge 已提交
520 521 522
        return rc;

    if (STRNEQ(drv->name, secdef->model)) {
523
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
J
Jamie Strandboge 已提交
524 525 526 527 528 529 530 531 532
                               _("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) {
533
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR, "%s",
J
Jamie Strandboge 已提交
534 535 536 537 538 539 540 541 542 543 544 545 546 547
                               _("error calling aa_change_profile()"));
        goto clean;
    }
    rc = 0;

  clean:
    VIR_FREE(profile_name);

    return rc;
}


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

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

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

J
Jamie Strandboge 已提交
567 568 569 570 571 572
    if (!disk->src)
        return 0;

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

578
        if ((profile_name = get_profile_name(vm)) == NULL)
J
Jamie Strandboge 已提交
579 580 581 582
            return rc;

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

  clean:
    VIR_FREE(profile_name);

    return rc;
}

static int
601
AppArmorSecurityVerify(virDomainDefPtr def)
J
Jamie Strandboge 已提交
602 603 604 605 606
{
    const virSecurityLabelDefPtr secdef = &def->seclabel;

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

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

static int
625 626
AppArmorSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                                virDomainObjPtr vm,
J
Jamie Strandboge 已提交
627 628 629
                                virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)

{
630 631 632 633 634
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;

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

J
Jamie Strandboge 已提交
635 636 637 638 639
    /* TODO: call load_profile with an update vm->def */
    return 0;
}

static int
640 641
AppArmorRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
                                    virDomainObjPtr vm,
J
Jamie Strandboge 已提交
642 643 644
                                    virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)

{
645 646 647 648
    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
        return 0;

J
Jamie Strandboge 已提交
649 650 651 652
    /* TODO: call load_profile (needs virDomainObjPtr vm) */
    return 0;
}

653
static int
654 655 656
AppArmorSetSavedStateLabel(virSecurityDriverPtr drv,
                           virDomainObjPtr vm,
                           const char *savefile)
657
{
658
    return reload_profile(drv, vm, savefile);
659 660 661 662
}


static int
663 664
AppArmorRestoreSavedStateLabel(virSecurityDriverPtr drv,
                               virDomainObjPtr vm,
665 666
                               const char *savefile ATTRIBUTE_UNUSED)
{
667
    return reload_profile(drv, vm, NULL);
668 669
}

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