From patchwork Mon Apr 6 17:59:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deven Bowers X-Patchwork-Id: 11476081 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7B1A41392 for ; Mon, 6 Apr 2020 17:59:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 59DCA20753 for ; Mon, 6 Apr 2020 17:59:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="BM2q7hn6" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727322AbgDFR7Y (ORCPT ); Mon, 6 Apr 2020 13:59:24 -0400 Received: from linux.microsoft.com ([13.77.154.182]:51628 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726787AbgDFR7Y (ORCPT ); Mon, 6 Apr 2020 13:59:24 -0400 Received: from dede-linux.corp.microsoft.com (unknown [131.107.147.242]) by linux.microsoft.com (Postfix) with ESMTPSA id F1FE52072955; Mon, 6 Apr 2020 10:59:22 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com F1FE52072955 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1586195963; bh=1PF/ShPN4ojALJPkpCvH1fBtV3IR9aL7+GRD4lEL+Es=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BM2q7hn61sgw2I8AOb7TKeT8byFgDQ2Gby36bTcx0NGZYBZTR4ic6MZGkE9sKA6jL O1exWydXPWFwwWnLD3XxAdPHQjtwVLE1c/4vlW+kKnXx/BP9tCkO9Aew/Ugg2Gg2PN VBQRJ6kIzJ3URF2LHbinXHf9kJnkSwEKL5+o7fQs= From: deven.desai@linux.microsoft.com To: agk@redhat.com, axboe@kernel.dk, snitzer@redhat.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, dm-devel@redhat.org, linux-block@vger.kernel.org Cc: tyhicks@linux.microsoft.com, pasha.tatashin@soleen.com, mdsakib@microsoft.com, sashal@kernel.org, jaskarankhurana@linux.microsoft.com, nramas@linux.microsoft.com Subject: [PATCH 01/11] scripts: add ipe tooling to generate boot policy Date: Mon, 6 Apr 2020 10:59:08 -0700 Message-Id: <20200406175919.1023205-2-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> References: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: Deven Bowers Add a tool for the generation of an IPE policy to be compiled into the kernel. This policy will be enforced until userland deploys and activates a new policy. Signed-off-by: Deven Bowers --- scripts/Makefile | 1 + scripts/ipe/Makefile | 2 + scripts/ipe/polgen/.gitignore | 1 + scripts/ipe/polgen/Makefile | 7 ++ scripts/ipe/polgen/polgen.c | 136 ++++++++++++++++++++++++++++++++++ 5 files changed, 147 insertions(+) create mode 100644 scripts/ipe/Makefile create mode 100644 scripts/ipe/polgen/.gitignore create mode 100644 scripts/ipe/polgen/Makefile create mode 100644 scripts/ipe/polgen/polgen.c diff --git a/scripts/Makefile b/scripts/Makefile index 5e75802b1a44..9338017a3b6e 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -38,6 +38,7 @@ hostprogs += unifdef subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins subdir-$(CONFIG_MODVERSIONS) += genksyms subdir-$(CONFIG_SECURITY_SELINUX) += selinux +subdir-$(CONFIG_SECURITY_IPE) += ipe # Let clean descend into subdirs subdir- += basic dtc gdb kconfig mod diff --git a/scripts/ipe/Makefile b/scripts/ipe/Makefile new file mode 100644 index 000000000000..e87553fbb8d6 --- /dev/null +++ b/scripts/ipe/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +subdir-y := polgen diff --git a/scripts/ipe/polgen/.gitignore b/scripts/ipe/polgen/.gitignore new file mode 100644 index 000000000000..80f32f25d200 --- /dev/null +++ b/scripts/ipe/polgen/.gitignore @@ -0,0 +1 @@ +polgen diff --git a/scripts/ipe/polgen/Makefile b/scripts/ipe/polgen/Makefile new file mode 100644 index 000000000000..a519b594e13c --- /dev/null +++ b/scripts/ipe/polgen/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +hostprogs-y := polgen +HOST_EXTRACFLAGS += \ + -I$(srctree)/include \ + -I$(srctree)/include/uapi \ + +always := $(hostprogs-y) diff --git a/scripts/ipe/polgen/polgen.c b/scripts/ipe/polgen/polgen.c new file mode 100644 index 000000000000..a80fffe1b27c --- /dev/null +++ b/scripts/ipe/polgen/polgen.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +static void usage(const char *const name) +{ + printf("Usage: %s OutputFile (PolicyFile)\n", name); + exit(EINVAL); +} + +static int policy_to_buffer(const char *pathname, char **buffer, size_t *size) +{ + int rc = 0; + FILE *fd; + char *lbuf; + size_t fsize; + size_t read; + + fd = fopen(pathname, "r"); + if (!fd) { + rc = errno; + goto out; + } + + fseek(fd, 0, SEEK_END); + fsize = ftell(fd); + rewind(fd); + + lbuf = malloc(fsize); + if (!lbuf) { + rc = ENOMEM; + goto out_close; + } + + read = fread((void *)lbuf, sizeof(*lbuf), fsize, fd); + if (read != fsize) { + rc = -1; + goto out_free; + } + + *buffer = lbuf; + *size = fsize; + fclose(fd); + + return rc; + +out_free: + free(lbuf); +out_close: + fclose(fd); +out: + return rc; +} + +static int write_boot_policy(const char *pathname, const char *buf, size_t size) +{ + FILE *fd; + size_t i; + + fd = fopen(pathname, "w"); + if (!fd) + goto err; + + fprintf(fd, "/* This file is automatically generated."); + fprintf(fd, " Do not edit. */\n"); + fprintf(fd, "#include \n"); + fprintf(fd, "const char *const ipe_boot_policy =\n"); + + if (!buf || size == 0) { + fprintf(fd, "\tNULL;\n"); + fclose(fd); + return 0; + } + + for (i = 0; i < size; ++i) { + if (i == 0) + fprintf(fd, "\t\""); + + switch (buf[i]) { + case '"': + fprintf(fd, "\\\""); + break; + case '\'': + fprintf(fd, "'"); + break; + case '\n': + fprintf(fd, "\\n\"\n\t\""); + break; + case '\\': + fprintf(fd, "\\\\"); + break; + default: + fprintf(fd, "%c", buf[i]); + } + } + fprintf(fd, "\";\n"); + fclose(fd); + + return 0; + +err: + if (fd) + fclose(fd); + return errno; +} + +int main(int argc, const char *argv[]) +{ + int rc = 0; + size_t len = 0; + char *policy = NULL; + + if (argc < 2) + usage(argv[0]); + + if (argc > 2) { + rc = policy_to_buffer(argv[2], &policy, &len); + if (rc != 0) + goto cleanup; + } + + rc = write_boot_policy(argv[1], policy, len); +cleanup: + if (policy) + free(policy); + if (rc != 0) + perror("An error occurred during policy conversion: "); + return rc; +} From patchwork Mon Apr 6 17:59:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deven Bowers X-Patchwork-Id: 11476097 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 65CCF174A for ; Mon, 6 Apr 2020 17:59:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3ADE420780 for ; Mon, 6 Apr 2020 17:59:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="T+B+HRhh" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727409AbgDFR70 (ORCPT ); Mon, 6 Apr 2020 13:59:26 -0400 Received: from linux.microsoft.com ([13.77.154.182]:51694 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727226AbgDFR70 (ORCPT ); Mon, 6 Apr 2020 13:59:26 -0400 Received: from dede-linux.corp.microsoft.com (unknown [131.107.147.242]) by linux.microsoft.com (Postfix) with ESMTPSA id 9063B207295B; Mon, 6 Apr 2020 10:59:23 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 9063B207295B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1586195963; bh=vTfxSCC02zdqx9PaEAcVLbq1r1+MIMBWH9enE+xlj04=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=T+B+HRhhfCWSJSPbz4iJyT28grAeBkuMyb0HQt+TVMMFI0R/RM0OHdgvldtKwUGXZ dM4hgQXjV2Rh8YnzqQF2MIxJESZBXQYuXdc4sMnMNt1EZNc0DHESS9X6VLzAkLjvRq R0bo5w/JkTq9CmvOqHElbeyBxHQ7EF85+I4saAmk= From: deven.desai@linux.microsoft.com To: agk@redhat.com, axboe@kernel.dk, snitzer@redhat.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, dm-devel@redhat.org, linux-block@vger.kernel.org Cc: tyhicks@linux.microsoft.com, pasha.tatashin@soleen.com, mdsakib@microsoft.com, sashal@kernel.org, jaskarankhurana@linux.microsoft.com, nramas@linux.microsoft.com Subject: [PATCH 03/11] ipe: add property for trust of boot volume Date: Mon, 6 Apr 2020 10:59:10 -0700 Message-Id: <20200406175919.1023205-4-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> References: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: Deven Bowers Add a property for IPE policy to express trust of the first superblock where a file would be evaluated to determine trust. Signed-off-by: Deven Bowers --- security/ipe/Kconfig | 2 + security/ipe/Makefile | 4 ++ security/ipe/ipe-engine.c | 4 ++ security/ipe/ipe-hooks.c | 19 +++++ security/ipe/ipe-hooks.h | 2 + security/ipe/ipe-pin.c | 93 +++++++++++++++++++++++++ security/ipe/ipe-pin.h | 56 +++++++++++++++ security/ipe/ipe.c | 14 +++- security/ipe/properties/Kconfig | 14 ++++ security/ipe/properties/Makefile | 11 +++ security/ipe/properties/boot-verified.c | 84 ++++++++++++++++++++++ security/ipe/properties/prop-entry.h | 20 ++++++ security/ipe/utility.h | 22 ++++++ 13 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 security/ipe/ipe-pin.c create mode 100644 security/ipe/ipe-pin.h create mode 100644 security/ipe/properties/Kconfig create mode 100644 security/ipe/properties/Makefile create mode 100644 security/ipe/properties/boot-verified.c create mode 100644 security/ipe/properties/prop-entry.h create mode 100644 security/ipe/utility.h diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig index ef6fb019be6f..b1d89244da3e 100644 --- a/security/ipe/Kconfig +++ b/security/ipe/Kconfig @@ -38,4 +38,6 @@ config SECURITY_IPE_PERMISSIVE_SWITCH If unsure, answer Y. +source "security/ipe/properties/Kconfig" + endif diff --git a/security/ipe/Makefile b/security/ipe/Makefile index 4dcfc5b26b58..741914ddc338 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -27,3 +27,7 @@ obj-$(CONFIG_SECURITY_IPE) += \ ipe-sysfs.o \ clean-files := ipe-bp.c + +obj-$(CONFIG_IPE_BOOT_PROP) += ipe-pin.o + +obj-$(CONFIG_SECURITY_IPE) += properties/ diff --git a/security/ipe/ipe-engine.c b/security/ipe/ipe-engine.c index 3e05fa911e71..a629ae3c882d 100644 --- a/security/ipe/ipe-engine.c +++ b/security/ipe/ipe-engine.c @@ -9,6 +9,8 @@ #include "ipe-policy.h" #include "ipe-engine.h" #include "ipe-audit.h" +#include "ipe-pin.h" +#include "utility.h" #include #include @@ -331,6 +333,8 @@ int ipe_process_event(const struct file *file, enum ipe_op op, if (IS_ERR(ctx)) goto cleanup; + ipe_pin_superblock(ctx->file); + rc = prealloc_cache(ctx, &cache); if (rc != 0) goto cleanup; diff --git a/security/ipe/ipe-hooks.c b/security/ipe/ipe-hooks.c index a5d37b87c0cd..43182ba25cc5 100644 --- a/security/ipe/ipe-hooks.c +++ b/security/ipe/ipe-hooks.c @@ -6,6 +6,7 @@ #include "ipe.h" #include "ipe-hooks.h" #include "ipe-engine.h" +#include "ipe-pin.h" #include #include @@ -149,3 +150,21 @@ int ipe_on_kernel_load_data(enum kernel_load_data_id id) ipe_hook_kernel_load); } } + +/** + * ipe_sb_free_security: LSM hook called on sb_free_security. + * @mnt_sb: Super block that is being freed. + * + * IPE does not currently utilize the super block security hook, + * it utilizes this hook to invalidate the saved super block for + * the boot_verified property. + * + * For more information, see the LSM hook, sb_free_security. + * + * Return: + * 0 - OK + */ +void ipe_sb_free_security(struct super_block *mnt_sb) +{ + ipe_invalidate_pinned_sb(mnt_sb); +} diff --git a/security/ipe/ipe-hooks.h b/security/ipe/ipe-hooks.h index 6af706a130ce..55e417c72425 100644 --- a/security/ipe/ipe-hooks.h +++ b/security/ipe/ipe-hooks.h @@ -111,4 +111,6 @@ int ipe_on_kernel_read(struct file *file, enum kernel_read_file_id id); */ int ipe_on_kernel_load_data(enum kernel_load_data_id id); +void ipe_sb_free_security(struct super_block *mnt_sb); + #endif /* IPE_HOOK_H */ diff --git a/security/ipe/ipe-pin.c b/security/ipe/ipe-pin.c new file mode 100644 index 000000000000..a963be8e5321 --- /dev/null +++ b/security/ipe/ipe-pin.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file has been heavily adapted from the source code of the + * loadpin LSM. The source code for loadpin is co-located in the linux + * tree under security/loadpin/loadpin.c. + * + * Please see loadpin.c for up-to-date information about + * loadpin. + */ + +#include "ipe.h" + +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_SPINLOCK(pinned_sb_spinlock); + +static struct super_block *pinned_sb; + +/** + * ipe_is_from_pinned_sb: Determine if @file originates from the initial + * super block that a file was executed from. + * @file: File to check if it originates from the super block. + * + * Return: + * true - File originates from the initial super block + * false - File does not originate from the initial super block + */ +bool ipe_is_from_pinned_sb(const struct file *file) +{ + bool rv = false; + + spin_lock(&pinned_sb_spinlock); + + /* + * Check if pinned_sb is set: + * NULL == not set -> exit + * ERR == was once set (and has been unmounted) -> exit + * AND check that the pinned sb is the same as the file's. + */ + if (!IS_ERR_OR_NULL(pinned_sb) && + file->f_path.mnt->mnt_sb == pinned_sb) { + rv = true; + goto cleanup; + } + +cleanup: + spin_unlock(&pinned_sb_spinlock); + return rv; +} + +/** + * ipe_pin_superblock: Attempt to save a file's super block address to later + * determine if a file originates from a super block. + * @file: File to source the super block from. + */ +void ipe_pin_superblock(const struct file *file) +{ + spin_lock(&pinned_sb_spinlock); + + /* if set, return */ + if (pinned_sb || !file) + goto cleanup; + + pinned_sb = file->f_path.mnt->mnt_sb; +cleanup: + spin_unlock(&pinned_sb_spinlock); +} + +/** + * ipe_invalidate_pinned_sb: Invalidate the saved super block. + * @mnt_sb: Super block to compare against the saved super block. + * + * This avoids authorizing a file when the super block does not exist anymore. + */ +void ipe_invalidate_pinned_sb(const struct super_block *mnt_sb) +{ + spin_lock(&pinned_sb_spinlock); + + /* + * On pinned sb unload - invalidate the pinned address + * by setting the pinned_sb to ERR_PTR(-EIO) + */ + if (!IS_ERR_OR_NULL(pinned_sb) && mnt_sb == pinned_sb) + pinned_sb = ERR_PTR(-EIO); + + spin_unlock(&pinned_sb_spinlock); +} diff --git a/security/ipe/ipe-pin.h b/security/ipe/ipe-pin.h new file mode 100644 index 000000000000..7c3773d8387d --- /dev/null +++ b/security/ipe/ipe-pin.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ +#ifndef IPE_PIN_H +#define IPE_PIN_H + +#include +#include + +#ifdef CONFIG_IPE_BOOT_PROP + +/** + * ipe_is_from_pinned_sb: Determine if @file originates from the initial + * super block that a file was executed from. + * @file: File to check if it originates from the super block. + * + * Return: + * true - File originates from the initial super block + * false - File does not originate from the initial super block + */ +bool ipe_is_from_pinned_sb(const struct file *file); + +/** + * ipe_pin_superblock: Attempt to save a file's super block address to later + * determine if a file originates from a super block. + * @file: File to source the super block from. + */ +void ipe_pin_superblock(const struct file *file); + +/** + * ipe_invalidate_pinned_sb: Invalidate the saved super block. + * @mnt_sb: Super block to compare against the saved super block. + * + * This avoids authorizing a file when the super block does not exist anymore. + */ +void ipe_invalidate_pinned_sb(const struct super_block *mnt_sb); + +#else /* CONFIG_IPE_BOOT_PROP */ + +static inline bool ipe_is_from_pinned_sb(const struct file *file) +{ + return false; +} + +static inline void ipe_pin_superblock(const struct file *file) +{ +} + +static inline void ipe_invalidate_pinned_sb(const struct super_block *mnt_sb) +{ +} + +#endif /* !CONFIG_IPE_BOOT_PROP */ + +#endif /* IPE_PIN_H */ diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c index 4642a0da57e5..971c50ecadaf 100644 --- a/security/ipe/ipe.c +++ b/security/ipe/ipe.c @@ -8,6 +8,7 @@ #include "ipe-hooks.h" #include "ipe-secfs.h" #include "ipe-sysfs.h" +#include "properties/prop-entry.h" #include #include @@ -23,6 +24,7 @@ static struct security_hook_list ipe_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(kernel_read_file, ipe_on_kernel_read), LSM_HOOK_INIT(kernel_load_data, ipe_on_kernel_load_data), LSM_HOOK_INIT(file_mprotect, ipe_on_mprotect), + LSM_HOOK_INIT(sb_free_security, ipe_sb_free_security), }; /** @@ -34,7 +36,13 @@ static struct security_hook_list ipe_hooks[] __lsm_ro_after_init = { */ static int __init ipe_load_properties(void) { - return 0; + int rc = 0; + + rc = ipe_init_bootv(); + if (rc != 0) + return rc; + + return rc; } /** @@ -54,6 +62,10 @@ static int __init ipe_init(void) { int rc = 0; + rc = ipe_load_properties(); + if (rc != 0) + panic("IPE: properties failed to load"); + rc = ipe_sysctl_init(); if (rc != 0) pr_err("failed to configure sysctl: %d", -rc); diff --git a/security/ipe/properties/Kconfig b/security/ipe/properties/Kconfig new file mode 100644 index 000000000000..9dc0db8817b2 --- /dev/null +++ b/security/ipe/properties/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Integrity Policy Enforcement (IPE) configuration +# + +config IPE_BOOT_PROP + bool "Enable trust for boot volume" + help + This option enables the property "boot_verified" in IPE policy. + This property 'pins' the initial superblock when something is + evaluated. This property will evaluate to true when the file + being evaluated originates from the initial superblock. + + if unsure, answer N. diff --git a/security/ipe/properties/Makefile b/security/ipe/properties/Makefile new file mode 100644 index 000000000000..e3e7fe17cf58 --- /dev/null +++ b/security/ipe/properties/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) Microsoft Corporation. All rights reserved. +# +# Makefile for building the properties that IPE uses +# as part of the kernel tree. +# + +obj-$(CONFIG_SECURITY_IPE) += properties.o + +properties-$(CONFIG_IPE_BOOT_PROP) += boot-verified.o diff --git a/security/ipe/properties/boot-verified.c b/security/ipe/properties/boot-verified.c new file mode 100644 index 000000000000..07c8ba768ac5 --- /dev/null +++ b/security/ipe/properties/boot-verified.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include "../ipe.h" +#include "../ipe-pin.h" +#include "../ipe-property.h" +#include "../utility.h" + +#include +#include +#include +#include +#include + +#define PROPERTY_NAME "boot_verified" + +static void audit(struct audit_buffer *ab, bool value) +{ + audit_log_format(ab, "%s", (value) ? "TRUE" : "FALSE"); +} + +static inline void audit_rule_value(struct audit_buffer *ab, + const void *value) +{ + audit(ab, (bool)value); +} + +static inline void audit_ctx(struct audit_buffer *ab, + const struct ipe_engine_ctx *ctx, + const void *storage) +{ + bool b = has_sb(ctx->file) && ipe_is_from_pinned_sb(ctx->file); + + audit(ab, b); +} + +static bool evaluate(const struct ipe_engine_ctx *ctx, + const void *value, void **storage) +{ + bool expect = (bool)value; + + if (!ctx->file || !has_sb(ctx->file)) + return false; + + return ipe_is_from_pinned_sb(ctx->file) == expect; +} + +static int parse(const char *val_str, void **value) +{ + if (strcmp("TRUE", val_str) == 0) + *value = (void *)true; + else if (strcmp("FALSE", val_str) == 0) + *value = (void *)false; + else + return -EBADMSG; + + return 0; +} + +static inline int duplicate(const void *src, void **dest) +{ + *dest = (void *)(bool)src; + + return 0; +} + +static const struct ipe_property boot_verified = { + .property_name = PROPERTY_NAME, + .eval = evaluate, + .rule_audit = audit_rule_value, + .ctx_audit = audit_ctx, + .parse = parse, + .dup = duplicate, + .prealloc = NULL, + .free_val = NULL, + .free_storage = NULL, +}; + +int ipe_init_bootv(void) +{ + return ipe_register_property(&boot_verified); +} diff --git a/security/ipe/properties/prop-entry.h b/security/ipe/properties/prop-entry.h new file mode 100644 index 000000000000..f598dd9608b9 --- /dev/null +++ b/security/ipe/properties/prop-entry.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include + +#ifndef IPE_PROP_ENTRY_H +#define IPE_PROP_ENTRY_H + +#ifndef CONFIG_IPE_BOOT_PROP +static inline int __init ipe_init_bootv(void) +{ + return 0; +} +#else +int __init ipe_init_bootv(void); +#endif /* CONFIG_IPE_BOOT_PROP */ + +#endif /* IPE_PROP_ENTRY_H */ diff --git a/security/ipe/utility.h b/security/ipe/utility.h new file mode 100644 index 000000000000..a13089bb0d8f --- /dev/null +++ b/security/ipe/utility.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#ifndef IPE_UTILITY_H +#define IPE_UTILITY_H + +#include +#include + +static inline bool has_mount(const struct file *file) +{ + return file && file->f_path.mnt; +} + +static inline bool has_sb(const struct file *file) +{ + return has_mount(file) && file->f_path.mnt->mnt_sb; +} + +#endif /* IPE_UTILITY_H */ From patchwork Mon Apr 6 17:59:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deven Bowers X-Patchwork-Id: 11476099 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A7D951392 for ; Mon, 6 Apr 2020 17:59:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8420520678 for ; Mon, 6 Apr 2020 17:59:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="fnGVmsEJ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727582AbgDFR71 (ORCPT ); Mon, 6 Apr 2020 13:59:27 -0400 Received: from linux.microsoft.com ([13.77.154.182]:51732 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727237AbgDFR70 (ORCPT ); Mon, 6 Apr 2020 13:59:26 -0400 Received: from dede-linux.corp.microsoft.com (unknown [131.107.147.242]) by linux.microsoft.com (Postfix) with ESMTPSA id CB2A320A0861; Mon, 6 Apr 2020 10:59:23 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com CB2A320A0861 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1586195963; bh=9FYFmPniCXDJvrlfzO+eVVXSFFFiE8iLOu+qPY26nh0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fnGVmsEJ2WeTNiFLRe4u3pCEO5ECRIUs+u+0ZsdPmU4chj0qyMaM8uaBTiap13DL1 hl1AB9uKqVkfeYOC9J6mA24QraGshYx/9/YJK1ReOS38W3cf82Nvib0vCtkb9Cf92g VRqK8oic3GfLVt0KQp8KZFtUOsHHnyssKEp/RU64= From: deven.desai@linux.microsoft.com To: agk@redhat.com, axboe@kernel.dk, snitzer@redhat.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, dm-devel@redhat.org, linux-block@vger.kernel.org Cc: tyhicks@linux.microsoft.com, pasha.tatashin@soleen.com, mdsakib@microsoft.com, sashal@kernel.org, jaskarankhurana@linux.microsoft.com, nramas@linux.microsoft.com Subject: [PATCH 04/11] fs: add security blob and hooks for block_device Date: Mon, 6 Apr 2020 10:59:11 -0700 Message-Id: <20200406175919.1023205-5-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> References: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: Deven Bowers Add a security blob and associated allocation, deallocation and set hooks for a block_device structure. Signed-off-by: Deven Bowers --- fs/block_dev.c | 8 +++++ include/linux/fs.h | 1 + include/linux/lsm_hook_defs.h | 5 +++ include/linux/lsm_hooks.h | 11 +++++++ include/linux/security.h | 22 +++++++++++++ security/security.c | 61 +++++++++++++++++++++++++++++++++++ 6 files changed, 108 insertions(+) diff --git a/fs/block_dev.c b/fs/block_dev.c index 52b6f646cdbd..5dfa25f03208 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "internal.h" struct bdev_inode { @@ -773,11 +774,18 @@ static struct inode *bdev_alloc_inode(struct super_block *sb) struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL); if (!ei) return NULL; + + if (unlikely(security_bdev_alloc(&ei->bdev))) { + kmem_cache_free(bdev_cachep, ei); + return NULL; + } + return &ei->vfs_inode; } static void bdev_free_inode(struct inode *inode) { + security_bdev_free(&BDEV_I(inode)->bdev); kmem_cache_free(bdev_cachep, BDEV_I(inode)); } diff --git a/include/linux/fs.h b/include/linux/fs.h index f81c822f4d89..03d089f4a511 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -506,6 +506,7 @@ struct block_device { int bd_fsfreeze_count; /* Mutex for freeze */ struct mutex bd_fsfreeze_mutex; + void *security; } __randomize_layout; /* XArray tags, for tagging dirty and writeback pages in the pagecache. */ diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 9cd4455528e5..4782fef7eaf9 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -379,3 +379,8 @@ LSM_HOOK(void, LSM_RET_VOID, perf_event_free, struct perf_event *event) LSM_HOOK(int, 0, perf_event_read, struct perf_event *event) LSM_HOOK(int, 0, perf_event_write, struct perf_event *event) #endif /* CONFIG_PERF_EVENTS */ + +LSM_HOOK(int, 0, bdev_alloc_security, struct block_device *bdev) +LSM_HOOK(void, LSM_RET_VOID, bdev_free_security, struct block_device *bdev) +LSM_HOOK(int, 0, bdev_setsecurity, struct block_device *bdev, const char *name, + const void *value, size_t size) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 988ca0df7824..7bf0f82bc5d6 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1476,6 +1476,16 @@ * * @what: kernel feature being accessed * + * @bdev_alloc_security: + * Initialize the security field inside a block_device structure. + * + * @bdev_free_security: + * Cleanup the security information stored inside a block_device structure. + * + * @bdev_setsecurity: + * Set the security property associated with @name for @bdev with + * value @value. @size indicates the size of the @value in bytes. + * * Security hooks for perf events * * @perf_event_open: @@ -1522,6 +1532,7 @@ struct lsm_blob_sizes { int lbs_ipc; int lbs_msg_msg; int lbs_task; + int lbs_bdev; }; /* diff --git a/include/linux/security.h b/include/linux/security.h index a8d9310472df..714eecc82e08 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -446,6 +446,11 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); int security_locked_down(enum lockdown_reason what); +int security_bdev_alloc(struct block_device *bdev); +void security_bdev_free(struct block_device *bdev); +int security_bdev_setsecurity(struct block_device *bdev, + const char *name, const void *value, + size_t size); #else /* CONFIG_SECURITY */ static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data) @@ -1273,6 +1278,23 @@ static inline int security_locked_down(enum lockdown_reason what) { return 0; } + +static inline int security_bdev_alloc(struct block_device *bdev) +{ + return 0; +} + +static inline void security_bdev_free(struct block_device *bdev) +{ +} + +static inline int security_bdev_setsecurity(struct block_device *bdev, + const char *name, + const void *value, size_t size) +{ + return 0; +} + #endif /* CONFIG_SECURITY */ #ifdef CONFIG_SECURITY_NETWORK diff --git a/security/security.c b/security/security.c index 7fed24b9d57e..0d1af27711c1 100644 --- a/security/security.c +++ b/security/security.c @@ -28,6 +28,7 @@ #include #include #include +#include #define MAX_LSM_EVM_XATTR 2 @@ -202,6 +203,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed) lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc); lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg); lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task); + lsm_set_blob_size(&needed->lbs_bdev, &blob_sizes.lbs_bdev); } /* Prepare LSM for initialization. */ @@ -337,6 +339,7 @@ static void __init ordered_lsm_init(void) init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc); init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); init_debug("task blob size = %d\n", blob_sizes.lbs_task); + init_debug("bdev blob size = %d\n", blob_sizes.lbs_bdev); /* * Create any kmem_caches needed for blobs @@ -654,6 +657,28 @@ static int lsm_msg_msg_alloc(struct msg_msg *mp) return 0; } +/** + * lsm_bdev_alloc - allocate a composite block_device blob + * @bdev: the block_device that needs a blob + * + * Allocate the block_device blob for all the modules + * + * Returns 0, or -ENOMEM if memory can't be allocated. + */ +static int lsm_bdev_alloc(struct block_device *bdev) +{ + if (blob_sizes.lbs_bdev == 0) { + bdev->security = NULL; + return 0; + } + + bdev->security = kzalloc(blob_sizes.lbs_bdev, GFP_KERNEL); + if (!bdev->security) + return -ENOMEM; + + return 0; +} + /** * lsm_early_task - during initialization allocate a composite task blob * @task: the task that needs a blob @@ -2456,6 +2481,42 @@ int security_locked_down(enum lockdown_reason what) } EXPORT_SYMBOL(security_locked_down); +int security_bdev_alloc(struct block_device *bdev) +{ + int rc = 0; + + rc = lsm_bdev_alloc(bdev); + if (unlikely(rc)) + return rc; + + rc = call_int_hook(bdev_alloc_security, 0, bdev); + if (unlikely(rc)) + security_bdev_free(bdev); + + return 0; +} +EXPORT_SYMBOL(security_bdev_alloc); + +void security_bdev_free(struct block_device *bdev) +{ + if (!bdev->security) + return; + + call_void_hook(bdev_free_security, bdev); + + kfree(bdev->security); + bdev->security = NULL; +} +EXPORT_SYMBOL(security_bdev_free); + +int security_bdev_setsecurity(struct block_device *bdev, + const char *name, const void *value, + size_t size) +{ + return call_int_hook(bdev_setsecurity, 0, bdev, name, value, size); +} +EXPORT_SYMBOL(security_bdev_setsecurity); + #ifdef CONFIG_PERF_EVENTS int security_perf_event_open(struct perf_event_attr *attr, int type) { From patchwork Mon Apr 6 17:59:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deven Bowers X-Patchwork-Id: 11476113 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9482C1744 for ; Mon, 6 Apr 2020 17:59:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 730402078C for ; Mon, 6 Apr 2020 17:59:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="KUrj+Irv" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727652AbgDFR72 (ORCPT ); Mon, 6 Apr 2020 13:59:28 -0400 Received: from linux.microsoft.com ([13.77.154.182]:51776 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727376AbgDFR71 (ORCPT ); Mon, 6 Apr 2020 13:59:27 -0400 Received: from dede-linux.corp.microsoft.com (unknown [131.107.147.242]) by linux.microsoft.com (Postfix) with ESMTPSA id 39AAA20A0866; Mon, 6 Apr 2020 10:59:24 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 39AAA20A0866 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1586195964; bh=pp2JNwWm8aiM6z3AlwB0sPXCjj9odJHaB9Ic7PhOYoU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KUrj+Irvb3Tof0O53yp13T2K1Qif+6raSYdo8mDoeJm8eFhxxWKoTerId/qCWN6Pw dxJAbSuRPGWKlL0rcn7xf18vbihMIYN4L+ux9x1gOe1KaTU81Pz/E+PRwIA40EKiKv 7RioTegR67nf41QpFbqpmcn3UEWLUTO9SWfLlNuw= From: deven.desai@linux.microsoft.com To: agk@redhat.com, axboe@kernel.dk, snitzer@redhat.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, dm-devel@redhat.org, linux-block@vger.kernel.org Cc: tyhicks@linux.microsoft.com, pasha.tatashin@soleen.com, mdsakib@microsoft.com, sashal@kernel.org, jaskarankhurana@linux.microsoft.com, nramas@linux.microsoft.com Subject: [PATCH 05/11] dm-verity: move signature check after tree validation Date: Mon, 6 Apr 2020 10:59:13 -0700 Message-Id: <20200406175919.1023205-7-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> References: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: Deven Bowers The CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG introduced by Jaskaran was intended to be used to allow an LSM to enforce verifications for all dm-verity volumes. However, with it's current implementation, this signature verification occurs after the merkel-tree is validated, as a result the signature can pass initial verification by passing a matching root-hash and signature. This results in an unreadable block_device, but that has passed signature validation (and subsequently, would be marked as verified). This change moves the signature verification to after the merkel-tree has finished validation. Signed-off-by: Deven Bowers --- drivers/md/dm-verity-target.c | 42 ++++----- drivers/md/dm-verity-verify-sig.c | 140 ++++++++++++++++++++++-------- drivers/md/dm-verity-verify-sig.h | 20 ++--- drivers/md/dm-verity.h | 2 +- 4 files changed, 132 insertions(+), 72 deletions(-) diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index eec9f252e935..c507f3a4e237 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -471,9 +471,9 @@ static int verity_verify_io(struct dm_verity_io *io) struct bvec_iter start; unsigned b; struct crypto_wait wait; + int r; for (b = 0; b < io->n_blocks; b++) { - int r; sector_t cur_block = io->block + b; struct ahash_request *req = verity_io_hash_req(v, io); @@ -530,6 +530,16 @@ static int verity_verify_io(struct dm_verity_io *io) return -EIO; } + /* + * At this point, the merkel tree has finished validating. + * if signature was specified, validate the signature here. + */ + r = verity_verify_root_hash(v); + if (r < 0) { + DMERR_LIMIT("signature mismatch"); + return r; + } + return 0; } @@ -728,7 +738,7 @@ static void verity_status(struct dm_target *ti, status_type_t type, args++; if (v->validated_blocks) args++; - if (v->signature_key_desc) + if (v->sig) args += DM_VERITY_ROOT_HASH_VERIFICATION_OPTS; if (!args) return; @@ -751,9 +761,9 @@ static void verity_status(struct dm_target *ti, status_type_t type, if (v->validated_blocks) DMEMIT(" " DM_VERITY_OPT_AT_MOST_ONCE); sz = verity_fec_status_table(v, sz, result, maxlen); - if (v->signature_key_desc) + if (v->sig) DMEMIT(" " DM_VERITY_ROOT_HASH_VERIFICATION_OPT_SIG_KEY - " %s", v->signature_key_desc); + " %s", v->sig->signature_key_desc); break; } } @@ -819,7 +829,7 @@ static void verity_dtr(struct dm_target *ti) verity_fec_dtr(v); - kfree(v->signature_key_desc); + verity_verify_dtr(v); kfree(v); } @@ -876,8 +886,7 @@ static int verity_alloc_zero_digest(struct dm_verity *v) return r; } -static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, - struct dm_verity_sig_opts *verify_args) +static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v) { int r; unsigned argc; @@ -927,9 +936,7 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, return r; continue; } else if (verity_verify_is_sig_opt_arg(arg_name)) { - r = verity_verify_sig_parse_opt_args(as, v, - verify_args, - &argc, arg_name); + r = verity_verify_sig_parse_opt_args(as, v, &argc); if (r) return r; continue; @@ -960,7 +967,6 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) { struct dm_verity *v; - struct dm_verity_sig_opts verify_args = {0}; struct dm_arg_set as; unsigned int num; unsigned long long num_ll; @@ -1128,20 +1134,11 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) as.argc = argc; as.argv = argv; - r = verity_parse_opt_args(&as, v, &verify_args); + r = verity_parse_opt_args(&as, v); if (r < 0) goto bad; } - /* Root hash signature is a optional parameter*/ - r = verity_verify_root_hash(root_hash_digest_to_validate, - strlen(root_hash_digest_to_validate), - verify_args.sig, - verify_args.sig_size); - if (r < 0) { - ti->error = "Root hash verification failed"; - goto bad; - } v->hash_per_block_bits = __fls((1 << v->hash_dev_block_bits) / v->digest_size); @@ -1207,13 +1204,10 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) ti->per_io_data_size = roundup(ti->per_io_data_size, __alignof__(struct dm_verity_io)); - verity_verify_sig_opts_cleanup(&verify_args); - return 0; bad: - verity_verify_sig_opts_cleanup(&verify_args); verity_dtr(ti); return r; diff --git a/drivers/md/dm-verity-verify-sig.c b/drivers/md/dm-verity-verify-sig.c index 614e43db93aa..27dac8aa2e5a 100644 --- a/drivers/md/dm-verity-verify-sig.c +++ b/drivers/md/dm-verity-verify-sig.c @@ -22,6 +22,16 @@ MODULE_PARM_DESC(require_signatures, #define DM_VERITY_IS_SIG_FORCE_ENABLED() \ (require_signatures != false) +static void destroy_verity_sig(struct dm_verity_sig *sig_info) +{ + if (!sig_info) + return; + + kfree(sig_info->sig); + kfree(sig_info->signature_key_desc); + kfree(sig_info); +} + bool verity_verify_is_sig_opt_arg(const char *arg_name) { return (!strcasecmp(arg_name, @@ -29,7 +39,7 @@ bool verity_verify_is_sig_opt_arg(const char *arg_name) } static int verity_verify_get_sig_from_key(const char *key_desc, - struct dm_verity_sig_opts *sig_opts) + struct dm_verity_sig *sig_info) { struct key *key; const struct user_key_payload *ukp; @@ -48,14 +58,14 @@ static int verity_verify_get_sig_from_key(const char *key_desc, goto end; } - sig_opts->sig = kmalloc(ukp->datalen, GFP_KERNEL); - if (!sig_opts->sig) { + sig_info->sig = kmalloc(ukp->datalen, GFP_KERNEL); + if (!sig_info->sig) { ret = -ENOMEM; goto end; } - sig_opts->sig_size = ukp->datalen; + sig_info->sig_size = ukp->datalen; - memcpy(sig_opts->sig, ukp->data, sig_opts->sig_size); + memcpy(sig_info->sig, ukp->data, sig_info->sig_size); end: up_read(&key->sem); @@ -64,70 +74,128 @@ static int verity_verify_get_sig_from_key(const char *key_desc, return ret; } +/** + * Parse any signature verification arguments. + * This function will populate v->sig, it is the caller's + * responsibility to free this structure via verity_verify_dtr + * + * @as: argument set passed in to parse + * @v: verity context structure. Should have a NULL v->sig member. + * @argc: current argument number + */ int verity_verify_sig_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, - struct dm_verity_sig_opts *sig_opts, - unsigned int *argc, - const char *arg_name) + unsigned int *argc) { struct dm_target *ti = v->ti; + struct dm_verity_sig *sig_info = NULL; int ret = 0; const char *sig_key = NULL; if (!*argc) { ti->error = DM_VERITY_VERIFY_ERR("Signature key not specified"); - return -EINVAL; + ret = -EINVAL; + goto cleanup; + } + + sig_info = kzalloc(sizeof(*sig_info), GFP_KERNEL); + if (!sig_info) { + ret = -ENOMEM; + goto cleanup; } sig_key = dm_shift_arg(as); (*argc)--; - ret = verity_verify_get_sig_from_key(sig_key, sig_opts); - if (ret < 0) + ret = verity_verify_get_sig_from_key(sig_key, sig_info); + if (ret < 0) { ti->error = DM_VERITY_VERIFY_ERR("Invalid key specified"); + goto cleanup; + } - v->signature_key_desc = kstrdup(sig_key, GFP_KERNEL); - if (!v->signature_key_desc) - return -ENOMEM; + sig_info->signature_key_desc = kstrdup(sig_key, GFP_KERNEL); + if (!sig_info->signature_key_desc) { + ret = -ENOMEM; + goto cleanup; + } + v->sig = sig_info; + sig_info = NULL; +cleanup: + if (sig_info) + destroy_verity_sig(sig_info); return ret; } -/* +/** * verify_verify_roothash - Verify the root hash of the verity hash device * using builtin trusted keys. * - * @root_hash: For verity, the roothash/data to be verified. - * @root_hash_len: Size of the roothash/data to be verified. - * @sig_data: The trusted signature that verifies the roothash/data. - * @sig_len: Size of the signature. + * @v: dm_verity structure containing all context for the dm_verity + * operation. * */ -int verity_verify_root_hash(const void *root_hash, size_t root_hash_len, - const void *sig_data, size_t sig_len) +int verity_verify_root_hash(const struct dm_verity *v) { - int ret; + int ret = 0; + char *root_hash = NULL; + size_t root_hash_size = 0; + struct dm_verity_sig *sig_target = NULL; + + if (!v || !v->ti || !v->root_digest || v->digest_size == 0) { + ret = -EINVAL; + goto cleanup; + } + + sig_target = v->sig; + + if (!sig_target || !sig_target->sig || sig_target->sig_size == 0) { + if (DM_VERITY_IS_SIG_FORCE_ENABLED()) { + ret = -ENOKEY; + goto cleanup; + } else { + goto cleanup; + } + } - if (!root_hash || root_hash_len == 0) - return -EINVAL; + /* + * If signature has passed validation once, assume + * that future signatures will pass. + */ + if (sig_target->passed) + goto cleanup; - if (!sig_data || sig_len == 0) { - if (DM_VERITY_IS_SIG_FORCE_ENABLED()) - return -ENOKEY; - else - return 0; + root_hash_size = v->digest_size * 2; + root_hash = kzalloc(root_hash_size, GFP_KERNEL); + if (!root_hash) { + ret = -ENOMEM; + goto cleanup; } - ret = verify_pkcs7_signature(root_hash, root_hash_len, sig_data, - sig_len, NULL, VERIFYING_UNSPECIFIED_SIGNATURE, - NULL, NULL); + bin2hex(root_hash, v->root_digest, v->digest_size); + + ret = verify_pkcs7_signature(root_hash, root_hash_size, v->sig->sig, + v->sig->sig_size, NULL, + VERIFYING_UNSPECIFIED_SIGNATURE, NULL, + NULL); + if (ret != 0) + goto cleanup; + sig_target->passed = true; +cleanup: + kfree(root_hash); return ret; } -void verity_verify_sig_opts_cleanup(struct dm_verity_sig_opts *sig_opts) +/** + * Performs destruction / cleanup of a valid dm_verity_sig struct + * + * @v: dm_verity structure containing the dm_verity_sig struct to + * be freed. + */ + +void verity_verify_dtr(struct dm_verity *v) { - kfree(sig_opts->sig); - sig_opts->sig = NULL; - sig_opts->sig_size = 0; + destroy_verity_sig(v->sig); + v->sig = NULL; } diff --git a/drivers/md/dm-verity-verify-sig.h b/drivers/md/dm-verity-verify-sig.h index 19b1547aa741..9d7b34672c80 100644 --- a/drivers/md/dm-verity-verify-sig.h +++ b/drivers/md/dm-verity-verify-sig.h @@ -11,31 +11,30 @@ #define DM_VERITY_ROOT_HASH_VERIFICATION "DM Verity Sig Verification" #define DM_VERITY_ROOT_HASH_VERIFICATION_OPT_SIG_KEY "root_hash_sig_key_desc" -struct dm_verity_sig_opts { +struct dm_verity_sig { + char *signature_key_desc; unsigned int sig_size; u8 *sig; + bool passed; }; #ifdef CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG #define DM_VERITY_ROOT_HASH_VERIFICATION_OPTS 2 -int verity_verify_root_hash(const void *data, size_t data_len, - const void *sig_data, size_t sig_len); +int verity_verify_root_hash(const struct dm_verity *v); bool verity_verify_is_sig_opt_arg(const char *arg_name); int verity_verify_sig_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, - struct dm_verity_sig_opts *sig_opts, - unsigned int *argc, const char *arg_name); + unsigned int *argc); -void verity_verify_sig_opts_cleanup(struct dm_verity_sig_opts *sig_opts); +void verity_verify_dtr(struct dm_verity *v); #else #define DM_VERITY_ROOT_HASH_VERIFICATION_OPTS 0 -int verity_verify_root_hash(const void *data, size_t data_len, - const void *sig_data, size_t sig_len) +int verity_verify_root_hash(const struct dm_verity *v); { return 0; } @@ -46,13 +45,12 @@ bool verity_verify_is_sig_opt_arg(const char *arg_name) } int verity_verify_sig_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, - struct dm_verity_sig_opts *sig_opts, - unsigned int *argc, const char *arg_name) + unsigned int *argc) { return -EINVAL; } -void verity_verify_sig_opts_cleanup(struct dm_verity_sig_opts *sig_opts) +void verity_verify_dtr(struct dm_verity *v) { } diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h index 641b9e3a399b..995c495decad 100644 --- a/drivers/md/dm-verity.h +++ b/drivers/md/dm-verity.h @@ -64,7 +64,7 @@ struct dm_verity { struct dm_verity_fec *fec; /* forward error correction */ unsigned long *validated_blocks; /* bitset blocks validated */ - char *signature_key_desc; /* signature keyring reference */ + struct dm_verity_sig *sig; /* signature verification */ }; struct dm_verity_io { From patchwork Mon Apr 6 17:59:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deven Bowers X-Patchwork-Id: 11476093 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 06A101744 for ; Mon, 6 Apr 2020 17:59:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D995D206F8 for ; Mon, 6 Apr 2020 17:59:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="l5H7tjuD" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727368AbgDFR70 (ORCPT ); Mon, 6 Apr 2020 13:59:26 -0400 Received: from linux.microsoft.com ([13.77.154.182]:51784 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727409AbgDFR70 (ORCPT ); Mon, 6 Apr 2020 13:59:26 -0400 Received: from dede-linux.corp.microsoft.com (unknown [131.107.147.242]) by linux.microsoft.com (Postfix) with ESMTPSA id 75BB620A0865; Mon, 6 Apr 2020 10:59:24 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 75BB620A0865 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1586195964; bh=P9n7+UpIgC9iVSLYj1Fo2stDBpEmg08YMF+B1Mh0GN4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=l5H7tjuDcEoklILN9Xq71iMbGb/xRV9+Wbbu5CCg3M8Hj6DHtfgwD6UOrtOLxOhz/ OYCf5qiEFTLuZRQgYTfz70pNLPeBFhpoTsHGSIXqYLiRIK3eIMZux+KzsOv+QOTEAt AoubtY3gYeQ97lsaGZX0WkpdRLXgPd2RxANTSauc= From: deven.desai@linux.microsoft.com To: agk@redhat.com, axboe@kernel.dk, snitzer@redhat.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, dm-devel@redhat.org, linux-block@vger.kernel.org Cc: tyhicks@linux.microsoft.com, pasha.tatashin@soleen.com, mdsakib@microsoft.com, sashal@kernel.org, jaskarankhurana@linux.microsoft.com, nramas@linux.microsoft.com Subject: [PATCH 06/11] dm-verity: add bdev_setsecurity hook for dm-verity signature Date: Mon, 6 Apr 2020 10:59:14 -0700 Message-Id: <20200406175919.1023205-8-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> References: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: Deven Bowers Add a security hook call to set a security property of a block_device in dm-verity with the results of a verified, signed root-hash. Signed-off-by: Deven Bowers --- drivers/md/dm-verity-verify-sig.c | 7 +++++++ include/linux/device-mapper.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/md/dm-verity-verify-sig.c b/drivers/md/dm-verity-verify-sig.c index 27dac8aa2e5a..242e2421d3c8 100644 --- a/drivers/md/dm-verity-verify-sig.c +++ b/drivers/md/dm-verity-verify-sig.c @@ -8,7 +8,10 @@ #include #include #include +#include +#include #include +#include "dm-core.h" #include "dm-verity.h" #include "dm-verity-verify-sig.h" @@ -182,6 +185,10 @@ int verity_verify_root_hash(const struct dm_verity *v) goto cleanup; sig_target->passed = true; + + ret = security_bdev_setsecurity(dm_table_get_md(v->ti->table)->bdev, + DM_VERITY_SIGNATURE_SEC_NAME, + v->sig->sig, v->sig->sig_size); cleanup: kfree(root_hash); return ret; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 475668c69dbc..6bd49aa48186 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -624,4 +624,6 @@ static inline unsigned long to_bytes(sector_t n) return (n << SECTOR_SHIFT); } +#define DM_VERITY_SIGNATURE_SEC_NAME DM_NAME ".verity-sig" + #endif /* _LINUX_DEVICE_MAPPER_H */ From patchwork Mon Apr 6 17:59:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deven Bowers X-Patchwork-Id: 11476109 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3DFB01871 for ; Mon, 6 Apr 2020 17:59:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1CCE32080C for ; Mon, 6 Apr 2020 17:59:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="Jf2vXjtr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726787AbgDFR72 (ORCPT ); Mon, 6 Apr 2020 13:59:28 -0400 Received: from linux.microsoft.com ([13.77.154.182]:51786 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727384AbgDFR71 (ORCPT ); Mon, 6 Apr 2020 13:59:27 -0400 Received: from dede-linux.corp.microsoft.com (unknown [131.107.147.242]) by linux.microsoft.com (Postfix) with ESMTPSA id C84F320A0860; Mon, 6 Apr 2020 10:59:24 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com C84F320A0860 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1586195964; bh=J3qVYWCqUcJEAIFBjrtYylPYF/G4EVx/RPwLWF72lKA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Jf2vXjtrUkyPWgad4i5OiXQh+Yc2KNO/Ntd8ojn57kMlFFp0EqFsB+/+hO6UxTR5S pGgVSoDk2MrY2b2DqPW2U7PVTEC38HqPiqtqV/vGhP/0nQiFOOCTwbgVqQ+dvye7+F YpxcidYCcYUrucEyJEw4XGY20wN1ne4o3tFu5Dd0= From: deven.desai@linux.microsoft.com To: agk@redhat.com, axboe@kernel.dk, snitzer@redhat.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, dm-devel@redhat.org, linux-block@vger.kernel.org Cc: tyhicks@linux.microsoft.com, pasha.tatashin@soleen.com, mdsakib@microsoft.com, sashal@kernel.org, jaskarankhurana@linux.microsoft.com, nramas@linux.microsoft.com Subject: [PATCH 07/11] ipe: add property for signed dmverity volumes Date: Mon, 6 Apr 2020 10:59:15 -0700 Message-Id: <20200406175919.1023205-9-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> References: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: Deven Bowers Allow IPE to leverage the stacked security blob infrastructure, and enlighten IPE to the block_device security blob. This allows IPE to have a property to express rules around a device-mapper verity volume whose root-hash has been signed, and the signature has been verified against the system keyring. This is property is also added in this patch. Signed-off-by: Deven Bowers --- security/ipe/Kconfig | 2 +- security/ipe/Makefile | 1 + security/ipe/ipe-blobs.c | 80 +++++++++++++++++++ security/ipe/ipe-blobs.h | 18 +++++ security/ipe/ipe-engine.c | 4 + security/ipe/ipe-engine.h | 9 +++ security/ipe/ipe-hooks.c | 1 + security/ipe/ipe-hooks.h | 43 ++++++++++ security/ipe/ipe.c | 18 +++++ security/ipe/ipe.h | 2 + security/ipe/properties/Kconfig | 10 +++ security/ipe/properties/Makefile | 1 + security/ipe/properties/dmverity-signature.c | 84 ++++++++++++++++++++ security/ipe/properties/prop-entry.h | 9 +++ security/ipe/utility.h | 10 +++ 15 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 security/ipe/ipe-blobs.c create mode 100644 security/ipe/ipe-blobs.h create mode 100644 security/ipe/properties/dmverity-signature.c diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig index b1d89244da3e..2c3012a6047b 100644 --- a/security/ipe/Kconfig +++ b/security/ipe/Kconfig @@ -5,7 +5,7 @@ menuconfig SECURITY_IPE bool "Integrity Policy Enforcement (IPE)" - depends on SECURITY && AUDIT && SECURITYFS + depends on SECURITY && AUDIT && SECURITYFS && BLOCK select SYSTEM_DATA_VERIFICATION help This option enables the Integrity Policy Enforcement subsystem, diff --git a/security/ipe/Makefile b/security/ipe/Makefile index 741914ddc338..615797f4cd38 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_SECURITY_IPE) += \ ipe-hooks.o \ ipe-secfs.o \ ipe-sysfs.o \ + ipe-blobs.o \ clean-files := ipe-bp.c diff --git a/security/ipe/ipe-blobs.c b/security/ipe/ipe-blobs.c new file mode 100644 index 000000000000..a4ee8df02855 --- /dev/null +++ b/security/ipe/ipe-blobs.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include "ipe.h" +#include "ipe-engine.h" +#include "ipe-blobs.h" + +#include +#include +#include + +/** + * ipe_bdev_alloc_security: Performs the initialization of IPE's security blob. + * @bdev: The block device to source the security blob from. + * + * The allocation is performed earlier by the LSM infrastructure, + * (on behalf of all LSMs) in lsm_alloc_bdev. At the moment, IPE uses + * this time to zero out the region of memory reserved for IPE. + * + * Return: + * 0 - OK + */ +int ipe_bdev_alloc_security(struct block_device *bdev) +{ + struct ipe_bdev_blob *bdev_sec = ipe_bdev(bdev); + + memset(bdev_sec, 0x0, sizeof(*bdev_sec)); + + return 0; +} + +/** + * ipe_bdev_free_security: Frees all fields of IPE's block dev security blob. + * @bdev: The block device to source the security blob from. + * + * The deallocation of the blob itself is performed later by the LSM + * infrastructure, (on behalf of all LSMs) in lsm_free_bdev. + * + * Pointers allocated by the bdev_setsecurity hook and alloc_security + * hook need to be deallocated here. + */ +void ipe_bdev_free_security(struct block_device *bdev) +{ + struct ipe_bdev_blob *bdev_sec = ipe_bdev(bdev); + + memset(bdev_sec, 0x0, sizeof(*bdev_sec)); +} + +/** + * ipe_bdev_setsecurity: Sets the a certain field of a block device security + * blob, based on @key. + * @bdev: The block device to source the security blob from. + * @key: The key representing the information to be stored. + * @value: The value to be stored. + * @len: The length of @value. + * + * As block-devices are a generic implementation across specific stacks, + * this allows information to be stored from various stacks. + * + * Return: + * 0 - OK + * !0 - Error + */ +int ipe_bdev_setsecurity(struct block_device *bdev, const char *key, + const void *value, size_t len) +{ + struct ipe_bdev_blob *bdev_sec = ipe_bdev(bdev); + + if (!strcmp(key, DM_VERITY_SIGNATURE_SEC_NAME)) { + bdev_sec->dmverity_rh_sig = kmemdup(value, len, GFP_KERNEL); + if (!bdev_sec->dmverity_rh_sig) + return -ENOMEM; + + bdev_sec->dmv_rh_sig_len = len; + } + + return 0; +} diff --git a/security/ipe/ipe-blobs.h b/security/ipe/ipe-blobs.h new file mode 100644 index 000000000000..7561f4cef558 --- /dev/null +++ b/security/ipe/ipe-blobs.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ +#include +#include + +#include "ipe.h" + +#ifndef IPE_BLOB_H +#define IPE_BLOB_H + +static inline struct ipe_bdev_blob *ipe_bdev(struct block_device *bdev) +{ + return bdev->security + ipe_blobs.lbs_bdev; +} + +#endif /* IPE_BLOB_H */ diff --git a/security/ipe/ipe-engine.c b/security/ipe/ipe-engine.c index a629ae3c882d..43757bbb1fbf 100644 --- a/security/ipe/ipe-engine.c +++ b/security/ipe/ipe-engine.c @@ -10,6 +10,7 @@ #include "ipe-engine.h" #include "ipe-audit.h" #include "ipe-pin.h" +#include "ipe-blobs.h" #include "utility.h" #include @@ -122,6 +123,9 @@ static struct ipe_engine_ctx *build_ctx(const struct file *file, local->op = op; local->hook = hook; + if (has_bdev(file)) + local->sec_bdev = ipe_bdev(bdev(file)); + return local; } diff --git a/security/ipe/ipe-engine.h b/security/ipe/ipe-engine.h index 3f7c471929e2..be17115861cb 100644 --- a/security/ipe/ipe-engine.h +++ b/security/ipe/ipe-engine.h @@ -3,20 +3,29 @@ * Copyright (C) Microsoft Corporation. All rights reserved. */ +#include "ipe.h" #include "ipe-hooks.h" #include #include #include +#include + #ifndef IPE_ENGINE_H #define IPE_ENGINE_H +struct ipe_bdev_blob { + u8 *dmverity_rh_sig; + size_t dmv_rh_sig_len; +}; + struct ipe_engine_ctx { enum ipe_op op; enum ipe_hook hook; const struct file *file; const char *audit_pathname; + const struct ipe_bdev_blob *sec_bdev; }; struct ipe_prop_cache { diff --git a/security/ipe/ipe-hooks.c b/security/ipe/ipe-hooks.c index 43182ba25cc5..f9728c96d73c 100644 --- a/security/ipe/ipe-hooks.c +++ b/security/ipe/ipe-hooks.c @@ -15,6 +15,7 @@ #include #include #include +#include #define HAS_EXEC(_p, _rp) (((_rp) & PROT_EXEC) || ((_p) & PROT_EXEC)) diff --git a/security/ipe/ipe-hooks.h b/security/ipe/ipe-hooks.h index 55e417c72425..35a7a681b4c6 100644 --- a/security/ipe/ipe-hooks.h +++ b/security/ipe/ipe-hooks.h @@ -113,4 +113,47 @@ int ipe_on_kernel_load_data(enum kernel_load_data_id id); void ipe_sb_free_security(struct super_block *mnt_sb); +/** + * ipe_bdev_alloc_security: Performs the initialization of IPE's security blob. + * @bdev: The block device to source the security blob from. + * + * The allocation is performed earlier by the LSM infrastructure, + * (on behalf of all LSMs) in lsm_alloc_bdev. At the moment, IPE uses + * this time to zero out the region of memory reserved for IPE. + * + * Return: + * 0 - OK + */ +int ipe_bdev_alloc_security(struct block_device *bdev); + +/** + * ipe_bdev_free_security: Frees all fields of IPE's block dev security blob. + * @bdev: The block device to source the security blob from. + * + * The deallocation of the blob itself is performed later by the LSM + * infrastructure, (on behalf of all LSMs) in lsm_free_bdev. + * + * Pointers allocated by the bdev_setsecurity hook and alloc_security + * hook need to be deallocated here. + */ +void ipe_bdev_free_security(struct block_device *bdev); + +/** + * ipe_bdev_setsecurity: Sets the a certain field of a block device security + * blob, based on @key. + * @bdev: The block device to source the security blob from. + * @key: The key representing the information to be stored. + * @value: The value to be stored. + * @len: The length of @value. + * + * As block-devices are a generic implementation across specific stacks, + * this allows information to be stored from various stacks. + * + * Return: + * 0 - OK + * !0 - Error + */ +int ipe_bdev_setsecurity(struct block_device *bdev, const char *key, + const void *value, size_t len); + #endif /* IPE_HOOK_H */ diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c index 971c50ecadaf..924f535c3d32 100644 --- a/security/ipe/ipe.c +++ b/security/ipe/ipe.c @@ -25,6 +25,9 @@ static struct security_hook_list ipe_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(kernel_load_data, ipe_on_kernel_load_data), LSM_HOOK_INIT(file_mprotect, ipe_on_mprotect), LSM_HOOK_INIT(sb_free_security, ipe_sb_free_security), + LSM_HOOK_INIT(bdev_alloc_security, ipe_bdev_alloc_security), + LSM_HOOK_INIT(bdev_free_security, ipe_bdev_free_security), + LSM_HOOK_INIT(bdev_setsecurity, ipe_bdev_setsecurity), }; /** @@ -42,6 +45,10 @@ static int __init ipe_load_properties(void) if (rc != 0) return rc; + rc = ipe_init_dm_verity_signature(); + if (rc != 0) + return rc; + return rc; } @@ -80,9 +87,20 @@ static int __init ipe_init(void) return rc; } +struct lsm_blob_sizes ipe_blobs = { + .lbs_cred = 0, + .lbs_file = 0, + .lbs_inode = 0, + .lbs_ipc = 0, + .lbs_msg_msg = 0, + .lbs_task = 0, + .lbs_bdev = sizeof(struct ipe_bdev_blob), +}; + DEFINE_LSM(ipe) = { .name = "ipe", .init = ipe_init, + .blobs = &ipe_blobs, }; int enforce = 1; diff --git a/security/ipe/ipe.h b/security/ipe/ipe.h index c016b57aa70b..117ee549861c 100644 --- a/security/ipe/ipe.h +++ b/security/ipe/ipe.h @@ -10,10 +10,12 @@ #include #include +#include #define IPE_MODE_ENFORCE "enforce" #define IPE_MODE_PERMISSIVE "permissive" +extern struct lsm_blob_sizes ipe_blobs; extern int enforce; extern int success_audit; extern int strict_parse; diff --git a/security/ipe/properties/Kconfig b/security/ipe/properties/Kconfig index 9dc0db8817b2..2d8866ee456e 100644 --- a/security/ipe/properties/Kconfig +++ b/security/ipe/properties/Kconfig @@ -12,3 +12,13 @@ config IPE_BOOT_PROP being evaluated originates from the initial superblock. if unsure, answer N. + +config IPE_DM_VERITY_SIGNATURE + bool "Enable property for signature verified dm-verity volumes" + depends on DM_VERITY_VERIFY_ROOTHASH_SIG + help + This option enables IPE's integration with Device-Mapper Verity's + signed root-hashes. This enables the usage of the property, + "dmverity_signature" in IPE's policy. + + if unsure, answer Y. diff --git a/security/ipe/properties/Makefile b/security/ipe/properties/Makefile index e3e7fe17cf58..6b67cbe36e31 100644 --- a/security/ipe/properties/Makefile +++ b/security/ipe/properties/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_SECURITY_IPE) += properties.o properties-$(CONFIG_IPE_BOOT_PROP) += boot-verified.o +properties-$(CONFIG_IPE_DM_VERITY_SIGNATURE) += dmverity-signature.o diff --git a/security/ipe/properties/dmverity-signature.c b/security/ipe/properties/dmverity-signature.c new file mode 100644 index 000000000000..448e3b8fd43e --- /dev/null +++ b/security/ipe/properties/dmverity-signature.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include "../ipe.h" +#include "../ipe-pin.h" +#include "../ipe-property.h" +#include "../utility.h" + +#include +#include +#include +#include +#include + +#define PROPERTY_NAME "dmverity_signature" + +static void audit(struct audit_buffer *ab, bool value) +{ + audit_log_format(ab, "%s", (value) ? "TRUE" : "FALSE"); +} + +static inline void audit_rule_value(struct audit_buffer *ab, + const void *value) +{ + audit(ab, (bool)value); +} + +static inline void audit_ctx(struct audit_buffer *ab, + const struct ipe_engine_ctx *ctx, + const void *storage) +{ + bool b = has_bdev(ctx->file) && ctx->sec_bdev->dmverity_rh_sig; + + audit(ab, b); +} + +static bool evaluate(const struct ipe_engine_ctx *ctx, + const void *value, void **storage) +{ + bool expect = (bool)value; + + if (!has_bdev(ctx->file)) + return false; + + return ((bool)ctx->sec_bdev->dmverity_rh_sig) == expect; +} + +static int parse(const char *val_str, void **value) +{ + if (strcmp("TRUE", val_str) == 0) + *value = (void *)true; + else if (strcmp("FALSE", val_str) == 0) + *value = (void *)false; + else + return -EBADMSG; + + return 0; +} + +static inline int duplicate(const void *src, void **dest) +{ + *dest = (void *)(bool)src; + + return 0; +} + +static const struct ipe_property dmv_signature = { + .property_name = PROPERTY_NAME, + .eval = evaluate, + .parse = parse, + .rule_audit = audit_rule_value, + .ctx_audit = audit_ctx, + .dup = duplicate, + .prealloc = NULL, + .free_val = NULL, + .free_storage = NULL, +}; + +int ipe_init_dm_verity_signature(void) +{ + return ipe_register_property(&dmv_signature); +} diff --git a/security/ipe/properties/prop-entry.h b/security/ipe/properties/prop-entry.h index f598dd9608b9..85366366ff0d 100644 --- a/security/ipe/properties/prop-entry.h +++ b/security/ipe/properties/prop-entry.h @@ -17,4 +17,13 @@ static inline int __init ipe_init_bootv(void) int __init ipe_init_bootv(void); #endif /* CONFIG_IPE_BOOT_PROP */ +#ifndef CONFIG_IPE_DM_VERITY_SIGNATURE +static inline int __init ipe_init_dm_verity_signature(void) +{ + return 0; +} +#else +int __init ipe_init_dm_verity_signature(void); +#endif /* CONFIG_IPE_DM_VERITY_SIGNATURE */ + #endif /* IPE_PROP_ENTRY_H */ diff --git a/security/ipe/utility.h b/security/ipe/utility.h index a13089bb0d8f..7580f17274a3 100644 --- a/security/ipe/utility.h +++ b/security/ipe/utility.h @@ -19,4 +19,14 @@ static inline bool has_sb(const struct file *file) return has_mount(file) && file->f_path.mnt->mnt_sb; } +static inline bool has_bdev(const struct file *file) +{ + return has_sb(file) && file->f_path.mnt->mnt_sb->s_bdev; +} + +static inline struct block_device *bdev(const struct file *file) +{ + return file->f_path.mnt->mnt_sb->s_bdev; +} + #endif /* IPE_UTILITY_H */ From patchwork Mon Apr 6 17:59:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deven Bowers X-Patchwork-Id: 11476145 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 299FF92C for ; Mon, 6 Apr 2020 17:59:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0610E2080C for ; Mon, 6 Apr 2020 17:59:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="Anb+ZcpK" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727547AbgDFR7a (ORCPT ); Mon, 6 Apr 2020 13:59:30 -0400 Received: from linux.microsoft.com ([13.77.154.182]:51784 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727464AbgDFR71 (ORCPT ); Mon, 6 Apr 2020 13:59:27 -0400 Received: from dede-linux.corp.microsoft.com (unknown [131.107.147.242]) by linux.microsoft.com (Postfix) with ESMTPSA id 08C8C20A0869; Mon, 6 Apr 2020 10:59:25 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 08C8C20A0869 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1586195965; bh=vtS7tZDadPt65wOWMS99/Fu0/Y/o77wsMAmWG3vccKc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Anb+ZcpKqEx5X6UGRlLRFsH+SwoEhxlh8lU8V6+QARcVo2Q4tGzDnrv8ZwLKU1nnH c8DdYmDxgYCEfeYpSPvyQxbuWJp5iwWVSWfl6TebleWswh6TYhCLpi+K6vS0G0m1sN UcY/lF9m2UB8O2YG8p+HvhKeZolN5B4QE+FNbaEg= From: deven.desai@linux.microsoft.com To: agk@redhat.com, axboe@kernel.dk, snitzer@redhat.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, dm-devel@redhat.org, linux-block@vger.kernel.org Cc: tyhicks@linux.microsoft.com, pasha.tatashin@soleen.com, mdsakib@microsoft.com, sashal@kernel.org, jaskarankhurana@linux.microsoft.com, nramas@linux.microsoft.com Subject: [PATCH 08/11] dm-verity: add bdev_setsecurity hook for root-hash Date: Mon, 6 Apr 2020 10:59:16 -0700 Message-Id: <20200406175919.1023205-10-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> References: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: Deven Bowers Add a security hook call to set a security property of a block_device in dm-verity with the root-hash that was verified to match the merkel-tree. Signed-off-by: Deven Bowers --- drivers/md/dm-verity-target.c | 8 ++++++++ include/linux/device-mapper.h | 1 + 2 files changed, 9 insertions(+) diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index c507f3a4e237..225f67ab378d 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -16,8 +16,10 @@ #include "dm-verity.h" #include "dm-verity-fec.h" #include "dm-verity-verify-sig.h" +#include "dm-core.h" #include #include +#include #define DM_MSG_PREFIX "verity" @@ -530,6 +532,12 @@ static int verity_verify_io(struct dm_verity_io *io) return -EIO; } + r = security_bdev_setsecurity(dm_table_get_md(v->ti->table)->bdev, + DM_VERITY_ROOTHASH_SEC_NAME, + v->root_digest, v->digest_size); + if (unlikely(r < 0)) + return r; + /* * At this point, the merkel tree has finished validating. * if signature was specified, validate the signature here. diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 6bd49aa48186..467db44de194 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -625,5 +625,6 @@ static inline unsigned long to_bytes(sector_t n) } #define DM_VERITY_SIGNATURE_SEC_NAME DM_NAME ".verity-sig" +#define DM_VERITY_ROOTHASH_SEC_NAME DM_NAME ".verity-rh" #endif /* _LINUX_DEVICE_MAPPER_H */ From patchwork Mon Apr 6 17:59:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deven Bowers X-Patchwork-Id: 11476133 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0A0AE1871 for ; Mon, 6 Apr 2020 17:59:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DCC9E206F8 for ; Mon, 6 Apr 2020 17:59:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="YN+5QGFU" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727737AbgDFR7a (ORCPT ); Mon, 6 Apr 2020 13:59:30 -0400 Received: from linux.microsoft.com ([13.77.154.182]:51826 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727522AbgDFR71 (ORCPT ); Mon, 6 Apr 2020 13:59:27 -0400 Received: from dede-linux.corp.microsoft.com (unknown [131.107.147.242]) by linux.microsoft.com (Postfix) with ESMTPSA id 3A9F220A086C; Mon, 6 Apr 2020 10:59:25 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 3A9F220A086C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1586195965; bh=L7uml37MoS+awBVHHXkHfOMwrRofUR0ZftwnIyeletc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YN+5QGFUHVF/9Up4jNgWE24VzWQT5cKwPUzT4arw12uZ/lgaWvXPcrMjFM7uecOcB kwB4MdagDBrR7KXnflg41CFB2cJZQS/dY6cNaxf+nG3BmNwn4c17Mx5Vzqdrn+qxYb YNqE8C65PyqnL+FaKMk9mstrdBJgF77VeM45LI3E= From: deven.desai@linux.microsoft.com To: agk@redhat.com, axboe@kernel.dk, snitzer@redhat.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, dm-devel@redhat.org, linux-block@vger.kernel.org Cc: tyhicks@linux.microsoft.com, pasha.tatashin@soleen.com, mdsakib@microsoft.com, sashal@kernel.org, jaskarankhurana@linux.microsoft.com, nramas@linux.microsoft.com Subject: [PATCH 09/11] ipe: add property for dmverity roothash Date: Mon, 6 Apr 2020 10:59:17 -0700 Message-Id: <20200406175919.1023205-11-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> References: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: Deven Bowers Add a property to allow IPE policy to express rules around a specific root-hash of a dm-verity volume. This can be used for revocation, (when combined with the previous dm-verity property) or the authorization of a single dm-verity volume. Signed-off-by: Deven Bowers --- security/ipe/ipe-blobs.c | 10 ++ security/ipe/ipe-engine.h | 3 + security/ipe/ipe.c | 4 + security/ipe/properties/Kconfig | 13 +- security/ipe/properties/Makefile | 1 + security/ipe/properties/dmverity-roothash.c | 155 ++++++++++++++++++++ security/ipe/properties/prop-entry.h | 9 ++ 7 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 security/ipe/properties/dmverity-roothash.c diff --git a/security/ipe/ipe-blobs.c b/security/ipe/ipe-blobs.c index a4ee8df02855..1e054eb13857 100644 --- a/security/ipe/ipe-blobs.c +++ b/security/ipe/ipe-blobs.c @@ -45,6 +45,8 @@ void ipe_bdev_free_security(struct block_device *bdev) { struct ipe_bdev_blob *bdev_sec = ipe_bdev(bdev); + kfree(bdev_sec->dmverity_rh); + memset(bdev_sec, 0x0, sizeof(*bdev_sec)); } @@ -76,5 +78,13 @@ int ipe_bdev_setsecurity(struct block_device *bdev, const char *key, bdev_sec->dmv_rh_sig_len = len; } + if (!strcmp(key, DM_VERITY_ROOTHASH_SEC_NAME)) { + bdev_sec->dmverity_rh = kmemdup(value, len, GFP_KERNEL); + if (!bdev_sec->dmverity_rh) + return -ENOMEM; + + bdev_sec->rh_size = len; + } + return 0; } diff --git a/security/ipe/ipe-engine.h b/security/ipe/ipe-engine.h index be17115861cb..d8cdb3cc7af8 100644 --- a/security/ipe/ipe-engine.h +++ b/security/ipe/ipe-engine.h @@ -18,6 +18,9 @@ struct ipe_bdev_blob { u8 *dmverity_rh_sig; size_t dmv_rh_sig_len; + + u8 *dmverity_rh; + size_t rh_size; }; struct ipe_engine_ctx { diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c index 924f535c3d32..b398eafa6049 100644 --- a/security/ipe/ipe.c +++ b/security/ipe/ipe.c @@ -49,6 +49,10 @@ static int __init ipe_load_properties(void) if (rc != 0) return rc; + rc = ipe_init_dm_verity_rh(); + if (rc != 0) + return rc; + return rc; } diff --git a/security/ipe/properties/Kconfig b/security/ipe/properties/Kconfig index 2d8866ee456e..57b97b2b3877 100644 --- a/security/ipe/properties/Kconfig +++ b/security/ipe/properties/Kconfig @@ -13,8 +13,19 @@ config IPE_BOOT_PROP if unsure, answer N. +config IPE_DM_VERITY_ROOTHASH + bool "Enable property for authorizing dm-verity volumes via root-hash" + depends on DM_VERITY + help + This option enables IPE's integration with Device-Mapper Verity. + This enables the usage of the property "dmverity_roothash" in IPE's + policy. This property allows authorization or revocation via a + a hex-string representing the roothash of a dmverity volume. + + if unsure, answer Y. + config IPE_DM_VERITY_SIGNATURE - bool "Enable property for signature verified dm-verity volumes" + bool "Enable property for verified dm-verity volumes" depends on DM_VERITY_VERIFY_ROOTHASH_SIG help This option enables IPE's integration with Device-Mapper Verity's diff --git a/security/ipe/properties/Makefile b/security/ipe/properties/Makefile index 6b67cbe36e31..d9a3807797f4 100644 --- a/security/ipe/properties/Makefile +++ b/security/ipe/properties/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_SECURITY_IPE) += properties.o properties-$(CONFIG_IPE_BOOT_PROP) += boot-verified.o properties-$(CONFIG_IPE_DM_VERITY_SIGNATURE) += dmverity-signature.o +properties-$(CONFIG_IPE_DM_VERITY_ROOTHASH) += dmverity-roothash.o diff --git a/security/ipe/properties/dmverity-roothash.c b/security/ipe/properties/dmverity-roothash.c new file mode 100644 index 000000000000..5c575fc275bc --- /dev/null +++ b/security/ipe/properties/dmverity-roothash.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Microsoft Corporation. All rights reserved. + */ + +#include "../ipe.h" +#include "../ipe-pin.h" +#include "../ipe-property.h" +#include "../utility.h" + +#include +#include +#include +#include +#include +#include + +#define PROPERTY_NAME "dmverity_roothash" + +struct counted_array { + u8 *arr; + size_t len; +}; + +static void audit(struct audit_buffer *ab, const void *value) +{ + const struct counted_array *a = (const struct counted_array *)value; + + if (!a || a->len == 0) + audit_log_format(ab, "NULL"); + else + audit_log_n_hex(ab, a->arr, a->len); +} + +static inline void audit_rule_value(struct audit_buffer *ab, + const void *value) +{ + audit(ab, value); +} + +static inline void audit_ctx(struct audit_buffer *ab, + const struct ipe_engine_ctx *ctx, + const void *storage) +{ + struct counted_array a; + + if (!has_bdev(ctx->file)) + return audit(ab, NULL); + + a.arr = ctx->sec_bdev->dmverity_rh; + a.len = ctx->sec_bdev->rh_size; + + return audit(ab, &a); +} + +static bool evaluate(const struct ipe_engine_ctx *ctx, + const void *value, void **storage) +{ + const struct counted_array *a = (const struct counted_array *)value; + + if (!has_bdev(ctx->file)) + return false; + + if (a->len != ctx->sec_bdev->rh_size) + return false; + + return memcmp(a->arr, ctx->sec_bdev->dmverity_rh, a->len) == 0; +} + +static int parse(const char *val_str, void **value) +{ + struct counted_array *arr = NULL; + int rv = 0; + + arr = kzalloc(sizeof(*arr), GFP_KERNEL); + if (!arr) { + rv = -ENOMEM; + goto err; + } + + arr->len = strlen(val_str) / 2; + + arr->arr = kzalloc(arr->len, GFP_KERNEL); + if (!arr->arr) { + rv = -ENOMEM; + goto err; + } + + rv = hex2bin(arr->arr, val_str, arr->len); + if (rv != 0) + goto err; + + *value = arr; + return rv; +err: + if (arr) + kfree(arr->arr); + kfree(arr); + return rv; +} + +static int duplicate(const void *src, void **dest) +{ + struct counted_array *arr = NULL; + const struct counted_array *src_arr = src; + int rv = 0; + + arr = kmemdup(src_arr, sizeof(*arr), GFP_KERNEL); + if (!arr) { + rv = -ENOMEM; + goto err; + } + + arr->arr = kmemdup(src_arr->arr, src_arr->len, GFP_KERNEL); + if (!arr->arr) { + rv = -ENOMEM; + goto err; + } + + *dest = arr; + return rv; +err: + if (arr) + kfree(arr->arr); + kfree(arr); + + return rv; +} + +static void free_val(void **value) +{ + struct counted_array *a = (struct counted_array *)*value; + + if (a) + kfree(a->arr); + kfree(a); + *value = NULL; +} + +static const struct ipe_property dmv_roothash = { + .property_name = PROPERTY_NAME, + .eval = evaluate, + .parse = parse, + .rule_audit = audit_rule_value, + .ctx_audit = audit_ctx, + .dup = duplicate, + .free_val = free_val, + .prealloc = NULL, + .free_storage = NULL, +}; + +int ipe_init_dm_verity_rh(void) +{ + return ipe_register_property(&dmv_roothash); +} diff --git a/security/ipe/properties/prop-entry.h b/security/ipe/properties/prop-entry.h index 85366366ff0d..86a360570f3b 100644 --- a/security/ipe/properties/prop-entry.h +++ b/security/ipe/properties/prop-entry.h @@ -26,4 +26,13 @@ static inline int __init ipe_init_dm_verity_signature(void) int __init ipe_init_dm_verity_signature(void); #endif /* CONFIG_IPE_DM_VERITY_SIGNATURE */ +#ifndef CONFIG_IPE_DM_VERITY_ROOTHASH +static inline int __init ipe_init_dm_verity_rh(void) +{ + return 0; +} +#else +int __init ipe_init_dm_verity_rh(void); +#endif /* CONFIG_IPE_DM_VERITY_ROOTHASH */ + #endif /* IPE_PROP_ENTRY_H */ From patchwork Mon Apr 6 17:59:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deven Bowers X-Patchwork-Id: 11476115 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C64B418C6 for ; Mon, 6 Apr 2020 17:59:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A212920678 for ; Mon, 6 Apr 2020 17:59:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="PdyZgzPS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727376AbgDFR73 (ORCPT ); Mon, 6 Apr 2020 13:59:29 -0400 Received: from linux.microsoft.com ([13.77.154.182]:51832 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727547AbgDFR72 (ORCPT ); Mon, 6 Apr 2020 13:59:28 -0400 Received: from dede-linux.corp.microsoft.com (unknown [131.107.147.242]) by linux.microsoft.com (Postfix) with ESMTPSA id 770F820B4737; Mon, 6 Apr 2020 10:59:25 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 770F820B4737 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1586195965; bh=pUlxPOjKC4KTSLx80keIuhKm7Wh1PV8nyWmrGSnsMTQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PdyZgzPSKDsP76t670uqTR72MmJx8V5Q/ul7E55Zn49J/nHmjUDSvhPAOJkNgodyk a3kHgV6FHH1yWId6H13DlPAyn9DA1R7WV0nqCx5JIWa7PCiGoRn26AcbWcEXuGbT93 PTsJyoUT2bjmUAeZAfD3L+ft5GUNP8OCgDZvZeZY= From: deven.desai@linux.microsoft.com To: agk@redhat.com, axboe@kernel.dk, snitzer@redhat.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, dm-devel@redhat.org, linux-block@vger.kernel.org Cc: tyhicks@linux.microsoft.com, pasha.tatashin@soleen.com, mdsakib@microsoft.com, sashal@kernel.org, jaskarankhurana@linux.microsoft.com, nramas@linux.microsoft.com Subject: [PATCH 10/11] documentation: Add IPE Documentation Date: Mon, 6 Apr 2020 10:59:18 -0700 Message-Id: <20200406175919.1023205-12-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> References: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: Deven Bowers Add IPE's documentation to the kernel tree. Signed-off-by: Deven Bowers --- Documentation/admin-guide/LSM/index.rst | 1 + Documentation/admin-guide/LSM/ipe.rst | 487 ++++++++++++++++++ .../admin-guide/kernel-parameters.txt | 20 + MAINTAINERS | 1 + 4 files changed, 509 insertions(+) create mode 100644 Documentation/admin-guide/LSM/ipe.rst diff --git a/Documentation/admin-guide/LSM/index.rst b/Documentation/admin-guide/LSM/index.rst index a6ba95fbaa9f..ce63be6d64ad 100644 --- a/Documentation/admin-guide/LSM/index.rst +++ b/Documentation/admin-guide/LSM/index.rst @@ -47,3 +47,4 @@ subdirectories. tomoyo Yama SafeSetID + ipe diff --git a/Documentation/admin-guide/LSM/ipe.rst b/Documentation/admin-guide/LSM/ipe.rst new file mode 100644 index 000000000000..def353e34288 --- /dev/null +++ b/Documentation/admin-guide/LSM/ipe.rst @@ -0,0 +1,487 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Integrity Policy Enforcement (IPE) +================================== + +Overview +-------- + +IPE is a Linux Security Module, which allows for a configurable policy +to enforce integrity requirements on the whole system. It attempts to +solve the issue of Code Integrity: that any code being executed (or +files being read), are identical to the version that was built by a +trusted source. + +There are multiple implementations within the Linux kernel that solve +some measure of integrity verification. For instance, device-mapper +verity, which ensures integrity for a block device, and fs-verity which +is a system that ensures integrity for a filesystem. What these +implementations lack is a measure of run-time verification that binaries +are sourced from these locations. IPE aims to address this gap. + +IPE is separated between two major components: A configurable policy, +provided by the LSM ("IPE Core"), and deterministic attributes provided +by the kernel to evaluate files against, ("IPE Properties"). + +Use Cases +--------- + +IPE is designed for use is an embedded device with a specific purpose +(e.g. network firewall device in a data center), where all software and +configuration is built and provisioned by the owner. + +Ideally, a system which leverages IPE is not intended for general +purpose computing and does not utilize any software or configuration +built by a third party. An ideal system to leverage IPE has both mutable +and immutable components, however, all binary executable code is +immutable. + +For the highest level of security, platform firmware should verify the +the kernel and optionally the root filesystem (e.g. via U-Boot verified +boot). This allows the entire system to be integrity verified. + +Known Gaps +---------- + +IPE cannot verify the integrity of anonymous executable memory, such as +the trampolines created by gcc closures and libffi, or JIT'd code. +Unfortunately, as this is dynamically generated code, there is no way +for IPE to detect that this code has not been tampered with in +transition from where it was built, to where it is running. As a result, +IPE is incapable of tackling this problem for dynamically generated +code. + +IPE cannot verify the integrity of interpreted languages' programs when +these scripts invoked via `` ``. This is because the +way interpreters execute these files, the scripts themselves are not +evaluated as executable code through one of IPE's hooks. Interpreters +can be enlightened to the usage of IPE by trying to mmap a file into +executable memory (+X), after opening the file and responding to the +error code appropriately. This also applies to included files, or high +value files, such as configuration files of critical system components. +This specific gap is planned on being addressed within IPE. + +Threat Model +------------ + +The threat type addressed by IPE is tampering of executable user-land +code beyond the initially booted kernel, and the initial verification of +kernel modules that are loaded in userland through ``modprobe`` or +``insmod``. + +Tampering violates the property of integrity. IPE's role in mitigating +this threat is to verify the integrity (and authenticity) of all +executable code and to deny their use if integrity verification fails. +IPE generates audit logs which may be utilized to detect integrity +verification failures. + +Tampering threat scenarios include modification or replacement of +executable code by a range of actors including: + +- Insiders with physical access to the hardware +- Insiders with local network access to the system +- Insiders with access to the deployment system +- Compromised internal systems under external control +- Malicious end users of the system +- Compromised end users of the system +- Remote (external) compromise of the system + +IPE does not mitigate threats arising from malicious authorized +developers, or compromised developer tools used by authorized +developers. Additionally, IPE draws hard security boundary between user +mode and kernel mode. As a result, IPE does not provide any protections +against a kernel level exploit, and a kernel-level exploit can disable +or tamper with IPE's protections. + +The root of trust for all of IPE's verifications is the +``SYSTEM_TRUSTED_KEYRING``. + +IPE Core +-------- + +IPE Policy +~~~~~~~~~~ + +IPE policy is designed to be both forward compatible and backwards +compatible. There is one required line, at the top of the policy, +indicating the policy name, and the policy version, for instance: + +:: + + policy_name="Ex Policy" policy_version=0.0.0 + +The policy name is a unique key identifying this policy in a human +readable name. This is used to create nodes under securityfs as well as +uniquely identify policies to deploy new policies vs update existing +policies. + +The policy version indicates the current version of the policy (NOT the +policy syntax version). This is used to prevent roll-back of policy to +potentially insecure previous versions of the policy. + +The next portion of IPE policy, are rules. Rules are formed by key=value +pairs, known as properties. IPE rules require two properties: "action", +which determines what IPE does when it encounters a match against the +rule, and "op", which determines when that rule should be evaluated. +Thus, a minimal rule is: + +:: + + op=EXECUTE action=ALLOW + +This example will allow any execution. Additional properties are used to +restrict attributes about the files being evaluated. These properties +are intended to be deterministic attributes that are resident in the +kernel. + +Order does not matter for the rule's properties - they can be listed in +any order, however it is encouraged to have the "op" property be first, +and the "action" property be last for readability. Rules are evaluated +top-to-bottom. As a result, any revocation rules, or denies should be +placed early in the file to ensure that these rules are evaluated before +as rule with "action=ALLOW" is hit. + +IPE policy is designed to be forward compatible and backwards +compatible, thus any failure to parse a rule will result in the line +being ignored, and a warning being emitted. If backwards compatibility +is not required, the kernel command line parameter and sysctl, +``ipe.strict_parse`` can be enabled, which will cause these warnings to +be fatal. + +IPE policy supports comments. The character '#' will function as a +comment, ignoring all characters to the right of '#' until the newline. + +The default behavior of IPE evaluations can also be expressed in policy, +through the ``DEFAULT`` statement. This can be done at a global level, +or a per-operation level: + +:: + + # Global + DEFAULT action=ALLOW + + # Operation Specific + DEFAULT op=EXECUTE action=ALLOW + +If a global default is unset, and a specific operation default is not +set for an IPE operation, it will assume that the default action should +be ``ALLOW``. This is to preserve compatibility between policies and the +LSM. + +With configurable policy-based LSMs, there's several issues with +enforcing the configurable policies at startup, around reading and +parsing the policy: + +1. The kernel *should* not read files from userland, so directly reading + the policy file is prohibited. +2. The kernel command line has a character limit, and one kernel module + should not reserve the entire character limit for its own + configuration. +3. There are various boot loaders in the kernel ecosystem, so handing + off a memory block would be costly to maintain. + +As a result, IPE has addressed this problem through a concept of a "boot +policy". A boot policy is a minimal policy, compiled into the kernel. +This policy is intended to get the system to a state where userland is +setup and ready to receive commands, at which point a more complex +policy ("user policies") can be deployed via securityfs. The boot policy +can be specified via the Kconfig, ``SECURITY_IPE_BOOT_POLICY``, which +accepts a path to a plain-text version of the IPE policy to apply. This +policy will be compiled into the kernel. If not specified, IPE will be +disabled until a policy is deployed through securityfs, and activated +through sysfs. + +Deploying Policies +^^^^^^^^^^^^^^^^^^ + +User policies as explained above, are policies that are deployed from +userland, through securityfs. These policies are signed to enforce some +level of authorization of the policies (prohibiting an attacker from +gaining root, and deploying an "allow all" policy), through the PKCS#7 +enveloped data format. These policies must be signed by a certificate +that chains to the ``SYSTEM_TRUSTED_KEYRING``. Through openssl, the +signing can be done via: + +:: + + openssl smime -sign -in "$MY_POLICY" -signer "$MY_CERTIFICATE" \ + -inkey "$MY_PRIVATE_KEY" -binary -outform der -noattr -nodetach \ + -out "$MY_POLICY.p7s" + +Deploying the policies is done through securityfs, through the +``new_policy`` node. To deploy a policy, simply cat the file into the +securityfs node: + +:: + + cat "$MY_POLICY.p7s" > /sys/kernel/security/ipe/new_policy + +Upon success, this will create one subdirectory under +``/sys/kernel/security/ipe/policies/``. The subdirectory will be the +``policy_name`` field of the policy deployed, so for the example above, +the directory will be ``/sys/kernel/security/ipe/policies/Ex\ Policy``. +Within this directory, there will be two files: ``raw`` and ``content``. + +The ``raw`` file is rw, reading will provide the raw PKCS#7 data that +was provided to the kernel, representing the policy. Writing, will +deploy an in-place policy update - if this policy is the currently +running policy, the new updated policy will replace it immediately upon +success. + +The ``content`` file is read only. Reading will provide the PKCS#7 inner +content of the policy, which will be the plain text policy. + +Similarly, the ``cat`` command above will result in an error upon +syntactically invalid or untrusted policies. It will also error if a +policy already exists with the same ``policy_name``. The write to the +``raw`` node will error upon syntactically invalid, untrusted policies, +or if the payload fails the version check. The write will also fail if +the ``policy_name`` in the payload does not match the existing policy. + +Deploying these policies will *not* cause IPE to start enforcing this +policy. Once deployment is successful, a policy can be marked as active, +via the sysctl, ``ipe.active_policy``. IPE will enforce whatever policy +is marked as active. For our example, we can activate the ``Ex Policy`` +via: + +:: + + sysctl ipe.active_policy="Ex Policy" + +At which point, ``Ex Policy`` will now be the enforced policy on the +system. + +IPE also provides a way to delete policies. This can be done via the +``del_policy`` securityfs node, ``/sys/kernel/security/ipe/del_policy``. +Writing the ``policy_name`` of the policy to be deleted will delete that +node: + +:: + + echo -n "$MY_POLICY_NAME" > /sys/kernel/security/ipe/del_policy + +There are two requirements to delete policies: + +1. The policy being deleted must not be the active policy. +2. The policy being deleted must not be the boot policy. + +NOTE: It's important to know above that the "echo" command will add a +newline to the end of the input, and this will be considered as part of +the filename. You can remove the newline via the -n parameter. + +Modes +~~~~~ + +IPE supports two modes of operation: permissive (similar to SELinux's +permissive mode) and enforce. Permissive mode performs the same checks +as enforce mode, and logs policy violations, but will not enforce the +policy. This allows users to test policies before enforcing them. + +The default mode is enforce, and can be changed via the kernel command +line parameter ``ipe.enforce=(0|1)``, or the sysctl +``ipe.enforce=(0|1)``. The ability to switch modes can be compiled out +of the LSM via setting the Kconfig +``CONFIG_SECURITY_IPE_PERMISSIVE_SWITCH`` to N. + +Audit Events +~~~~~~~~~~~~ + +Success Auditing +^^^^^^^^^^^^^^^^ + +IPE supports success auditing. When enabled, all events that pass IPE +policy and are not blocked will emit an audit event. This is disabled by +default, and can be enabled via the kernel command line +``ipe.success_audit=(0|1)`` or the sysctl ``ipe.success_audit=(0|1)``. + +This is very noisy, as IPE will check every user-mode binary on the +system, but is useful for debugging policies. + +IPE Properties +-------------- + +As explained above, IPE properties are ``key=value`` pairs expressed in +IPE policy. Two properties are built-into the policy parser: 'op' and +'action'. The other properties are determinstic attributes to express +across files. Currently those properties are: 'boot_verified', +'dmverity_signature', 'dmverity_roothash'. A description of all +properties supported by IPE are listed below: + +op +~~ + +Indicates the operation for a rule to apply to. Must be in every rule. +IPE supports the following operations: + +``EXECUTE`` + + Pertains to any file attempting to be executed, or loaded as an + executable. + +``FIRMWARE``: + + Pertains to firmware being loaded via the firmware_class interface. + This covers both the preallocated buffer and the firmware file + itself. + +``KMODULE``: + + Pertains to loading kernel modules via ``modprobe`` or ``insmod``. + +``KEXEC_IMAGE``: + + Pertains to kernel images loading via ``kexec``. + +``KEXEC_INITRAMFS`` + + Pertains to initrd images loading via ``kexec --initrd``. + +``POLICY``: + + Controls loading IMA policies through the + ``/sys/kernel/security/ima/policy`` securityfs entry. + +``X509_CERT``: + + Controls loading IMA certificates through the Kconfigs, + ``CONFIG_IMA_X509_PATH`` and ``CONFIG_EVM_X509_PATH``. + +action +~~~~~~ + +Determines what IPE should do when a rule matches. Must be in every +rule. Can be one of: + +``ALLOW``: + + If the rule matches, explicitly allow the call to proceed without + executing any more rules. + +``DENY``: + + If the rule matches, explicitly prohibit the call from proceeding + without executing any more rules. + +boot_verified +~~~~~~~~~~~~~ + +This property can be utilized for authorization of the first super-block +that is mounted on the system, where IPE attempts to evaluate a file. +Typically this is used for systems with an initramfs or other initial +disk, where this is unmounted before the system becomes available, and +is not covered by any other property. This property is controlled by the +Kconfig, ``CONFIG_IPE_BOOT_PROP``. The format of this property is: + +:: + + boot_verified=(TRUE|FALSE) + + +.. WARNING:: + + This property will trust any disk where the first IPE + evaluation occurs. If you do not have a startup disk that is + unpacked and unmounted (like initramfs), then it will automatically + trust the root filesystem and potentially overauthorize the entire + disk. + +dmverity_roothash +~~~~~~~~~~~~~~~~~ + +This property can be utilized for authorization or revocation of +specific dm-verity volumes, identified via root hash. It has a +dependency on the DM_VERITY module. This property is controlled by the +property: ``CONFIG_IPE_DM_VERITY_ROOTHASH``. The format of this property +is: + +:: + + dmverity_roothash=HashHexDigest + +dmverity_signature +~~~~~~~~~~~~~~~~~~ + +This property can be utilized for authorization of all dm-verity volumes +that have a signed roothash that chains to the system trusted keyring. +It has a dependency on the ``DM_VERITY_VERIFY_ROOTHASH_SIG`` Kconfig. +This property is controlled by the Kconfig: +``CONFIG_IPE_DM_VERITY_SIGNATURE``. The format of this property is: + +:: + + dmverity_signature=(TRUE|FALSE) + +Policy Examples +--------------- + +Allow all +~~~~~~~~~ + +:: + + policy_name="Allow All" policy_version=0.0.0 + DEFAULT action=ALLOW + +Allow only initial superblock +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + policy_name="Allow All Initial SB" policy_version=0.0.0 + DEFAULT action=DENY + + op=EXECUTE boot_verified=TRUE action=ALLOW + +Allow any signed dm-verity volume and the initial superblock +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + policy_name="AllowSignedAndInitial" policy_version=0.0.0 + DEFAULT action=DENY + + op=EXECUTE boot_verified=TRUE action=ALLOW + op=EXECUTE dmverity_signature=TRUE action=ALLOW + +Prohibit execution from a specific dm-verity volume +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + policy_name="AllowSignedAndInitial" policy_version=0.0.0 + DEFAULT action=DENY + + op=EXECUTE dmverity_roothash=401fcec5944823ae12f62726e8184407a5fa9599783f030dec146938 action=DENY + op=EXECUTE boot_verified=TRUE action=ALLOW + op=EXECUTE dmverity_signature=TRUE action=ALLOW + +Allow only a specific dm-verity volume +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + policy_name="AllowSignedAndInitial" policy_version=0.0.0 + DEFAULT action=DENY + + op=EXECUTE dmverity_roothash=401fcec5944823ae12f62726e8184407a5fa9599783f030dec146938 action=ALLOW + +External Information +-------------------- + +Please see the github repository at: https://github.com/microsoft/Integrity-Policy-Enforcement-LSM + +FAQ +--- + +Q: What's the difference between other LSMs which provide integrity +verification (i.e. IMA)? + +A: IPE differs from other LSMs which provide integrity checking, as it +has no dependency on the filesystem metadata itself. The attributes that +IPE checks are deterministic properties that exist solely in the kernel. +Additionally, IPE provides no additional mechanisms of verifying these +files (e.g. IMA Signatures) - all of the attributes of verifying files +are existing features within the kernel. + +Additionally, IPE is completely restricted to integrity. It offers no +measurement or attestation features, which IMA addresses. diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 4d5a4fe22703..9eb8b19fe9db 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1913,6 +1913,26 @@ ip= [IP_PNP] See Documentation/admin-guide/nfs/nfsroot.rst. + ipe.enforce= [IPE] + Format: { "0" | "1" } + 0 - Start IPE in audit mode + 1 - Start IPE in enforce mode (default). + See Documentation/security/ipe.rst + + ipe.success_audit= + [IPE] Start IPE with success auditing + Format: { "0" | "1" } + 0 - Disable success auditing (default) + 1 - Enable success auditing + See Documentation/security/ipe.rst + + ipe.strict_parse= + [IPE] Start IPE with strict policy parsing enabled + Format: { "0" | "1" } + 0 - Disable strict parsing (default) + 1 - Enable strict parsing + See Documentation/security/ipe.rst + ipcmni_extend [KNL] Extend the maximum number of unique System V IPC identifiers from 32,768 to 16,777,216. diff --git a/MAINTAINERS b/MAINTAINERS index ab9adcd37a0c..897da80af3f8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8441,6 +8441,7 @@ INTEGRITY POLICY ENFORCEMENT (IPE) M: Deven Bowers L: linux-integrity@vger.kernel.org S: Supported +F: Documentation/admin-guide/LSM/ipe.rst F: scripts/ipe/ F: security/ipe/ From patchwork Mon Apr 6 17:59:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deven Bowers X-Patchwork-Id: 11476127 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6955D92C for ; Mon, 6 Apr 2020 17:59:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 47ECC206F8 for ; Mon, 6 Apr 2020 17:59:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="m4RQ3sbP" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727717AbgDFR7a (ORCPT ); Mon, 6 Apr 2020 13:59:30 -0400 Received: from linux.microsoft.com ([13.77.154.182]:51834 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727226AbgDFR71 (ORCPT ); Mon, 6 Apr 2020 13:59:27 -0400 Received: from dede-linux.corp.microsoft.com (unknown [131.107.147.242]) by linux.microsoft.com (Postfix) with ESMTPSA id BFB87207295F; Mon, 6 Apr 2020 10:59:25 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com BFB87207295F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1586195965; bh=FoQEwrrWn/d3Fno/jqMS38zWmUVRke4mJOAaLbjRrY8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=m4RQ3sbP70RlGztgdMxmZ1GdO/7pMzX5CS1tYBSXsCOJpoP7e1ve+lJcF3GYwxQD8 tkzj+maTzWyww5Ar6mLg+n8hu9HtzFKtardh95LU0IYloWf3zccicB1OxAqNKsdpFP uSgRwSh8rq383RkGV8mLYbX13r2wuAa/QB2mDcTg= From: deven.desai@linux.microsoft.com To: agk@redhat.com, axboe@kernel.dk, snitzer@redhat.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, dm-devel@redhat.org, linux-block@vger.kernel.org Cc: tyhicks@linux.microsoft.com, pasha.tatashin@soleen.com, mdsakib@microsoft.com, sashal@kernel.org, jaskarankhurana@linux.microsoft.com, nramas@linux.microsoft.com Subject: [PATCH 11/11] cleanup: uapi/linux/audit.h Date: Mon, 6 Apr 2020 10:59:19 -0700 Message-Id: <20200406175919.1023205-13-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> References: <20200406175919.1023205-1-deven.desai@linux.microsoft.com> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: Deven Bowers Remove trailing whitespaces and align the integrity #defines in linux/uapi/audit.h Signed-off-by: Deven Bowers --- include/uapi/linux/audit.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 4e0122a0ed0c..d642ade068b5 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -48,7 +48,7 @@ * 2500 - 2999 future user space (maybe integrity labels and related events) * * Messages from 1000-1199 are bi-directional. 1200-1299 & 2100 - 2999 are - * exclusively user space. 1300-2099 is kernel --> user space + * exclusively user space. 1300-2099 is kernel --> user space * communication. */ #define AUDIT_GET 1000 /* Get status */ @@ -78,7 +78,7 @@ #define AUDIT_LAST_USER_MSG 1199 #define AUDIT_FIRST_USER_MSG2 2100 /* More user space messages */ #define AUDIT_LAST_USER_MSG2 2999 - + #define AUDIT_DAEMON_START 1200 /* Daemon startup record */ #define AUDIT_DAEMON_END 1201 /* Daemon normal stop record */ #define AUDIT_DAEMON_ABORT 1202 /* Daemon error stop record */ @@ -139,20 +139,20 @@ #define AUDIT_MAC_CALIPSO_ADD 1418 /* NetLabel: add CALIPSO DOI entry */ #define AUDIT_MAC_CALIPSO_DEL 1419 /* NetLabel: del CALIPSO DOI entry */ -#define AUDIT_FIRST_KERN_ANOM_MSG 1700 -#define AUDIT_LAST_KERN_ANOM_MSG 1799 -#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ -#define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */ -#define AUDIT_ANOM_LINK 1702 /* Suspicious use of file links */ -#define AUDIT_ANOM_CREAT 1703 /* Suspicious file creation */ -#define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ -#define AUDIT_INTEGRITY_METADATA 1801 /* Metadata integrity verification */ -#define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ -#define AUDIT_INTEGRITY_HASH 1803 /* Integrity HASH type */ -#define AUDIT_INTEGRITY_PCR 1804 /* PCR invalidation msgs */ -#define AUDIT_INTEGRITY_RULE 1805 /* policy rule */ -#define AUDIT_INTEGRITY_EVM_XATTR 1806 /* New EVM-covered xattr */ -#define AUDIT_INTEGRITY_POLICY_RULE 1807 /* IMA policy rules */ +#define AUDIT_FIRST_KERN_ANOM_MSG 1700 +#define AUDIT_LAST_KERN_ANOM_MSG 1799 +#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ +#define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */ +#define AUDIT_ANOM_LINK 1702 /* Suspicious use of file links */ +#define AUDIT_ANOM_CREAT 1703 /* Suspicious file creation */ +#define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ +#define AUDIT_INTEGRITY_METADATA 1801 /* Metadata integrity verification */ +#define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ +#define AUDIT_INTEGRITY_HASH 1803 /* Integrity HASH type */ +#define AUDIT_INTEGRITY_PCR 1804 /* PCR invalidation msgs */ +#define AUDIT_INTEGRITY_RULE 1805 /* policy rule */ +#define AUDIT_INTEGRITY_EVM_XATTR 1806 /* New EVM-covered xattr */ +#define AUDIT_INTEGRITY_POLICY_RULE 1807 /* IMA policy rules */ #define AUDIT_INTEGRITY_POLICY_LOAD 1808 /* IPE Policy Load */ #define AUDIT_INTEGRITY_POLICY_ACTIVATE 1809 /* IPE Policy Activation */ #define AUDIT_INTEGRITY_EVENT 1810 /* IPE Evaluation Event */