From patchwork Thu Oct 14 13:08:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dov Murik X-Patchwork-Id: 12558479 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CCDCFC433EF for ; Thu, 14 Oct 2021 13:14:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B154D60F41 for ; Thu, 14 Oct 2021 13:14:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231443AbhJNNQP (ORCPT ); Thu, 14 Oct 2021 09:16:15 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:11308 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230339AbhJNNQP (ORCPT ); Thu, 14 Oct 2021 09:16:15 -0400 Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19ED4kNv023463; Thu, 14 Oct 2021 09:13:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=mSMhS5KuMYXSCCHFWTjt0J4W3hRXJ0JBE2fkifaGDT8=; b=ELieMpXYvHzwWCXV/nG6KZKb/zhit22gYHYEK523A4425R8qIWWASYhf/2wT8jMolaIq f8kaoaLenSCgfHaj1uW4mWSte61Pfeaa8OxW9RpigeKPO7LVNOTZCtJebEFLxPqr40cx YkiHjL1jUqEsVg7GvfbK36R86HQAoULctWIHBhdoagHXmHeh+uiTVRpO+OgYL9e3b7Py 8ViFiEx4gsPcGp4j47Ee14veU/pthAWz4S5BN+im5o6X/rPdbD/eNb2jE0BKJH92bFBi zpMqiL+Yd+3XNcW6sw0JruzcMytihSiTUWF9VgalCrQyZmxFMU+8uteJOXB+OPDkC7kq uA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3bpn3vgbur-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 14 Oct 2021 09:13:59 -0400 Received: from m0098399.ppops.net (m0098399.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 19ED562p024445; Thu, 14 Oct 2021 09:13:58 -0400 Received: from ppma04dal.us.ibm.com (7a.29.35a9.ip4.static.sl-reverse.com [169.53.41.122]) by mx0a-001b2d01.pphosted.com with ESMTP id 3bpn3vgbtx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 14 Oct 2021 09:13:58 -0400 Received: from pps.filterd (ppma04dal.us.ibm.com [127.0.0.1]) by ppma04dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 19ED1o5p028228; Thu, 14 Oct 2021 13:08:57 GMT Received: from b03cxnp07029.gho.boulder.ibm.com (b03cxnp07029.gho.boulder.ibm.com [9.17.130.16]) by ppma04dal.us.ibm.com with ESMTP id 3bkeq8fg2s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 14 Oct 2021 13:08:57 +0000 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp07029.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 19ED8tFr47579514 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 14 Oct 2021 13:08:55 GMT Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3B06778069; Thu, 14 Oct 2021 13:08:55 +0000 (GMT) Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CBAD47806B; Thu, 14 Oct 2021 13:08:53 +0000 (GMT) Received: from amdrome3.watson.ibm.com (unknown [9.2.130.16]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP; Thu, 14 Oct 2021 13:08:53 +0000 (GMT) From: Dov Murik To: linux-efi@vger.kernel.org Cc: Dov Murik , Borislav Petkov , Ashish Kalra , Brijesh Singh , Tom Lendacky , Ard Biesheuvel , James Morris , "Serge E. Hallyn" , Andi Kleen , Greg KH , Andrew Scull , Dave Hansen , "Dr. David Alan Gilbert" , James Bottomley , Tobin Feldman-Fitzthum , Jim Cadden , Daniele Buono , linux-coco@lists.linux.dev, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/3] efi/libstub: Copy confidential computing secret area Date: Thu, 14 Oct 2021 13:08:46 +0000 Message-Id: <20211014130848.592611-2-dovmurik@linux.ibm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211014130848.592611-1-dovmurik@linux.ibm.com> References: <20211014130848.592611-1-dovmurik@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: g-x72YszDybe12iWAPWaQ5xrAnD4NRCD X-Proofpoint-ORIG-GUID: NdDWlULNK4F2NzG9_WhKBCSI9NLCulsV X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-14_08,2021-10-14_02,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 spamscore=0 phishscore=0 bulkscore=0 adultscore=0 impostorscore=0 mlxscore=0 malwarescore=0 clxscore=1015 mlxlogscore=999 suspectscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2109230001 definitions=main-2110140084 Precedence: bulk List-ID: Confidential computing (coco) hardware such as AMD SEV (Secure Encrypted Virtualization) allows a guest owner to inject secrets into the VMs memory without the host/hypervisor being able to read them. Firmware support for secret injection is available in OVMF, which reserves a memory area for secret injection and includes a pointer to it the in EFI config table entry LINUX_EFI_COCO_SECRET_TABLE_GUID. However, OVMF doesn't force the guest OS to keep this memory area reserved. If EFI exposes such a table entry, efi/libstub will copy this area to a reserved memory for future use inside the kernel. A pointer to the new copy is kept in the EFI table under LINUX_EFI_COCO_SECRET_AREA_GUID. Signed-off-by: Dov Murik --- drivers/firmware/efi/libstub/Makefile | 2 +- drivers/firmware/efi/libstub/coco.c | 68 +++++++++++++++++++++++++ drivers/firmware/efi/libstub/efi-stub.c | 2 + drivers/firmware/efi/libstub/efistub.h | 2 + drivers/firmware/efi/libstub/x86-stub.c | 2 + include/linux/efi.h | 6 +++ 6 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/efi/libstub/coco.c diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index d0537573501e..d77690b7dfb9 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -55,7 +55,7 @@ KCOV_INSTRUMENT := n lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ file.o mem.o random.o randomalloc.o pci.o \ skip_spaces.o lib-cmdline.o lib-ctype.o \ - alignedmem.o relocate.o vsprintf.o + alignedmem.o relocate.o vsprintf.o coco.o # include the stub's generic dependencies from lib/ when building for ARM/arm64 efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c diff --git a/drivers/firmware/efi/libstub/coco.c b/drivers/firmware/efi/libstub/coco.c new file mode 100644 index 000000000000..bf546b6a3f72 --- /dev/null +++ b/drivers/firmware/efi/libstub/coco.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Confidential computing (coco) secret area handling + * + * Copyright (C) 2021 IBM Corporation + * Author: Dov Murik + */ + +#include +#include +#include + +#include "efistub.h" + +#define LINUX_EFI_COCO_SECRET_TABLE_GUID \ + EFI_GUID(0xadf956ad, 0xe98c, 0x484c, 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47) + +/** + * struct efi_coco_secret_table - EFI config table that points to the + * confidential computing secret area. The guid + * LINUX_EFI_COCO_SECRET_TABLE_GUID holds this table. + * @base: Physical address of the EFI secret area + * @size: Size (in bytes) of the EFI secret area + */ +struct efi_coco_secret_table { + u64 base; + u64 size; +} __attribute((packed)); + +/* + * Create a copy of EFI's confidential computing secret area (if available) so + * that the secrets are accessible in the kernel after ExitBootServices. + */ +void efi_copy_coco_secret_area(void) +{ + efi_guid_t linux_secret_area_guid = LINUX_EFI_COCO_SECRET_AREA_GUID; + efi_status_t status; + struct efi_coco_secret_table *secret_table; + struct linux_efi_coco_secret_area *secret_area; + + secret_table = get_efi_config_table(LINUX_EFI_COCO_SECRET_TABLE_GUID); + if (!secret_table) + return; + + if (secret_table->size == 0 || secret_table->size >= SZ_4G) + return; + + /* Allocate space for the secret area and copy it */ + status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, + sizeof(*secret_area) + secret_table->size, (void **)&secret_area); + + if (status != EFI_SUCCESS) { + efi_err("Unable to allocate memory for confidential computing secret area copy\n"); + return; + } + + secret_area->size = secret_table->size; + memcpy(secret_area->area, (void *)(unsigned long)secret_table->base, secret_table->size); + + status = efi_bs_call(install_configuration_table, &linux_secret_area_guid, secret_area); + if (status != EFI_SUCCESS) + goto err_free; + + return; + +err_free: + efi_bs_call(free_pool, secret_area); +} diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c index 26e69788f27a..18b3acd15c85 100644 --- a/drivers/firmware/efi/libstub/efi-stub.c +++ b/drivers/firmware/efi/libstub/efi-stub.c @@ -205,6 +205,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, efi_retrieve_tpm2_eventlog(); + efi_copy_coco_secret_area(); + /* Ask the firmware to clear memory on unclean shutdown */ efi_enable_reset_attack_mitigation(); diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index cde0a2ef507d..d604c6744cef 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -858,4 +858,6 @@ efi_enable_reset_attack_mitigation(void) { } void efi_retrieve_tpm2_eventlog(void); +void efi_copy_coco_secret_area(void); + #endif diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c index f14c4ff5839f..4ad85e1b6191 100644 --- a/drivers/firmware/efi/libstub/x86-stub.c +++ b/drivers/firmware/efi/libstub/x86-stub.c @@ -793,6 +793,8 @@ unsigned long efi_main(efi_handle_t handle, efi_retrieve_tpm2_eventlog(); + efi_copy_coco_secret_area(); + setup_graphics(boot_params); setup_efi_pci(boot_params); diff --git a/include/linux/efi.h b/include/linux/efi.h index 6b5d36babfcc..9021dd521302 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -359,6 +359,7 @@ void efi_native_runtime_setup(void); #define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2) #define LINUX_EFI_INITRD_MEDIA_GUID EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68) #define LINUX_EFI_MOK_VARIABLE_TABLE_GUID EFI_GUID(0xc451ed2b, 0x9694, 0x45d3, 0xba, 0xba, 0xed, 0x9f, 0x89, 0x88, 0xa3, 0x89) +#define LINUX_EFI_COCO_SECRET_AREA_GUID EFI_GUID(0x940ed1e9, 0xd3da, 0x408b, 0xb3, 0x07, 0xe3, 0x2d, 0x25, 0x4a, 0x65, 0x16) /* OEM GUIDs */ #define DELLEMC_EFI_RCI2_TABLE_GUID EFI_GUID(0x2d9f28a2, 0xa886, 0x456a, 0x97, 0xa8, 0xf1, 0x1e, 0xf2, 0x4f, 0xf4, 0x55) @@ -1282,4 +1283,9 @@ static inline struct efi_mokvar_table_entry *efi_mokvar_entry_find( } #endif +struct linux_efi_coco_secret_area { + u32 size; + u8 area[]; +}; + #endif /* _LINUX_EFI_H */ From patchwork Thu Oct 14 13:08:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dov Murik X-Patchwork-Id: 12558447 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8D019C433F5 for ; Thu, 14 Oct 2021 13:09:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7692F61167 for ; Thu, 14 Oct 2021 13:09:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231676AbhJNNLk (ORCPT ); Thu, 14 Oct 2021 09:11:40 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:46365 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231607AbhJNNLe (ORCPT ); Thu, 14 Oct 2021 09:11:34 -0400 Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19EBC5dL017855; Thu, 14 Oct 2021 09:09:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=Iqjb/HuqAPee0d/niWc0Tugcm0RWM3NiSGvG5Q1ad6Y=; b=CpHSJbNrUb5GwmVgmQnynlrsFMsaptnNXelWobM1TYi/LfOgjz1Uyrdn0r4qou5XZEVf B84IYhrqMqrArmwbPomJTkhz6OAd8l0Mmczvi8RQ6CYjRiybKtNvvjy2dxrUVwVAydGD RYpRucA80PFVMkLRJ8CJ0kscCN0ryFAbRgIEt7GPlKtRSLVE7Bo3Sp7v+RCvVMfTehkG cvvkncBj4E7Zt4GD2vymZdYAVwAfF4VMH/fVCqkAkmhTG/HTCPqreBnIrNODOi5bNS4J R/QNQjcH4a5/uqJSQ0Ver7StvxDVcOyVB7LTW4gv1P2GsY1Mx/E2sgVTAr15pW5UnW+i IQ== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3bnrndq6b9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 14 Oct 2021 09:09:01 -0400 Received: from m0098409.ppops.net (m0098409.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 19ECnkva023854; Thu, 14 Oct 2021 09:09:00 -0400 Received: from ppma04dal.us.ibm.com (7a.29.35a9.ip4.static.sl-reverse.com [169.53.41.122]) by mx0a-001b2d01.pphosted.com with ESMTP id 3bnrndq6a1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 14 Oct 2021 09:09:00 -0400 Received: from pps.filterd (ppma04dal.us.ibm.com [127.0.0.1]) by ppma04dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 19ED1oP7028226; Thu, 14 Oct 2021 13:08:59 GMT Received: from b03cxnp08025.gho.boulder.ibm.com (b03cxnp08025.gho.boulder.ibm.com [9.17.130.17]) by ppma04dal.us.ibm.com with ESMTP id 3bkeq8fg3h-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 14 Oct 2021 13:08:59 +0000 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp08025.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 19ED8uwq48628170 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 14 Oct 2021 13:08:56 GMT Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B3D4D7805C; Thu, 14 Oct 2021 13:08:56 +0000 (GMT) Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5CC4878069; Thu, 14 Oct 2021 13:08:55 +0000 (GMT) Received: from amdrome3.watson.ibm.com (unknown [9.2.130.16]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP; Thu, 14 Oct 2021 13:08:55 +0000 (GMT) From: Dov Murik To: linux-efi@vger.kernel.org Cc: Dov Murik , Borislav Petkov , Ashish Kalra , Brijesh Singh , Tom Lendacky , Ard Biesheuvel , James Morris , "Serge E. Hallyn" , Andi Kleen , Greg KH , Andrew Scull , Dave Hansen , "Dr. David Alan Gilbert" , James Bottomley , Tobin Feldman-Fitzthum , Jim Cadden , Daniele Buono , linux-coco@lists.linux.dev, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/3] efi: Reserve confidential computing secret area Date: Thu, 14 Oct 2021 13:08:47 +0000 Message-Id: <20211014130848.592611-3-dovmurik@linux.ibm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211014130848.592611-1-dovmurik@linux.ibm.com> References: <20211014130848.592611-1-dovmurik@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: yx5Gfz-6P4vTRy7Djs4iVYRWiOKwytTX X-Proofpoint-ORIG-GUID: 6HXCS_vLp3UT_1unKxewKjspuKTe6XGc X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-14_07,2021-10-14_02,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 mlxlogscore=999 adultscore=0 spamscore=0 lowpriorityscore=0 bulkscore=0 mlxscore=0 suspectscore=0 phishscore=0 impostorscore=0 clxscore=1015 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2109230001 definitions=main-2110140084 Precedence: bulk List-ID: When efi-stub copies an EFI-provided confidential computing (coco) secret area, reserve that memory block for future use within the kernel. Signed-off-by: Dov Murik --- arch/x86/platform/efi/efi.c | 1 + drivers/firmware/efi/Makefile | 2 +- drivers/firmware/efi/coco.c | 41 +++++++++++++++++++++++++++++++++++ drivers/firmware/efi/efi.c | 4 ++++ include/linux/efi.h | 3 +++ 5 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/efi/coco.c diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 147c30a81f15..35e082e5f603 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -93,6 +93,7 @@ static const unsigned long * const efi_tables[] = { #ifdef CONFIG_LOAD_UEFI_KEYS &efi.mokvar_table, #endif + &efi.coco_secret, }; u64 efi_setup; /* efi setup_data physical address */ diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index c02ff25dd477..bfd35294703e 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -12,7 +12,7 @@ KASAN_SANITIZE_runtime-wrappers.o := n obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o tpm.o -obj-$(CONFIG_EFI) += memmap.o +obj-$(CONFIG_EFI) += memmap.o coco.o ifneq ($(CONFIG_EFI_CAPSULE_LOADER),) obj-$(CONFIG_EFI) += capsule.o endif diff --git a/drivers/firmware/efi/coco.c b/drivers/firmware/efi/coco.c new file mode 100644 index 000000000000..42f477d6188c --- /dev/null +++ b/drivers/firmware/efi/coco.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Confidential computing (coco) secret area handling + * + * Copyright (C) 2021 IBM Corporation + * Author: Dov Murik + */ + +#define pr_fmt(fmt) "efi: " fmt + +#include +#include +#include +#include + +/* + * Reserve the confidential computing secret area memory + */ +int __init efi_coco_secret_area_reserve(void) +{ + struct linux_efi_coco_secret_area *secret_area; + unsigned long secret_area_size; + + if (efi.coco_secret == EFI_INVALID_TABLE_ADDR) + return 0; + + secret_area = early_memremap(efi.coco_secret, sizeof(*secret_area)); + if (!secret_area) { + pr_err("Failed to map confidential computing secret area\n"); + efi.coco_secret = EFI_INVALID_TABLE_ADDR; + return -ENOMEM; + } + + secret_area_size = sizeof(*secret_area) + secret_area->size; + memblock_reserve(efi.coco_secret, secret_area_size); + + pr_info("Reserved memory of EFI-provided confidential computing secret area"); + + early_memunmap(secret_area, sizeof(*secret_area)); + return 0; +} diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 847f33ffc4ae..4c1ab98cf693 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -46,6 +46,7 @@ struct efi __read_mostly efi = { #ifdef CONFIG_LOAD_UEFI_KEYS .mokvar_table = EFI_INVALID_TABLE_ADDR, #endif + .coco_secret = EFI_INVALID_TABLE_ADDR, }; EXPORT_SYMBOL(efi); @@ -526,6 +527,7 @@ static const efi_config_table_type_t common_tables[] __initconst = { #ifdef CONFIG_LOAD_UEFI_KEYS {LINUX_EFI_MOK_VARIABLE_TABLE_GUID, &efi.mokvar_table, "MOKvar" }, #endif + {LINUX_EFI_COCO_SECRET_AREA_GUID, &efi.coco_secret, "CocoSecret" }, {}, }; @@ -613,6 +615,8 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables, efi_tpm_eventlog_init(); + efi_coco_secret_area_reserve(); + if (mem_reserve != EFI_INVALID_TABLE_ADDR) { unsigned long prsv = mem_reserve; diff --git a/include/linux/efi.h b/include/linux/efi.h index 9021dd521302..e86600af5dfd 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -550,6 +550,7 @@ extern struct efi { unsigned long tpm_log; /* TPM2 Event Log table */ unsigned long tpm_final_log; /* TPM2 Final Events Log table */ unsigned long mokvar_table; /* MOK variable config table */ + unsigned long coco_secret; /* Confidential computing secret table */ efi_get_time_t *get_time; efi_set_time_t *set_time; @@ -1189,6 +1190,8 @@ extern int efi_tpm_final_log_size; extern unsigned long rci2_table_phys; +extern int efi_coco_secret_area_reserve(void); + /* * efi_runtime_service() function identifiers. * "NONE" is used by efi_recover_from_page_fault() to check if the page From patchwork Thu Oct 14 13:08:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dov Murik X-Patchwork-Id: 12558445 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4DCB1C433EF for ; Thu, 14 Oct 2021 13:09:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 30B1A610CC for ; Thu, 14 Oct 2021 13:09:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231598AbhJNNLe (ORCPT ); Thu, 14 Oct 2021 09:11:34 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:31013 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230321AbhJNNLb (ORCPT ); Thu, 14 Oct 2021 09:11:31 -0400 Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19ECPTdF020960; Thu, 14 Oct 2021 09:09:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=xrdg3IbiDOZ5RzqwSqJ+xjgW5NIh7Qtwmcz4vXlTXxI=; b=ZDFxvLUHdFPZvU5BgdHXrPT/Ks5BPv5po6SUQFCU0dIy+/oZ0DNKLvkZ8xa1fPh65cYS V8jn8l8RqNuqLJPuHB4eICbET2WgKSSBx42zgApcon3C52TIZ05t8Qkb+Rm3ncrSdh13 52uO4zgs4dAAHPKiq4OB2tHCIQ/lV6xdfarJrju5RqPKxL3Qhr567Tk2Mk9MGEJ7PrHA MNh1KsH8aG6wzSTpNbWxsSD4QqXkcKT3xi4SYclfAkXM1Rj5KZTsLfkxljw4T6ev+wDC AFWK1PmMB6cpC3oB7n4PpUDUYlM3hqtv2fYHevJO0VzMUPt7ALOpX1qNcfhkQMRUraAV 9Q== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3bntpxw1wx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 14 Oct 2021 09:09:03 -0400 Received: from m0098410.ppops.net (m0098410.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 19ECb8nQ032463; Thu, 14 Oct 2021 09:09:02 -0400 Received: from ppma05wdc.us.ibm.com (1b.90.2fa9.ip4.static.sl-reverse.com [169.47.144.27]) by mx0a-001b2d01.pphosted.com with ESMTP id 3bntpxw1vu-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 14 Oct 2021 09:09:02 -0400 Received: from pps.filterd (ppma05wdc.us.ibm.com [127.0.0.1]) by ppma05wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 19ED1nul012254; Thu, 14 Oct 2021 13:09:00 GMT Received: from b03cxnp08027.gho.boulder.ibm.com (b03cxnp08027.gho.boulder.ibm.com [9.17.130.19]) by ppma05wdc.us.ibm.com with ESMTP id 3bk2qcffvr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 14 Oct 2021 13:09:00 +0000 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp08027.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 19ED8wg617826112 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 14 Oct 2021 13:08:58 GMT Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5979D78069; Thu, 14 Oct 2021 13:08:58 +0000 (GMT) Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id DECF17805C; Thu, 14 Oct 2021 13:08:56 +0000 (GMT) Received: from amdrome3.watson.ibm.com (unknown [9.2.130.16]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP; Thu, 14 Oct 2021 13:08:56 +0000 (GMT) From: Dov Murik To: linux-efi@vger.kernel.org Cc: Dov Murik , Borislav Petkov , Ashish Kalra , Brijesh Singh , Tom Lendacky , Ard Biesheuvel , James Morris , "Serge E. Hallyn" , Andi Kleen , Greg KH , Andrew Scull , Dave Hansen , "Dr. David Alan Gilbert" , James Bottomley , Tobin Feldman-Fitzthum , Jim Cadden , Daniele Buono , linux-coco@lists.linux.dev, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 3/3] virt: Add efi_secret module to expose confidential computing secrets Date: Thu, 14 Oct 2021 13:08:48 +0000 Message-Id: <20211014130848.592611-4-dovmurik@linux.ibm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211014130848.592611-1-dovmurik@linux.ibm.com> References: <20211014130848.592611-1-dovmurik@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: PBDey6nnu-atkvWkooSsSmsFoVWaMQ7D X-Proofpoint-ORIG-GUID: X_XyNcXSeBKA53wjYkJqBGdyGUWzjZVf X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-14_08,2021-10-14_02,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 malwarescore=0 bulkscore=0 mlxlogscore=999 clxscore=1015 phishscore=0 spamscore=0 mlxscore=0 priorityscore=1501 suspectscore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2109230001 definitions=main-2110140084 Precedence: bulk List-ID: The new efi_secret module exposes the confidential computing (coco) EFI secret area via securityfs interface. When the module is loaded (and securityfs is mounted, typically under /sys/kernel/security), a "coco/efi_secret" directory is created in securityfs. In it, a file is created for each secret entry. The name of each such file is the GUID of the secret entry, and its content is the secret data. This allows applications running in a confidential computing setting to read secrets provided by the guest owner via a secure secret injection mechanism (such as AMD SEV's LAUNCH_SECRET command). Removing (unlinking) files in the "coco/efi_secret" directory will zero out the secret in memory, and remove the filesystem entry. If the module is removed and loaded again, that secret will not appear in the filesystem. Signed-off-by: Dov Murik --- .../ABI/testing/securityfs-coco-efi_secret | 50 +++ drivers/virt/Kconfig | 3 + drivers/virt/Makefile | 1 + drivers/virt/coco/efi_secret/Kconfig | 10 + drivers/virt/coco/efi_secret/Makefile | 2 + drivers/virt/coco/efi_secret/efi_secret.c | 324 ++++++++++++++++++ 6 files changed, 390 insertions(+) create mode 100644 Documentation/ABI/testing/securityfs-coco-efi_secret create mode 100644 drivers/virt/coco/efi_secret/Kconfig create mode 100644 drivers/virt/coco/efi_secret/Makefile create mode 100644 drivers/virt/coco/efi_secret/efi_secret.c diff --git a/Documentation/ABI/testing/securityfs-coco-efi_secret b/Documentation/ABI/testing/securityfs-coco-efi_secret new file mode 100644 index 000000000000..ae56976db1bc --- /dev/null +++ b/Documentation/ABI/testing/securityfs-coco-efi_secret @@ -0,0 +1,50 @@ +What: security/coco/efi_secret +Date: October 2021 +Contact: Dov Murik +Description: + Exposes confidential computing (coco) EFI secrets to + userspace via securityfs. + + EFI can declare memory area used by confidential computing + platforms (such as AMD SEV and SEV-ES) for secret injection by + the Guest Owner during VM's launch. The secrets are encrypted + by the Guest Owner and decrypted inside the trusted enclave, + and therefore are not readable by the untrusted host. + + The efi_secret module exposes the secrets to userspace. Each + secret appears as a file under /coco/efi_secret, + where the filename is the GUID of the entry in the secrets + table. + + Two operations are supported for the files: read and unlink. + Reading the file returns the content of secret entry. + Unlinking the file overwrites the secret data with zeroes and + removes the entry from the filesystem. A secret cannot be read + after it has been unlinked. + + For example, listing the available secrets:: + + # modprobe efi_secret + # ls -l /sys/kernel/security/coco/efi_secret + -r--r----- 1 root root 0 Jun 28 11:54 736870e5-84f0-4973-92ec-06879ce3da0b + -r--r----- 1 root root 0 Jun 28 11:54 83c83f7f-1356-4975-8b7e-d3a0b54312c6 + -r--r----- 1 root root 0 Jun 28 11:54 9553f55d-3da2-43ee-ab5d-ff17f78864d2 + -r--r----- 1 root root 0 Jun 28 11:54 e6f5a162-d67f-4750-a67c-5d065f2a9910 + + Reading the secret data by reading a file:: + + # cat /sys/kernel/security/coco/efi_secret/e6f5a162-d67f-4750-a67c-5d065f2a9910 + the-content-of-the-secret-data + + Wiping a secret by unlinking a file:: + + # rm /sys/kernel/security/coco/efi_secret/e6f5a162-d67f-4750-a67c-5d065f2a9910 + # ls -l /sys/kernel/security/coco/efi_secret + -r--r----- 1 root root 0 Jun 28 11:54 736870e5-84f0-4973-92ec-06879ce3da0b + -r--r----- 1 root root 0 Jun 28 11:54 83c83f7f-1356-4975-8b7e-d3a0b54312c6 + -r--r----- 1 root root 0 Jun 28 11:54 9553f55d-3da2-43ee-ab5d-ff17f78864d2 + + Note: The binary format of the secrets table injected by the + Guest Owner is described in + drivers/virt/coco/efi_secret/efi_secret.c under "Structure of + the EFI secret area". diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig index 8061e8ef449f..fe7a6579b974 100644 --- a/drivers/virt/Kconfig +++ b/drivers/virt/Kconfig @@ -36,4 +36,7 @@ source "drivers/virt/vboxguest/Kconfig" source "drivers/virt/nitro_enclaves/Kconfig" source "drivers/virt/acrn/Kconfig" + +source "drivers/virt/coco/efi_secret/Kconfig" + endif diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile index 3e272ea60cd9..efdb015783f9 100644 --- a/drivers/virt/Makefile +++ b/drivers/virt/Makefile @@ -8,3 +8,4 @@ obj-y += vboxguest/ obj-$(CONFIG_NITRO_ENCLAVES) += nitro_enclaves/ obj-$(CONFIG_ACRN_HSM) += acrn/ +obj-$(CONFIG_EFI_SECRET) += coco/efi_secret/ diff --git a/drivers/virt/coco/efi_secret/Kconfig b/drivers/virt/coco/efi_secret/Kconfig new file mode 100644 index 000000000000..91d07366e8b0 --- /dev/null +++ b/drivers/virt/coco/efi_secret/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only +config EFI_SECRET + tristate "EFI secret area securityfs support" + depends on EFI + select SECURITYFS + help + This is a driver for accessing the EFI secret area via securityfs. + + To compile this driver as a module, choose M here. + The module will be called efi_secret. diff --git a/drivers/virt/coco/efi_secret/Makefile b/drivers/virt/coco/efi_secret/Makefile new file mode 100644 index 000000000000..c7047ce804f7 --- /dev/null +++ b/drivers/virt/coco/efi_secret/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_EFI_SECRET) += efi_secret.o diff --git a/drivers/virt/coco/efi_secret/efi_secret.c b/drivers/virt/coco/efi_secret/efi_secret.c new file mode 100644 index 000000000000..c8b1eaba75fb --- /dev/null +++ b/drivers/virt/coco/efi_secret/efi_secret.c @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * efi_secret module + * + * Copyright (C) 2021 IBM Corporation + * Author: Dov Murik + */ + +/** + * DOC: efi_secret: Allow reading EFI confidential computing (coco) secret area + * via securityfs interface. + * + * When the module is loaded (and securityfs is mounted, typically under + * /sys/kernel/security), a "coco/efi_secret" directory is created in + * securityfs. In it, a file is created for each secret entry. The name of + * each such file is the GUID of the secret entry, and its content is the + * secret data. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EFI_SECRET_NUM_FILES 64 + +#define EFI_SECRET_TABLE_HEADER_GUID \ + EFI_GUID(0x1e74f542, 0x71dd, 0x4d66, 0x96, 0x3e, 0xef, 0x42, 0x87, 0xff, 0x17, 0x3b) + +struct efi_secret { + struct dentry *coco_dir; + struct dentry *fs_dir; + struct dentry *fs_files[EFI_SECRET_NUM_FILES]; + struct linux_efi_coco_secret_area *secret_area; +}; + +/* + * Structure of the EFI secret area + * + * Offset Length + * (bytes) (bytes) Usage + * ------- ------- ----- + * 0 16 Secret table header GUID (must be 1e74f542-71dd-4d66-963e-ef4287ff173b) + * 16 4 Length of bytes of the entire secret area + * + * 20 16 First secret entry's GUID + * 36 4 First secret entry's length in bytes (= 16 + 4 + x) + * 40 x First secret entry's data + * + * 40+x 16 Second secret entry's GUID + * 56+x 4 Second secret entry's length in bytes (= 16 + 4 + y) + * 60+x y Second secret entry's data + * + * (... and so on for additional entries) + * + * The GUID of each secret entry designates the usage of the secret data. + */ + +/** + * struct secret_header - Header of entire secret area; this should be followed + * by instances of struct secret_entry. + * @guid: Must be EFI_SECRET_TABLE_HEADER_GUID + * @len: Length in bytes of entire secret area, including header + */ +struct secret_header { + efi_guid_t guid; + u32 len; +} __attribute((packed)); + +/** + * struct secret_entry - Holds one secret entry + * @guid: Secret-specific GUID (or NULL_GUID if this secret entry was deleted) + * @len: Length of secret entry, including its guid and len fields + * @data: The secret data (full of zeros if this secret entry was deleted) + */ +struct secret_entry { + efi_guid_t guid; + u32 len; + u8 data[]; +} __attribute((packed)); + +static size_t secret_entry_data_len(struct secret_entry *e) +{ + return e->len - sizeof(*e); +} + +static struct efi_secret the_efi_secret; + +static inline struct efi_secret *efi_secret_get(void) +{ + return &the_efi_secret; +} + +static int efi_secret_bin_file_show(struct seq_file *file, void *data) +{ + struct secret_entry *e = file->private; + + if (e) + seq_write(file, e->data, secret_entry_data_len(e)); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(efi_secret_bin_file); + +/* + * Overwrite memory content with zeroes, and ensure that dirty cache lines are + * actually written back to memory, to clear out the secret. + */ +static void wipe_memory(void *addr, size_t size) +{ + memzero_explicit(addr, size); + clflush_cache_range(addr, size); +} + +static int efi_secret_unlink(struct inode *dir, struct dentry *dentry) +{ + struct efi_secret *s = efi_secret_get(); + struct inode *inode = d_inode(dentry); + struct secret_entry *e = (struct secret_entry *)inode->i_private; + int i; + + if (e) { + /* Zero out the secret data */ + wipe_memory(e->data, secret_entry_data_len(e)); + e->guid = NULL_GUID; + } + + inode->i_private = NULL; + + for (i = 0; i < EFI_SECRET_NUM_FILES; i++) + if (s->fs_files[i] == dentry) + s->fs_files[i] = NULL; + + /* + * securityfs_remove tries to lock the directory's inode, but we reach + * the unlink callback when it's already locked + */ + inode_unlock(dir); + securityfs_remove(dentry); + inode_lock(dir); + + return 0; +} + +static const struct inode_operations efi_secret_dir_inode_operations = { + .lookup = simple_lookup, + .unlink = efi_secret_unlink, +}; + +static int efi_secret_map_area(void) +{ + struct efi_secret *s = efi_secret_get(); + struct linux_efi_coco_secret_area *secret_area; + u32 secret_area_size; + + if (efi.coco_secret == EFI_INVALID_TABLE_ADDR) { + pr_err("Secret area address is not available\n"); + return -EINVAL; + } + + secret_area = memremap(efi.coco_secret, sizeof(*secret_area), MEMREMAP_WB); + if (secret_area == NULL) { + pr_err("Could not map secret area header\n"); + return -ENOMEM; + } + + secret_area_size = sizeof(*secret_area) + secret_area->size; + memunmap(secret_area); + + secret_area = memremap(efi.coco_secret, secret_area_size, MEMREMAP_WB); + if (secret_area == NULL) { + pr_err("Could not map secret area\n"); + return -ENOMEM; + } + + s->secret_area = secret_area; + return 0; +} + +static void efi_secret_securityfs_teardown(void) +{ + struct efi_secret *s = efi_secret_get(); + int i; + + for (i = (EFI_SECRET_NUM_FILES - 1); i >= 0; i--) { + securityfs_remove(s->fs_files[i]); + s->fs_files[i] = NULL; + } + + securityfs_remove(s->fs_dir); + s->fs_dir = NULL; + + securityfs_remove(s->coco_dir); + s->coco_dir = NULL; + + pr_debug("Removed efi_secret securityfs entries\n"); +} + +static int efi_secret_securityfs_setup(void) +{ + efi_guid_t tableheader_guid = EFI_SECRET_TABLE_HEADER_GUID; + struct efi_secret *s = efi_secret_get(); + int ret = 0, i = 0, bytes_left; + unsigned char *ptr; + struct secret_header *h; + struct secret_entry *e; + struct dentry *dent; + char guid_str[EFI_VARIABLE_GUID_LEN + 1]; + + s->coco_dir = NULL; + s->fs_dir = NULL; + memset(s->fs_files, 0, sizeof(s->fs_files)); + + dent = securityfs_create_dir("coco", NULL); + if (IS_ERR(dent)) { + pr_err("Error creating coco securityfs directory entry err=%ld\n", PTR_ERR(dent)); + return PTR_ERR(dent); + } + s->coco_dir = dent; + + dent = securityfs_create_dir("efi_secret", s->coco_dir); + if (IS_ERR(dent)) { + pr_err("Error creating efi_secret securityfs directory entry err=%ld\n", + PTR_ERR(dent)); + return PTR_ERR(dent); + } + d_inode(dent)->i_op = &efi_secret_dir_inode_operations; + s->fs_dir = dent; + + ptr = s->secret_area->area; + h = (struct secret_header *)ptr; + if (memcmp(&h->guid, &tableheader_guid, sizeof(h->guid))) { + pr_err("EFI secret area does not start with correct GUID\n"); + ret = -EINVAL; + goto err_cleanup; + } + if (h->len < sizeof(*h)) { + pr_err("EFI secret area reported length is too small\n"); + ret = -EINVAL; + goto err_cleanup; + } + + bytes_left = h->len - sizeof(*h); + ptr += sizeof(*h); + while (bytes_left >= (int)sizeof(*e) && i < EFI_SECRET_NUM_FILES) { + e = (struct secret_entry *)ptr; + if (e->len < sizeof(*e) || e->len > (unsigned int)bytes_left) { + pr_err("EFI secret area is corrupted\n"); + ret = -EINVAL; + goto err_cleanup; + } + + /* Skip deleted entries (which will have NULL_GUID) */ + if (efi_guidcmp(e->guid, NULL_GUID)) { + efi_guid_to_str(&e->guid, guid_str); + + dent = securityfs_create_file(guid_str, 0440, s->fs_dir, (void *)e, + &efi_secret_bin_file_fops); + if (IS_ERR(dent)) { + pr_err("Error creating efi_secret securityfs entry\n"); + ret = PTR_ERR(dent); + goto err_cleanup; + } + + s->fs_files[i++] = dent; + } + ptr += e->len; + bytes_left -= e->len; + } + + pr_debug("Created %d entries in efi_secret securityfs\n", i); + return 0; + +err_cleanup: + efi_secret_securityfs_teardown(); + return ret; +} + +static void efi_secret_unmap_area(void) +{ + struct efi_secret *s = efi_secret_get(); + + if (s->secret_area) { + memunmap(s->secret_area); + s->secret_area = NULL; + } +} + +static int __init efi_secret_init(void) +{ + int ret; + + ret = efi_secret_map_area(); + if (ret) + return ret; + + ret = efi_secret_securityfs_setup(); + if (ret) + goto err_unmap; + + return ret; + +err_unmap: + efi_secret_unmap_area(); + return ret; +} + +static void __exit efi_secret_exit(void) +{ + efi_secret_securityfs_teardown(); + efi_secret_unmap_area(); +} + +module_init(efi_secret_init); +module_exit(efi_secret_exit); + +MODULE_DESCRIPTION("Confidential computing EFI secret area access"); +MODULE_AUTHOR("IBM"); +MODULE_LICENSE("GPL");