Received: by 2002:a05:7412:3784:b0:e2:908c:2ebd with SMTP id jk4csp2893096rdb; Wed, 4 Oct 2023 15:11:28 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFoIFTtik7ml5Foa681W9c48r2MpQMb5DjECgVH2uYUL9DqRQd6PuivSHdR9JxzFELQ7Ob3 X-Received: by 2002:a17:902:7682:b0:1c7:249f:5e33 with SMTP id m2-20020a170902768200b001c7249f5e33mr3371211pll.46.1696457488537; Wed, 04 Oct 2023 15:11:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696457488; cv=none; d=google.com; s=arc-20160816; b=GwXrzsNa9xXBZfYYbPtHu7eMS9nom/wSvmrj+ZzMKUm1k/h83cahaiyi9BGcDhREqZ vP8iJIVsK0TRLSXj0EcG0XbW3r7r1J2C0c64PIm0sc7tCDztZqTKxuq0MU/A/b/DaQ7C P8/r925q8jP25QloxpwYJKhYFe2ozj0yoOeAjbSXdbl2ViW4AFaHIQT1/7HzKE2N9+JR v6nb5gtzcahZ4pJpuqR/lPd4UZd7sXm9b15QR0h/rl5Xg3sG71ZaXiztsemZQAwSuTM3 pBV4ucBTrcb6eQHcofu6FMDE7XQrd2U1HTn0Q50LYqex0fFQ5OYyB90sjVnkobKSC2KX E4fw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:dkim-signature:dkim-filter; bh=cKSSmS5MjvhxWnrfdrxEcrTWZRLjAMoJm7+XqI4yjHc=; fh=WKOxBQCBkKJEYHNk8gUZtM1FdSmLSIlhHGYfTk9Bdmc=; b=wMsigPUi9DxEHXWIsCD/btZpgDMketxN7p5MuhXO/TfIRK/FzrSPeLvKUfo2eMdg9Q TDf3716aB5gjA5CCqNbIlE5370/BjJcscEUzM4qOHLb2C55m5RmX4CplWEk7S54MX/cY bIXOTO1PCFyOLdASTy8LjVY6VU84q34zsadWRyLjOFwXoBHA27/dv4wM7egJz0n4IfFv i1s7irDZrC31bNBS29HgaP6NZAxZyWJ8d+P3wyFIhGBg9jNuEGCV1dDstBdilJ9Yntpj 0waos3s9nt7uWVGZHl7KPb3rl5sLF0l31hYYLMQBhCa+tdLw33WN5W7DbRanzUTlS+aH jTsQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linux.microsoft.com header.s=default header.b=VOurqwe8; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.microsoft.com Return-Path: Received: from howler.vger.email (howler.vger.email. [2620:137:e000::3:4]) by mx.google.com with ESMTPS id km5-20020a17090327c500b001c3c75842f1si110899plb.14.2023.10.04.15.11.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Oct 2023 15:11:28 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) client-ip=2620:137:e000::3:4; Authentication-Results: mx.google.com; dkim=pass header.i=@linux.microsoft.com header.s=default header.b=VOurqwe8; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.microsoft.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by howler.vger.email (Postfix) with ESMTP id 6C4638021586; Wed, 4 Oct 2023 15:10:45 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at howler.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232566AbjJDWKh (ORCPT + 99 others); Wed, 4 Oct 2023 18:10:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36216 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235063AbjJDWKA (ORCPT ); Wed, 4 Oct 2023 18:10:00 -0400 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 873E2102; Wed, 4 Oct 2023 15:09:55 -0700 (PDT) Received: by linux.microsoft.com (Postfix, from userid 1052) id 2889120B74E1; Wed, 4 Oct 2023 15:09:50 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 2889120B74E1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1696457391; bh=cKSSmS5MjvhxWnrfdrxEcrTWZRLjAMoJm7+XqI4yjHc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VOurqwe8QyNFRVtjJMxg+ddxC2R4di2tBIxG2z13QowNwXQlsq4RF4zvjeGSGEeOv TQOxnr047e000yieSkgiYjuGrwMwkgSdsGhl2vLCOasu+hCNMchK2KSZa1jizOKola NmtRRC7sUWEZhNlpgb9yvmcFjy8JZJxUrzrd9zNk= From: Fan Wu To: corbet@lwn.net, zohar@linux.ibm.com, jmorris@namei.org, serge@hallyn.com, tytso@mit.edu, ebiggers@kernel.org, axboe@kernel.dk, agk@redhat.com, snitzer@kernel.org, eparis@redhat.com, paul@paul-moore.com Cc: linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-block@vger.kernel.org, dm-devel@redhat.com, audit@vger.kernel.org, roberto.sassu@huawei.com, linux-kernel@vger.kernel.org, Deven Bowers , Fan Wu Subject: [RFC PATCH v11 17/19] scripts: add boot policy generation program Date: Wed, 4 Oct 2023 15:09:44 -0700 Message-Id: <1696457386-3010-18-git-send-email-wufan@linux.microsoft.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1696457386-3010-1-git-send-email-wufan@linux.microsoft.com> References: <1696457386-3010-1-git-send-email-wufan@linux.microsoft.com> X-Spam-Status: No, score=-17.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,ENV_AND_HDR_SPF_MATCH,SPF_HELO_PASS,SPF_PASS, URIBL_BLOCKED,USER_IN_DEF_DKIM_WL,USER_IN_DEF_SPF_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (howler.vger.email [0.0.0.0]); Wed, 04 Oct 2023 15:10:45 -0700 (PDT) From: Deven Bowers Enables an IPE policy to be enforced from kernel start, enabling access control based on trust from kernel startup. This is accomplished by transforming an IPE policy indicated by CONFIG_IPE_BOOT_POLICY into a c-string literal that is parsed at kernel startup as an unsigned policy. Signed-off-by: Deven Bowers Signed-off-by: Fan Wu --- v2: + No Changes v3: + No Changes v4: + No Changes v5: + No Changes v6: + No Changes v7: + Move from 01/11 to 14/16 + Don't return errno directly. + Make output of script more user-friendly + Add escaping for tab and '?' + Mark argv pointer const + Invert return code check in the boot policy parsing code path. v8: + No significant changes. v9: + No changes v10: + Update the init part code for rcu changes in the eval loop patch v11: + Fix code style issues --- MAINTAINERS | 1 + scripts/Makefile | 1 + scripts/ipe/Makefile | 2 + scripts/ipe/polgen/.gitignore | 1 + scripts/ipe/polgen/Makefile | 6 ++ scripts/ipe/polgen/polgen.c | 145 ++++++++++++++++++++++++++++++++++ security/ipe/.gitignore | 1 + security/ipe/Kconfig | 10 +++ security/ipe/Makefile | 11 +++ security/ipe/fs.c | 8 ++ security/ipe/ipe.c | 12 +++ 11 files changed, 198 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 create mode 100644 security/ipe/.gitignore diff --git a/MAINTAINERS b/MAINTAINERS index b898f2f8f9c4..18b1aeea6306 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10394,6 +10394,7 @@ M: Fan Wu L: linux-security-module@vger.kernel.org S: Supported T: git https://github.com/microsoft/ipe.git +F: scripts/ipe/ F: security/ipe/ INTEL 810/815 FRAMEBUFFER DRIVER diff --git a/scripts/Makefile b/scripts/Makefile index 576cf64be667..1dbaf3a49aef 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -50,6 +50,7 @@ targets += module.lds 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..066060c22b4a --- /dev/null +++ b/scripts/ipe/polgen/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +hostprogs-always-y := polgen +HOST_EXTRACFLAGS += \ + -I$(srctree)/include \ + -I$(srctree)/include/uapi \ + diff --git a/scripts/ipe/polgen/polgen.c b/scripts/ipe/polgen/polgen.c new file mode 100644 index 000000000000..40b6fe07f47b --- /dev/null +++ b/scripts/ipe/polgen/polgen.c @@ -0,0 +1,145 @@ +// 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) +{ + int rc = 0; + FILE *fd; + size_t i; + + fd = fopen(pathname, "w"); + if (!fd) { + rc = errno; + goto err; + } + + fprintf(fd, "/* This file is automatically generated."); + fprintf(fd, " Do not edit. */\n"); + fprintf(fd, "#include \n"); + fprintf(fd, "\nextern const char *const ipe_boot_policy;\n\n"); + fprintf(fd, "const char *const ipe_boot_policy =\n"); + + if (!buf || size == 0) { + fprintf(fd, "\tNULL;\n"); + fclose(fd); + return 0; + } + + fprintf(fd, "\t\""); + + for (i = 0; i < size; ++i) { + switch (buf[i]) { + case '"': + fprintf(fd, "\\\""); + break; + case '\'': + fprintf(fd, "'"); + break; + case '\n': + fprintf(fd, "\\n\"\n\t\""); + break; + case '\\': + fprintf(fd, "\\\\"); + break; + case '\t': + fprintf(fd, "\\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 rc; +} + +int main(int argc, const char *const 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; +} diff --git a/security/ipe/.gitignore b/security/ipe/.gitignore new file mode 100644 index 000000000000..eca22ad5ed22 --- /dev/null +++ b/security/ipe/.gitignore @@ -0,0 +1 @@ +boot-policy.c \ No newline at end of file diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig index 9dd5c4769d79..a6c5d48dd0a3 100644 --- a/security/ipe/Kconfig +++ b/security/ipe/Kconfig @@ -18,6 +18,16 @@ menuconfig SECURITY_IPE If unsure, answer N. if SECURITY_IPE +config IPE_BOOT_POLICY + string "Integrity policy to apply on system startup" + help + This option specifies a filepath to a IPE policy that is compiled + into the kernel. This policy will be enforced until a policy update + is deployed via the $securityfs/ipe/policies/$policy_name/active + interface. + + If unsure, leave blank. + menu "IPE Trust Providers" config IPE_PROP_DM_VERITY diff --git a/security/ipe/Makefile b/security/ipe/Makefile index 66de53687d11..ce23101b66ba 100644 --- a/security/ipe/Makefile +++ b/security/ipe/Makefile @@ -5,7 +5,16 @@ # Makefile for building the IPE module as part of the kernel tree. # +quiet_cmd_polgen = IPE_POL $(2) + cmd_polgen = scripts/ipe/polgen/polgen security/ipe/boot-policy.c $(2) + +targets += boot-policy.c + +$(obj)/boot-policy.c: scripts/ipe/polgen/polgen $(CONFIG_IPE_BOOT_POLICY) FORCE + $(call if_changed,polgen,$(CONFIG_IPE_BOOT_POLICY)) + obj-$(CONFIG_SECURITY_IPE) += \ + boot-policy.o \ digest.o \ eval.o \ hooks.o \ @@ -15,3 +24,5 @@ obj-$(CONFIG_SECURITY_IPE) += \ policy_fs.o \ policy_parser.o \ audit.o \ + +clean-files := boot-policy.c \ diff --git a/security/ipe/fs.c b/security/ipe/fs.c index 0a1838432bd0..58584c5f3ee4 100644 --- a/security/ipe/fs.c +++ b/security/ipe/fs.c @@ -190,6 +190,7 @@ static const struct file_operations enforce_fops = { static int __init ipe_init_securityfs(void) { int rc = 0; + struct ipe_policy *ap; if (!ipe_enabled) return -EOPNOTSUPP; @@ -220,6 +221,13 @@ static int __init ipe_init_securityfs(void) goto err; } + ap = rcu_access_pointer(ipe_active_policy); + if (ap) { + rc = ipe_new_policyfs_node(ap); + if (rc) + goto err; + } + np = securityfs_create_file("new_policy", 0200, root, NULL, &np_fops); if (IS_ERR(np)) { rc = PTR_ERR(np); diff --git a/security/ipe/ipe.c b/security/ipe/ipe.c index e789f1db6f66..3d672dd57b32 100644 --- a/security/ipe/ipe.c +++ b/security/ipe/ipe.c @@ -7,6 +7,7 @@ #include "hooks.h" #include "eval.h" +extern const char *const ipe_boot_policy; bool ipe_enabled; static struct lsm_blob_sizes ipe_blobs __ro_after_init = { @@ -60,9 +61,20 @@ static struct security_hook_list ipe_hooks[] __ro_after_init = { */ static int __init ipe_init(void) { + struct ipe_policy *p = NULL; + security_add_hooks(ipe_hooks, ARRAY_SIZE(ipe_hooks), "ipe"); ipe_enabled = true; + if (ipe_boot_policy) { + p = ipe_new_policy(ipe_boot_policy, strlen(ipe_boot_policy), + NULL, 0); + if (IS_ERR(p)) + return PTR_ERR(p); + + rcu_assign_pointer(ipe_active_policy, p); + } + return 0; } -- 2.25.1