From patchwork Tue Sep 26 04:17:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 144914 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:cae8:0:b0:403:3b70:6f57 with SMTP id r8csp1961907vqu; Tue, 26 Sep 2023 07:33:19 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFV7haVy8ig1vuSe7mIsXWnj/YUVnUITiPCzrrmuVF+EV3s07eZyZvteleA+CyNF9kRbjjE X-Received: by 2002:a17:902:e847:b0:1b6:bced:1dc2 with SMTP id t7-20020a170902e84700b001b6bced1dc2mr9791185plg.0.1695738799306; Tue, 26 Sep 2023 07:33:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695738799; cv=none; d=google.com; s=arc-20160816; b=S/PJVZRBAuKPtMh1LoE8f7Trm/Bq8xTXsQbfIFiHgzayeEYbnKTKd57hJkhiqWp8SN /pUNt/9t93in2V4fr+yhI6gyN3JjpCUSgltWoaZnsJUbsv9En9RiX5+uGCdKrbEFDKPi k7WjlJ7tVxtGsUgeYX8BFSIiixIbs7tPrTf53oZnfvF9ANruJmw8MbtR1NM+iAoMvps5 MOMxM6eHCXte28JEDld5wRh9e7yz40UujXaD2ClTCBDFIV/SxFpcysxN91XdPWuPcjDN xoL2C9Ep0Pe2H/aj2jTmkXWD0BBcLs/U77qWZYXhNtI9qZI40tb92MOgUxAN8i237vtz +Vpg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject:dkim-signature; bh=oA378HnFzyBGQ29r0bkQfzX1PmH1nxYOUiPv9CihgNE=; fh=1P1ByqBgV8dzCo6/pmhB8AtIvEGF4n5ubggLpPr81U4=; b=FLmriImsVmDg6qVlHpxCTavvRVBvzRO42HpmazIKa3rSGue3cV5LWpn9tbrzRDVK/8 ByFb5UC2HzEboJIjua5aMPFuFsreijJAUy4kGLOLoaA7RF+LSB1/WLdMB4W6m60kM2gl EDO4iwnRDm3NJ+o+BExQR/UmzWA3TjONkaaOu8FVBXui2UxnUJtOPxY/o5oAnex7Qhtj hLVSP6FQRT4ASvs5s0U1FuRWUQjyd5Z6ngFLxGpN6JDwZJF49P0X85JuqfXM/7WymZ6Y a+xKAZquSIw5UdxeBgjwAwLVuBjLEkrMptoVHO0B2g1YTJDGwjYWsw/8TOhSZIFMpmnD eaUQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=XwY6W78S; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from lipwig.vger.email (lipwig.vger.email. [23.128.96.33]) by mx.google.com with ESMTPS id n14-20020a170903110e00b001bbcb3d9265si13373704plh.68.2023.09.26.07.33.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Sep 2023 07:33:19 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) client-ip=23.128.96.33; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=XwY6W78S; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by lipwig.vger.email (Postfix) with ESMTP id 01C358063011; Mon, 25 Sep 2023 21:18:05 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at lipwig.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233201AbjIZERT (ORCPT + 27 others); Tue, 26 Sep 2023 00:17:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39970 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229472AbjIZERS (ORCPT ); Tue, 26 Sep 2023 00:17:18 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D6C05BF for ; Mon, 25 Sep 2023 21:17:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695701831; x=1727237831; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=b7vp5OcVBoNhgN64VhsxskMsEKIzR4SqcCbOS2xbSV8=; b=XwY6W78SJ/KIXmy2wY2I6K8uumqVsu9GFo+epbHRNLz80UIYzqBWEIWD 6RvvrhTEjkE2r86IglipAkqEe3HJj6SLJS/iSdkWEtj3mBRRyk4MwhTlQ qg9m4taKBFAY9TIhubUtLJxgoXLMWwpxYb5jLc6UK7yGUTeiz9SEqkn6T qEMOnUHcdW/nlWfrsEqQxL+Akvst6ldaOHs+9xE6XRmzszs9DZPEXEzIY JGrZsCXaR4IVJ6Iv5bYxSArt9ThQaRln8l2xUcrHH4J6IC5wv5+cVQiyU yRCKQA7x59T3IST5umeCUoj2JDgQyOkEJGoLhuICQRE7TN/9b6ywsxbtG A==; X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="412395794" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="412395794" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="814314514" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="814314514" Received: from fvivekku-mobl.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.251.18.72]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:04 -0700 Subject: [PATCH v4 1/6] virt: coco: Add a coco/Makefile and coco/Kconfig From: Dan Williams To: linux-coco@lists.linux.dev Cc: Kuppuswamy Sathyanarayanan , peterz@infradead.org, linux-kernel@vger.kernel.org, x86@kernel.org, dave.hansen@linux.intel.com Date: Mon, 25 Sep 2023 21:17:03 -0700 Message-ID: <169570182376.596431.13665321099443794459.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> References: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lipwig.vger.email 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 (lipwig.vger.email [0.0.0.0]); Mon, 25 Sep 2023 21:18:05 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778111007297525262 X-GMAIL-MSGID: 1778111007297525262 In preparation for adding another coco build target, relieve drivers/virt/Makefile of the responsibility to track new compilation unit additions to drivers/virt/coco/, and do the same for drivers/virt/Kconfig. Reviewed-by: Kuppuswamy Sathyanarayanan Signed-off-by: Dan Williams --- drivers/virt/Kconfig | 6 +----- drivers/virt/Makefile | 4 +--- drivers/virt/coco/Kconfig | 9 +++++++++ drivers/virt/coco/Makefile | 7 +++++++ 4 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 drivers/virt/coco/Kconfig create mode 100644 drivers/virt/coco/Makefile diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig index f79ab13a5c28..40129b6f0eca 100644 --- a/drivers/virt/Kconfig +++ b/drivers/virt/Kconfig @@ -48,10 +48,6 @@ source "drivers/virt/nitro_enclaves/Kconfig" source "drivers/virt/acrn/Kconfig" -source "drivers/virt/coco/efi_secret/Kconfig" - -source "drivers/virt/coco/sev-guest/Kconfig" - -source "drivers/virt/coco/tdx-guest/Kconfig" +source "drivers/virt/coco/Kconfig" endif diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile index e9aa6fc96fab..f29901bd7820 100644 --- a/drivers/virt/Makefile +++ b/drivers/virt/Makefile @@ -9,6 +9,4 @@ obj-y += vboxguest/ obj-$(CONFIG_NITRO_ENCLAVES) += nitro_enclaves/ obj-$(CONFIG_ACRN_HSM) += acrn/ -obj-$(CONFIG_EFI_SECRET) += coco/efi_secret/ -obj-$(CONFIG_SEV_GUEST) += coco/sev-guest/ -obj-$(CONFIG_INTEL_TDX_GUEST) += coco/tdx-guest/ +obj-y += coco/ diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig new file mode 100644 index 000000000000..fc5c64f04c4a --- /dev/null +++ b/drivers/virt/coco/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Confidential computing related collateral +# +source "drivers/virt/coco/efi_secret/Kconfig" + +source "drivers/virt/coco/sev-guest/Kconfig" + +source "drivers/virt/coco/tdx-guest/Kconfig" diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile new file mode 100644 index 000000000000..55302ef719ad --- /dev/null +++ b/drivers/virt/coco/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Confidential computing related collateral +# +obj-$(CONFIG_EFI_SECRET) += efi_secret/ +obj-$(CONFIG_SEV_GUEST) += sev-guest/ +obj-$(CONFIG_INTEL_TDX_GUEST) += tdx-guest/ From patchwork Tue Sep 26 04:17:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 144754 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:cae8:0:b0:403:3b70:6f57 with SMTP id r8csp1729543vqu; Tue, 26 Sep 2023 00:19:52 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFaTmSMTMSEv522fL0dxE/CIUluPzYUTykDaSEfkxs/zqz8Vt4OaFDx5F1ZdqvTuJ72i/Fd X-Received: by 2002:aa7:88cb:0:b0:68a:5395:7aa5 with SMTP id k11-20020aa788cb000000b0068a53957aa5mr10855601pff.17.1695712791675; Tue, 26 Sep 2023 00:19:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695712791; cv=none; d=google.com; s=arc-20160816; b=ws9DyvP3paXLWsIeHbCg934n+K4qaaNmnPxQDjdeaNIm/RF9VUWZtrsNxjWjJc3YKB 7by2CBBdOUm5sGaTlad5o3S9NWlwXQoXbmPG3XdZ1u2FMei8UUigbncmkkCw/O8TVvXN EtOg9ngeszvyvK40lmwdAn8L1LBIuYXF7tGrr/5Xf8mRtcctbYvhE1MUCK7KbCIhW4G3 aq5q90fcu5Xgs97IuGIfFtJqQ8Jds0/V4hweCWYHaenVJwFLIckoGYzR/GoDEuTFXd1o Wlt3CyuimVWc4jI56DArXqH4sMcYOVg5anWjv9pCuwcJHx5bT84zZnQhTFgSu/V73oBx vUdw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject:dkim-signature; bh=wyaXpc7OK1OxLE3CApLpqFqvG9721Aii2M9RcOn9rvI=; fh=IlwrjYqzonJnGzb5Wg8IPf6IE2h6C0xec7Q/7plDEg8=; b=ve7vHsAevUsK9aU5vf+SMDoe7ech8a4GeYcAIDl0pnR3Sx3OOu9fjRgJZepGM3xlZD jyTQPcw4zFKVTPuaT5SgJAQme7pPS/4radMwzn20pD/OZKHvvaf9qMhLmkAz8b0vfWwT yK4wYB1ADamMfOtuYJKxSlXX5NvJEFEFZsG4CtnEJEqoHp9ZSaWbSZkGvpTGTWbVHlJs hng0LoU5uuRap2kG8t962sAAxUWBtrwebKcOuxQ5y3Zm16BcKg0CgeZkKerUTZHuX3tn 8lV5F4R3rGVviMnqLBzktbGbUDjOZvZ2lctRv2yx1tRgQHq+6piMkKz/Bg1vc45hZNsy yoCg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b="j/2N/ack"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.32 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from agentk.vger.email (agentk.vger.email. [23.128.96.32]) by mx.google.com with ESMTPS id g20-20020a056a001a1400b0068fcf6fe22esi12285672pfv.306.2023.09.26.00.19.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Sep 2023 00:19:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.32 as permitted sender) client-ip=23.128.96.32; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b="j/2N/ack"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.32 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by agentk.vger.email (Postfix) with ESMTP id 91AC0801D80B; Mon, 25 Sep 2023 21:17:39 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at agentk.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233583AbjIZERZ (ORCPT + 27 others); Tue, 26 Sep 2023 00:17:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36026 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229472AbjIZERW (ORCPT ); Tue, 26 Sep 2023 00:17:22 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7A3BEC for ; Mon, 25 Sep 2023 21:17:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695701832; x=1727237832; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=U/q/ee1Hi6Rv/vxDVySTbn/n4UowW9g1FmVfGdNU9g4=; b=j/2N/ackmH7e4hcyF3jiA5WS7yBNZkMPTp4aXFauuxBf2Q6iGzn2Oc+d tSCppyz70t3nBpPzv1CspOMlMCAflhAY2BUKaFFryFRxdem0hO7Fmb1IS x6KIhuRKkgMjSnsKrj4DJx499UEigaPIRApNpt/dcMmKbyZk/YrggcRb8 CEeH1yX4T2F/MVZ73fAK2wF0ftKW+pfIC8vGdHYBbpi9aB1H4ReJXLfAo H6qQH20gx2SPas5QhTuK3x7MZt0EWRnGWJtY3dZf9ZCjXcoDQ1lKWsOMQ sD+SJXQ90Jq11zseoxvMQlLO35g8MUtEq9xOfcbvoPPXa22WMtxKb25tQ A==; X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="412395812" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="412395812" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="814314520" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="814314520" Received: from fvivekku-mobl.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.251.18.72]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:10 -0700 Subject: [PATCH v4 2/6] configfs-tsm: Introduce a shared ABI for attestation reports From: Dan Williams To: linux-coco@lists.linux.dev Cc: Kuppuswamy Sathyanarayanan , Dionna Amalie Glaze , James Bottomley , Peter Gonda , Greg Kroah-Hartman , Samuel Ortiz , Greg Kroah-Hartman , Thomas Gleixner , peterz@infradead.org, linux-kernel@vger.kernel.org, x86@kernel.org, dave.hansen@linux.intel.com Date: Mon, 25 Sep 2023 21:17:09 -0700 Message-ID: <169570182987.596431.14062417344858914481.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> References: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on agentk.vger.email 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 (agentk.vger.email [0.0.0.0]); Mon, 25 Sep 2023 21:17:39 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778083736438371107 X-GMAIL-MSGID: 1778083736438371107 One of the common operations of a TSM (Trusted Security Module) is to provide a way for a TVM (confidential computing guest execution environment) to take a measurement of its launch state, sign it and submit it to a verifying party. Upon successful attestation that verifies the integrity of the TVM additional secrets may be deployed. The concept is common across TSMs, but the implementations are unfortunately vendor specific. While the industry grapples with a common definition of this attestation format [1], Linux need not make this problem worse by defining a new ABI per TSM that wants to perform a similar operation. The current momentum has been to invent new ioctl-ABI per TSM per function which at best is an abdication of the kernel's responsibility to make common infrastructure concepts share common ABI. The proposal, targeted to conceptually work with TDX, SEV-SNP, COVE if not more, is to define a configfs interface to retrieve the TSM-specific blob. report=/sys/kernel/config/tsm/report/report0 mkdir $report dd if=binary_userdata_plus_nonce > $report/inblob hexdump $report/outblob This approach later allows for the standardization of the attestation blob format without needing to invent a new ABI. Once standardization happens the standard format can be emitted by $report/outblob and indicated by $report/provider, or a new attribute like "$report/tcg_coco_report" can emit the standard format alongside the vendor format. Review of previous iterations of this interface identified that there is a need to scale report generation for multiple container environments [2]. Configfs enables a model where each container can bind mount one or more report generation item instances. Still, within a container only a single thread can be manipulating a given configuration instance at a time. A 'generation' count is provided to detect conflicts between multiple threads racing to configure a report instance. The SEV-SNP concepts of "extended reports" and "privilege levels" are optionally enabled by selecting 'tsm_report_ext_type' at register_tsm() time. The expectation is that those concepts are generic enough that they may be adopted by other TSM implementations. In other words, configfs-tsm aims to address a superset of TSM specific functionality with a common ABI where attributes may appear, or not appear, based on the set of concepts the implementation supports. Link: http://lore.kernel.org/r/64961c3baf8ce_142af829436@dwillia2-xfh.jf.intel.com.notmuch [1] Link: http://lore.kernel.org/r/57f3a05e-8fcd-4656-beea-56bb8365ae64@linux.microsoft.com [2] Cc: Kuppuswamy Sathyanarayanan Cc: Dionna Amalie Glaze Cc: James Bottomley Cc: Peter Gonda Cc: Greg Kroah-Hartman Cc: Samuel Ortiz Acked-by: Greg Kroah-Hartman Acked-by: Thomas Gleixner Signed-off-by: Dan Williams --- Documentation/ABI/testing/configfs-tsm | 67 +++++ MAINTAINERS | 8 + drivers/virt/coco/Kconfig | 5 drivers/virt/coco/Makefile | 1 drivers/virt/coco/tsm.c | 411 ++++++++++++++++++++++++++++++++ include/linux/tsm.h | 63 +++++ 6 files changed, 555 insertions(+) create mode 100644 Documentation/ABI/testing/configfs-tsm create mode 100644 drivers/virt/coco/tsm.c create mode 100644 include/linux/tsm.h diff --git a/Documentation/ABI/testing/configfs-tsm b/Documentation/ABI/testing/configfs-tsm new file mode 100644 index 000000000000..ba81083046d3 --- /dev/null +++ b/Documentation/ABI/testing/configfs-tsm @@ -0,0 +1,67 @@ +What: /sys/kernel/config/tsm/report/$name/inblob +Date: September, 2023 +KernelVersion: v6.7 +Contact: linux-coco@lists.linux.dev +Description: + (WO) Up to 64 bytes of user specified binary data. For replay + protection this should include a nonce, but the kernel does not + place any restrictions on the content. + +What: /sys/kernel/config/tsm/report/$name/outblob +Date: September, 2023 +KernelVersion: v6.7 +Contact: linux-coco@lists.linux.dev +Description: + (RO) Binary attestation report generated from @inblob and other + options The format of the report is implementation specific + where the implementation is conveyed via the @provider + attribute. + +What: /sys/kernel/config/tsm/report/$name/certs +Date: September, 2023 +KernelVersion: v6.7 +Contact: linux-coco@lists.linux.dev +Description: + (RO) Zero or more certificates in concatenated PEM format. Refer + to implementation specific documentation on which certificates + might be returned. + +What: /sys/kernel/config/tsm/report/$name/provider +Date: September, 2023 +KernelVersion: v6.7 +Contact: linux-coco@lists.linux.dev +Description: + (RO) A name for the format-specification of @outblob like + "sev-snp" or "tdx" in the near term, or a common standard format + in the future. + +What: /sys/kernel/config/tsm/report/$name/generation +Date: September, 2023 +KernelVersion: v6.7 +Contact: linux-coco@lists.linux.dev +Description: + (RO) The value in this attribute increments each time @inblob or + any option is written. Userspace can detect conflicts by + checking generation before writing to any attribute and making + sure the number of writes matches expectations after reading + @outblob, or it can prevent conflicts by creating a report + instance per requesting context. + +What: /sys/kernel/config/tsm/report/$name/privlevel +Date: September, 2023 +KernelVersion: v6.7 +Contact: linux-coco@lists.linux.dev +Description: + (WO) If a TSM implementation supports the concept of attestation + reports for TVMs running at different privilege levels, like + SEV-SNP "VMPL", specify the privilege level via this attribute. + The minimum acceptable value is conveyed via @privlevel_floor + and the maximum acceptable value is TSM_PRIVLEVEL_MAX (3). + +What: /sys/kernel/config/tsm/report/$name/privlevel_floor +Date: September, 2023 +KernelVersion: v6.7 +Contact: linux-coco@lists.linux.dev +Description: + (RO) Indicates the minimum permissible value that can be written + to @privlevel. diff --git a/MAINTAINERS b/MAINTAINERS index b19995690904..8acbeb029ba1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21889,6 +21889,14 @@ W: https://github.com/srcres258/linux-doc T: git git://github.com/srcres258/linux-doc.git doc-zh-tw F: Documentation/translations/zh_TW/ +TRUSTED SECURITY MODULE (TSM) ATTESTATION REPORTS +M: Dan Williams +L: linux-coco@lists.linux.dev +S: Maintained +F: Documentation/ABI/testing/configfs-tsm +F: drivers/virt/coco/tsm.c +F: include/linux/tsm.h + TTY LAYER AND SERIAL DRIVERS M: Greg Kroah-Hartman M: Jiri Slaby diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig index fc5c64f04c4a..87d142c1f932 100644 --- a/drivers/virt/coco/Kconfig +++ b/drivers/virt/coco/Kconfig @@ -2,6 +2,11 @@ # # Confidential computing related collateral # + +config TSM_REPORTS + select CONFIGFS_FS + tristate + source "drivers/virt/coco/efi_secret/Kconfig" source "drivers/virt/coco/sev-guest/Kconfig" diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile index 55302ef719ad..18c1aba5edb7 100644 --- a/drivers/virt/coco/Makefile +++ b/drivers/virt/coco/Makefile @@ -2,6 +2,7 @@ # # Confidential computing related collateral # +obj-$(CONFIG_TSM_REPORTS) += tsm.o obj-$(CONFIG_EFI_SECRET) += efi_secret/ obj-$(CONFIG_SEV_GUEST) += sev-guest/ obj-$(CONFIG_INTEL_TDX_GUEST) += tdx-guest/ diff --git a/drivers/virt/coco/tsm.c b/drivers/virt/coco/tsm.c new file mode 100644 index 000000000000..343fc77d0509 --- /dev/null +++ b/drivers/virt/coco/tsm.c @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Intel Corporation. All rights reserved. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct tsm_provider { + const struct tsm_ops *ops; + const struct config_item_type *type; + void *data; +} provider; +static DECLARE_RWSEM(tsm_rwsem); + +/** + * DOC: Trusted Security Module (TSM) Attestation Report Interface + * + * The TSM report interface is a common provider of blobs that facilitate + * attestation of a TVM (confidential computing guest) by an attestation + * service. A TSM report combines a user-defined blob (likely a public-key with + * a nonce for a key-exchange protocol) with a signed attestation report. That + * combined blob is then used to obtain secrets provided by an agent that can + * validate the attestation report. The expectation is that this interface is + * invoked infrequently, however configfs allows for multiple agents to + * own their own report generation instances to generate reports as + * often as needed. + * + * The attestation report format is TSM provider specific, when / if a standard + * materializes that can be published instead of the vendor layout. Until then + * the 'provider' attribute indicates the format of 'outblob'. However, + * the common "return a list of certs" capability across multiple TSM + * implementations is returned in a unified @certs attribute. + */ + +struct tsm_report_state { + struct tsm_report report; + unsigned long write_generation; + unsigned long read_generation; + struct config_item cfg; +}; + +enum tsm_data_select { + TSM_REPORT, + TSM_CERTS, +}; + +static struct tsm_report *to_tsm_report(struct config_item *cfg) +{ + struct tsm_report_state *state = + container_of(cfg, struct tsm_report_state, cfg); + + return &state->report; +} + +static struct tsm_report_state *to_state(struct tsm_report *report) +{ + return container_of(report, struct tsm_report_state, report); +} + +static int try_advance_write_generation(struct tsm_report *report) +{ + struct tsm_report_state *state = to_state(report); + + lockdep_assert_held_write(&tsm_rwsem); + + /* + * Malicious or broken userspace has written enough times for + * read_generation == write_generation by modular arithmetic without an + * interim read. Stop accepting updates until the current report + * configuration is read. + */ + if (state->write_generation == state->read_generation - 1) + return -EBUSY; + state->write_generation++; + return 0; +} + +static ssize_t tsm_report_privlevel_store(struct config_item *cfg, + const char *buf, size_t len) +{ + struct tsm_report *report = to_tsm_report(cfg); + unsigned int val; + int rc; + + rc = kstrtouint(buf, 0, &val); + if (rc) + return rc; + + /* + * The valid privilege levels that a TSM might accept, if it accepts a + * privilege level setting at all, are a max of TSM_PRIVLEVEL_MAX (see + * SEV-SNP GHCB) and a minimum of a TSM selected floor value no less + * than 0. + */ + if (provider.ops->privlevel_floor > val || val > TSM_PRIVLEVEL_MAX) + return -EINVAL; + + guard(rwsem_write)(&tsm_rwsem); + rc = try_advance_write_generation(report); + if (rc) + return rc; + report->desc.privlevel = val; + + return len; +} +CONFIGFS_ATTR_WO(tsm_report_, privlevel); + +static ssize_t tsm_report_privlevel_floor_show(struct config_item *cfg, + char *buf) +{ + guard(rwsem_read)(&tsm_rwsem); + return sysfs_emit(buf, "%u\n", provider.ops->privlevel_floor); +} +CONFIGFS_ATTR_RO(tsm_report_, privlevel_floor); + +static ssize_t tsm_report_inblob_write(struct config_item *cfg, + const void *buf, size_t count) +{ + struct tsm_report *report = to_tsm_report(cfg); + int rc; + + guard(rwsem_write)(&tsm_rwsem); + rc = try_advance_write_generation(report); + if (rc) + return rc; + + report->desc.inblob_len = count; + memcpy(report->desc.inblob, buf, count); + return count; +} +CONFIGFS_BIN_ATTR_WO(tsm_report_, inblob, NULL, TSM_INBLOB_MAX); + +static ssize_t tsm_report_generation_show(struct config_item *cfg, char *buf) +{ + struct tsm_report *report = to_tsm_report(cfg); + struct tsm_report_state *state = to_state(report); + + guard(rwsem_read)(&tsm_rwsem); + return sysfs_emit(buf, "%lu\n", state->write_generation); +} +CONFIGFS_ATTR_RO(tsm_report_, generation); + +static ssize_t tsm_report_provider_show(struct config_item *cfg, char *buf) +{ + guard(rwsem_read)(&tsm_rwsem); + return sysfs_emit(buf, "%s\n", provider.ops->name); +} +CONFIGFS_ATTR_RO(tsm_report_, provider); + +static ssize_t __read_report(struct tsm_report *report, void *buf, size_t count, + enum tsm_data_select select) +{ + loff_t offset = 0; + u8 *out, len; + + if (select == TSM_REPORT) { + out = report->outblob; + len = report->outblob_len; + } else { + out = report->certs; + len = report->certs_len; + } + + if (!buf) + return len; + return memory_read_from_buffer(buf, count, &offset, out, len); +} + +static ssize_t read_cached_report(struct tsm_report *report, void *buf, + size_t count, enum tsm_data_select select) +{ + struct tsm_report_state *state = to_state(report); + + guard(rwsem_read)(&tsm_rwsem); + if (!report->desc.inblob_len) + return -EINVAL; + + /* + * A given TSM backend always fills in ->outblob regardless of + * whether the report includes certs or not. + */ + if (!report->outblob || + state->read_generation != state->write_generation) + return -EWOULDBLOCK; + + return __read_report(report, buf, count, select); +} + +static ssize_t tsm_report_read(struct tsm_report *report, void *buf, + size_t count, enum tsm_data_select select) +{ + struct tsm_report_state *state = to_state(report); + const struct tsm_ops *ops; + ssize_t rc; + + /* try to read from the existing report if present and valid... */ + rc = read_cached_report(report, buf, count, select); + if (rc >= 0 || rc != -EWOULDBLOCK) + return rc; + + /* slow path, report may need to be regenerated... */ + guard(rwsem_write)(&tsm_rwsem); + ops = provider.ops; + if (!report->desc.inblob_len) + return -EINVAL; + + /* did another thread already generate this report? */ + if (report->outblob && + state->read_generation == state->write_generation) + goto out; + + kvfree(report->outblob); + kvfree(report->certs); + report->outblob = NULL; + report->certs = NULL; + rc = ops->report_new(report, provider.data); + if (rc < 0) + return rc; + state->read_generation = state->write_generation; +out: + return __read_report(report, buf, count, select); +} + +static ssize_t tsm_report_outblob_read(struct config_item *cfg, void *buf, + size_t count) +{ + struct tsm_report *report = to_tsm_report(cfg); + + return tsm_report_read(report, buf, count, TSM_REPORT); +} +CONFIGFS_BIN_ATTR_RO(tsm_report_, outblob, NULL, TSM_OUTBLOB_MAX); + +static ssize_t tsm_report_certs_read(struct config_item *cfg, void *buf, + size_t count) +{ + struct tsm_report *report = to_tsm_report(cfg); + + return tsm_report_read(report, buf, count, TSM_CERTS); +} +CONFIGFS_BIN_ATTR_RO(tsm_report_, certs, NULL, TSM_OUTBLOB_MAX); + +#define TSM_DEFAULT_ATTRS() \ + &tsm_report_attr_generation, \ + &tsm_report_attr_provider + +static struct configfs_attribute *tsm_report_attrs[] = { + TSM_DEFAULT_ATTRS(), + NULL, +}; + +static struct configfs_bin_attribute *tsm_report_bin_attrs[] = { + &tsm_report_attr_inblob, + &tsm_report_attr_outblob, + &tsm_report_attr_certs, + NULL, +}; + +static struct configfs_attribute *tsm_report_extra_attrs[] = { + TSM_DEFAULT_ATTRS(), + &tsm_report_attr_privlevel, + &tsm_report_attr_privlevel_floor, + NULL, +}; + +static void tsm_report_item_release(struct config_item *cfg) +{ + struct tsm_report *report = to_tsm_report(cfg); + struct tsm_report_state *state = to_state(report); + + kvfree(report->certs); + kvfree(report->outblob); + kfree(state); +} + +static struct configfs_item_operations tsm_report_item_ops = { + .release = tsm_report_item_release, +}; + +const struct config_item_type tsm_report_default_type = { + .ct_owner = THIS_MODULE, + .ct_bin_attrs = tsm_report_bin_attrs, + .ct_attrs = tsm_report_attrs, + .ct_item_ops = &tsm_report_item_ops, +}; +EXPORT_SYMBOL_GPL(tsm_report_default_type); + +const struct config_item_type tsm_report_ext_type = { + .ct_owner = THIS_MODULE, + .ct_bin_attrs = tsm_report_bin_attrs, + .ct_attrs = tsm_report_extra_attrs, + .ct_item_ops = &tsm_report_item_ops, +}; +EXPORT_SYMBOL_GPL(tsm_report_ext_type); + +static struct config_item *tsm_report_make_item(struct config_group *group, + const char *name) +{ + struct tsm_report_state *state; + + guard(rwsem_read)(&tsm_rwsem); + if (!provider.ops) + return ERR_PTR(-ENXIO); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return ERR_PTR(-ENOMEM); + + config_item_init_type_name(&state->cfg, name, provider.type); + return &state->cfg; +} + +static struct configfs_group_operations tsm_report_group_ops = { + .make_item = tsm_report_make_item, +}; + +static const struct config_item_type tsm_reports_type = { + .ct_owner = THIS_MODULE, + .ct_group_ops = &tsm_report_group_ops, +}; + +static const struct config_item_type tsm_root_group_type = { + .ct_owner = THIS_MODULE, +}; + +static struct configfs_subsystem tsm_configfs = { + .su_group = { + .cg_item = { + .ci_namebuf = "tsm", + .ci_type = &tsm_root_group_type, + }, + }, + .su_mutex = __MUTEX_INITIALIZER(tsm_configfs.su_mutex), +}; + +static struct config_group *tsm_report_group; + +int tsm_register(const struct tsm_ops *ops, void *priv, + const struct config_item_type *type) +{ + const struct tsm_ops *conflict; + + if (!type) + type = &tsm_report_default_type; + if (!(type == &tsm_report_default_type || type == &tsm_report_ext_type)) + return -EINVAL; + + guard(rwsem_write)(&tsm_rwsem); + conflict = provider.ops; + if (conflict) { + pr_err("\"%s\" ops already registered\n", conflict->name); + return -EBUSY; + } + + provider.ops = ops; + provider.data = priv; + provider.type = type; + return 0; +} +EXPORT_SYMBOL_GPL(tsm_register); + +int tsm_unregister(const struct tsm_ops *ops) +{ + guard(rwsem_write)(&tsm_rwsem); + if (ops != provider.ops) + return -EBUSY; + provider.ops = NULL; + provider.data = NULL; + provider.type = NULL; + return 0; +} +EXPORT_SYMBOL_GPL(tsm_unregister); + +static int __init tsm_init(void) +{ + struct config_group *root = &tsm_configfs.su_group; + struct config_group *tsm; + int rc; + + config_group_init(root); + rc = configfs_register_subsystem(&tsm_configfs); + if (rc) + return rc; + + tsm = configfs_register_default_group(root, "report", + &tsm_reports_type); + if (IS_ERR(tsm)) { + configfs_unregister_subsystem(&tsm_configfs); + return PTR_ERR(tsm); + } + tsm_report_group = tsm; + + return 0; +} +module_init(tsm_init); + +static void __exit tsm_exit(void) +{ + configfs_unregister_default_group(tsm_report_group); + configfs_unregister_subsystem(&tsm_configfs); +} +module_exit(tsm_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Provide Trusted Security Module attestation reports via configfs"); diff --git a/include/linux/tsm.h b/include/linux/tsm.h new file mode 100644 index 000000000000..1fe1dba3a912 --- /dev/null +++ b/include/linux/tsm.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __TSM_H +#define __TSM_H + +#include +#include +#include + +#define TSM_INBLOB_MAX 64 +#define TSM_OUTBLOB_MAX SZ_32K + +/* + * Privilege level is a nested permission concept to allow confidential + * guests to partition address space, 4-levels are supported. + */ +#define TSM_PRIVLEVEL_MAX 3 + +/** + * struct tsm_desc - option descriptor for generating tsm report blobs + * @privlevel: optional privilege level to associate with @outblob + * @inblob_len: sizeof @inblob + * @inblob: arbitrary input data + */ +struct tsm_desc { + unsigned int privlevel; + size_t inblob_len; + u8 inblob[TSM_INBLOB_MAX]; +}; + +/** + * struct tsm_report - track state of report generation relative to options + * @desc: report generation options / cached report state + * @outblob: generated evidence to provider to the attestation agent + * @outblob_len: sizeof(outblob) + * @write_generation: conflict detection, and report regeneration tracking + * @read_generation: cached report invalidation tracking + * @cfg: configfs interface + */ +struct tsm_report { + struct tsm_desc desc; + size_t outblob_len; + u8 *outblob; + size_t certs_len; + u8 *certs; +}; + +/* + * arch specific ops, only one is expected to be registered at a time + * i.e. only one of SEV, TDX, COVE, etc. + */ +struct tsm_ops { + const char *name; + const int privlevel_floor; + int (*report_new)(struct tsm_report *desc, void *data); +}; + +extern const struct config_item_type tsm_report_ext_type; +extern const struct config_item_type tsm_report_default_type; + +int tsm_register(const struct tsm_ops *ops, void *priv, + const struct config_item_type *type); +int tsm_unregister(const struct tsm_ops *ops); +#endif /* __TSM_H */ From patchwork Tue Sep 26 04:17:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 144820 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:cae8:0:b0:403:3b70:6f57 with SMTP id r8csp1830732vqu; Tue, 26 Sep 2023 04:13:31 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFqgZY+KnHJbU8WtC7KHZPRhq2yJpVzgSO7nyRLsqx2BuGMuQoXUntwKWOqiRhpbVFHVdah X-Received: by 2002:a17:902:7443:b0:1c3:7628:fca8 with SMTP id e3-20020a170902744300b001c37628fca8mr6050332plt.49.1695726811331; Tue, 26 Sep 2023 04:13:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695726811; cv=none; d=google.com; s=arc-20160816; b=k6fgHSXQqKL9vtcI7xm22qq8sBikLV+TF+9WaKqml+j4Pc8TwaKQse87O0jEaHa3z2 k2APB4siX2fFLrTMeAVTnxHt1lx1VuScVQgPYFBylfFsFADlGQgKUYPr2fAI0Z01z8Fq 8bi85rh28ik8oRFY/1wWkR4PZ3zZyUomx3Pqh6ZNrmTEW+Dwu+u9YjV76w/I9J6gK3mq Qlm/piZ7QyZ2+W7NI+W3s3rNJBtnqJs69STOe8QnU/9JrV6NytrTuomHWieePdY/bMkm 5XREfmo/ycErvFs/9T5kVtDVt0p+YwVgRcLv+YO9S6SQdaYJPYJq/N/4D8u4bUPzCjy/ VwXw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject:dkim-signature; bh=8qMjhmFHygTNSN53h9fwrAyZxFfymgwitlXhu8lOv9E=; fh=vMXCV+OLnjwC+OcqrBbJtO2JFZ4/9oy6vg518K/6O28=; b=a6S52K5p+dPhnFq7ifWURryNVUvLUG0I7kVU0mIoWcPgqFFQnlD7XdbGYN8adhbXkM F1ieiW57YfD1f/3aB3HHCcQz1dM3SgvD1g8alY1PXlIZEi3HIZaEisuiYduqN8RJGPQ9 vJE/TeqL2l5lfUOzFSuIvxBtHpjDe198v1Buyi9Q76DKEkwujRNHHQXNM7XH1XfVsDRN LClSaFbRCWKAtLQYSUnBsJbmXGWUw07nC9ttdtv5jBbRPLhoFgPKWrsEhDqD4Y+WY7gg CrJ89q6ZIc+hu3U88Ixu7IaaDuEWeLsdzt4gWYWugXAFp+dxu8B2hJ/ozQ15iD+cbL2U GRAw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=CSqdrlm6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from pete.vger.email (pete.vger.email. [2620:137:e000::3:6]) by mx.google.com with ESMTPS id t4-20020a17090340c400b001bc434b9d95si12678040pld.156.2023.09.26.04.13.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Sep 2023 04:13:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) client-ip=2620:137:e000::3:6; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=CSqdrlm6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by pete.vger.email (Postfix) with ESMTP id 037CE80D543D; Mon, 25 Sep 2023 21:17:55 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at pete.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233615AbjIZER2 (ORCPT + 27 others); Tue, 26 Sep 2023 00:17:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36052 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233098AbjIZERY (ORCPT ); Tue, 26 Sep 2023 00:17:24 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A359BF for ; Mon, 25 Sep 2023 21:17:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695701837; x=1727237837; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yHkxxHhfcS/p1Zj4sNJBN+HXPs+0Ubf8u2ycubsIO3g=; b=CSqdrlm67xxNdLS93wEThmfZXIFP/QheO7Win5Nf3sjFAYzt8/1aOQ0i sXxVIC2eM1476TZp6qyi24eDEXZH8xGN3Uj2CM7sLiDQWSBkdfEB7ONb8 Y2BdU6sjsZOR1m/fP6lefz44F8ns5+1xQzzT10OsLVdNGfLYHY8oFukPI PzhW9VY+weMuLYFrQQwfJBXA4GQxiFCpQ+CoT3MrLHoAhQ4TJ/z8b2/cr Wd2LvzE6v7/FZzj+nVzgIJmWpdgpd6tpk4rqbbOcQpjwhMQtATDBaQ4Z+ 02MNJdT7Y+r4mhu8jHy6QuS9XR43N9rswfTyRUbmtFOlENJVgSWpFyALI A==; X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="412395834" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="412395834" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:17 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="814314528" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="814314528" Received: from fvivekku-mobl.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.251.18.72]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:16 -0700 Subject: [PATCH v4 3/6] virt: sevguest: Prep for kernel internal {get, get_ext}_report() From: Dan Williams To: linux-coco@lists.linux.dev Cc: Borislav Petkov , Tom Lendacky , Dionna Glaze , Brijesh Singh , peterz@infradead.org, linux-kernel@vger.kernel.org, x86@kernel.org, dave.hansen@linux.intel.com Date: Mon, 25 Sep 2023 21:17:16 -0700 Message-ID: <169570183602.596431.6477217304734993370.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> References: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on pete.vger.email 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 (pete.vger.email [0.0.0.0]); Mon, 25 Sep 2023 21:17:55 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778098436875226853 X-GMAIL-MSGID: 1778098436875226853 In preparation for using the configs-tsm facility to convey attestation blobs to userspace, switch to using the 'sockptr' api for copying payloads to provided buffers where 'sockptr' handles user vs kernel buffers. While configfs-tsm is meant to replace existing confidential computing ioctl() implementations for attestation report retrieval the old ioctl() path needs to stick around for a deprecation period. No behavior change intended. Cc: Borislav Petkov Cc: Tom Lendacky Cc: Dionna Glaze Cc: Brijesh Singh Signed-off-by: Dan Williams Reviewed-by: Kuppuswamy Sathyanarayanan --- drivers/virt/coco/sev-guest/sev-guest.c | 50 ++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index 97dbe715e96a..c3c9e9ea691f 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -470,7 +471,13 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, return 0; } -static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg) +struct snp_req_resp { + sockptr_t req_data; + sockptr_t resp_data; +}; + +static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg, + struct snp_req_resp *io) { struct snp_guest_crypto *crypto = snp_dev->crypto; struct snp_report_resp *resp; @@ -479,10 +486,10 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io lockdep_assert_held(&snp_cmd_mutex); - if (!arg->req_data || !arg->resp_data) + if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data)) return -EINVAL; - if (copy_from_user(&req, (void __user *)arg->req_data, sizeof(req))) + if (copy_from_sockptr(&req, io->req_data, sizeof(req))) return -EFAULT; /* @@ -501,7 +508,7 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io if (rc) goto e_free; - if (copy_to_user((void __user *)arg->resp_data, resp, sizeof(*resp))) + if (copy_to_sockptr(io->resp_data, resp, sizeof(*resp))) rc = -EFAULT; e_free: @@ -550,22 +557,25 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque return rc; } -static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg) +static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg, + struct snp_req_resp *io) + { struct snp_guest_crypto *crypto = snp_dev->crypto; struct snp_ext_report_req req; struct snp_report_resp *resp; int ret, npages = 0, resp_len; + sockptr_t certs_address; lockdep_assert_held(&snp_cmd_mutex); - if (!arg->req_data || !arg->resp_data) + if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data)) return -EINVAL; - if (copy_from_user(&req, (void __user *)arg->req_data, sizeof(req))) + if (copy_from_sockptr(&req, io->req_data, sizeof(req))) return -EFAULT; - /* userspace does not want certificate data */ + /* caller does not want certificate data */ if (!req.certs_len || !req.certs_address) goto cmd; @@ -573,8 +583,13 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques !IS_ALIGNED(req.certs_len, PAGE_SIZE)) return -EINVAL; - if (!access_ok((const void __user *)req.certs_address, req.certs_len)) - return -EFAULT; + if (sockptr_is_kernel(io->resp_data)) { + certs_address = KERNEL_SOCKPTR((void *)req.certs_address); + } else { + certs_address = USER_SOCKPTR((void __user *)req.certs_address); + if (!access_ok(certs_address.user, req.certs_len)) + return -EFAULT; + } /* * Initialize the intermediate buffer with all zeros. This buffer @@ -604,21 +619,19 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) { req.certs_len = snp_dev->input.data_npages << PAGE_SHIFT; - if (copy_to_user((void __user *)arg->req_data, &req, sizeof(req))) + if (copy_to_sockptr(io->req_data, &req, sizeof(req))) ret = -EFAULT; } if (ret) goto e_free; - if (npages && - copy_to_user((void __user *)req.certs_address, snp_dev->certs_data, - req.certs_len)) { + if (npages && copy_to_sockptr(certs_address, snp_dev->certs_data, req.certs_len)) { ret = -EFAULT; goto e_free; } - if (copy_to_user((void __user *)arg->resp_data, resp, sizeof(*resp))) + if (copy_to_sockptr(io->resp_data, resp, sizeof(*resp))) ret = -EFAULT; e_free: @@ -631,6 +644,7 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long struct snp_guest_dev *snp_dev = to_snp_dev(file); void __user *argp = (void __user *)arg; struct snp_guest_request_ioctl input; + struct snp_req_resp io; int ret = -ENOTTY; if (copy_from_user(&input, argp, sizeof(input))) @@ -651,15 +665,17 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long return -ENOTTY; } + io.req_data = USER_SOCKPTR((void __user *)input.req_data); + io.resp_data = USER_SOCKPTR((void __user *)input.resp_data); switch (ioctl) { case SNP_GET_REPORT: - ret = get_report(snp_dev, &input); + ret = get_report(snp_dev, &input, &io); break; case SNP_GET_DERIVED_KEY: ret = get_derived_key(snp_dev, &input); break; case SNP_GET_EXT_REPORT: - ret = get_ext_report(snp_dev, &input); + ret = get_ext_report(snp_dev, &input, &io); break; default: break; From patchwork Tue Sep 26 04:17:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 144746 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:cae8:0:b0:403:3b70:6f57 with SMTP id r8csp1717451vqu; Mon, 25 Sep 2023 23:53:01 -0700 (PDT) X-Google-Smtp-Source: AGHT+IE2yI9M4ppr/38zoGGXboXWiaZKfHS+4w1DVL5sObU1ppiloUqDMPSdp6QukfY/6GXS5xR7 X-Received: by 2002:a05:6a20:96d4:b0:15d:8857:79fb with SMTP id hq20-20020a056a2096d400b0015d885779fbmr8632180pzc.32.1695711181725; Mon, 25 Sep 2023 23:53:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695711181; cv=none; d=google.com; s=arc-20160816; b=i1vDZkVAuNIwzP2K3Yo2p1k7188wUBpex9U+DaIebyyIzA+29xYvl+pxJ96h8MJD4o 8dQhc5t0VMZSRY3yZVFB5DIhdHLcqzYgoXyrjf9zqpzEhX6/9zLuYUCq2V7TgSfVF6NR zS/F7d8bfxIByftIPB8p+RGx9s3W5PusXLi2bsEf+XlbHJyeeDoUNAiH63AjRyxe9zk9 nIUk3sOlyaxgFI1Rn89MQZYAZK6x7w9B3oI2m5HdqgRxIh2nz96INIoGW5ft0yoik0mj zOYe1tkJ0yopI2gcgCXntB3HKHnwd3AkmWkJI+mVkdqJLpz49dvJDVyZSy1yQW55oemf mucQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject:dkim-signature; bh=llOYuKpCGiFQykK3KHvx+udZobEsTzG8G8vb/AeL730=; fh=RrijT3tJL98V46dhGYxkE0am/XK+EBz9F1RrcTmm9Pc=; b=Rl3hVQJau8MSUkU2RNudc+sH4unjOR9pIFzryB3GqFk+c/wttjaazPmBLmlxSPs8g0 EIHuInuZRwb6TaG5IKr2OjtQ2KB4yh61hte0t82LDmbRk2DIu3T9jvIvM93xTS+M/Ojh F7Br6uM/cNi8nLXPoKcZvDtqIt/8fAHzDHmWojvJOvfPOtRzUqha3MRG67kHaUcqW0Xz eNcGc5SBqn4Gv8OZpT/Wjew1KhvM0Tcl4zu5SmQWPhfUz9P/V0seK646xMfSQkAoXkww J99KnNmTLdS8xQAm3PjaMUlE2cyiAL7XN/FgVSVfVLFP4uckhsK7attaj1CHTEjGm/TV KoAg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=V8D8lo5+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.31 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from morse.vger.email (morse.vger.email. [23.128.96.31]) by mx.google.com with ESMTPS id f5-20020a056a0022c500b0068fb8704b9csi12703403pfj.28.2023.09.25.23.53.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Sep 2023 23:53:01 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.31 as permitted sender) client-ip=23.128.96.31; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=V8D8lo5+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.31 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by morse.vger.email (Postfix) with ESMTP id 518908251723; Mon, 25 Sep 2023 21:18:23 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at morse.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233666AbjIZERl (ORCPT + 27 others); Tue, 26 Sep 2023 00:17:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44652 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233633AbjIZERf (ORCPT ); Tue, 26 Sep 2023 00:17:35 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8E93012A for ; Mon, 25 Sep 2023 21:17:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695701843; x=1727237843; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=bDADOCK5y6EfdtJCioVa1Ksl06xw+gGHZUtfoSD5ALE=; b=V8D8lo5+1HG8X0EJ8TY7l4O2f2Ut1XoMIqARpvbUOonps/MGt51nPAFA ZWSI4/Sr8gZUeUuEzAMKsomMB/8SmaL5Y9iYcNBCqfgAhC1DwfvIeiLRK WE3Iy0IfgTwMnRKam6gHynFinm5i6EskerAty+aj/g2QSFz8cHfjLDJgG E7HSy6nDY9eTPhW50u8ROf1Ww+yrH3obyvrWEfVVhQoYf3yQDAkDLJ7jy 60ilYo5SbCuYral0ynHUL4wrIYoZ90qtr81UL+zphxvuVkYcH3tNeYlMN wRwjAPz00jeerQm7wPZkNO8kIOBVuNX/i3bOfscL/5h+KNCBq1C8R+5qu g==; X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="412395854" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="412395854" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="814314534" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="814314534" Received: from fvivekku-mobl.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.251.18.72]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:22 -0700 Subject: [PATCH v4 4/6] mm/slab: Add __free() support for kvfree From: Dan Williams To: linux-coco@lists.linux.dev Cc: Andrew Morton , Peter Zijlstra , Greg Kroah-Hartman , Pankaj Gupta , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, x86@kernel.org, dave.hansen@linux.intel.com Date: Mon, 25 Sep 2023 21:17:22 -0700 Message-ID: <169570184210.596431.3407746911924957078.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> References: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on morse.vger.email 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 (morse.vger.email [0.0.0.0]); Mon, 25 Sep 2023 21:18:23 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778082047704951108 X-GMAIL-MSGID: 1778082047704951108 Allow for the declaration of variables that trigger kvfree() when they go out of scope. The check for NULL and call to kvfree() can be elided by the compiler in most cases, otherwise without the NULL check an unnecessary call to kvfree() may be emitted. Peter proposed a comment for this detail [1]. Link: http://lore.kernel.org/r/20230816103102.GF980931@hirez.programming.kicks-ass.net [1] Cc: Andrew Morton Cc: Peter Zijlstra Cc: Greg Kroah-Hartman Acked-by: Pankaj Gupta Acked-by: Greg Kroah-Hartman Signed-off-by: Dan Williams --- include/linux/slab.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/slab.h b/include/linux/slab.h index 8228d1276a2f..df4c2d45bb86 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -763,6 +763,8 @@ static inline __alloc_size(1, 2) void *kvcalloc(size_t n, size_t size, gfp_t fla extern void *kvrealloc(const void *p, size_t oldsize, size_t newsize, gfp_t flags) __realloc_size(3); extern void kvfree(const void *addr); +DEFINE_FREE(kvfree, void *, if (_T) kvfree(_T)) + extern void kvfree_sensitive(const void *addr, size_t len); unsigned int kmem_cache_size(struct kmem_cache *s); From patchwork Tue Sep 26 04:17:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 144727 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:cae8:0:b0:403:3b70:6f57 with SMTP id r8csp1689408vqu; Mon, 25 Sep 2023 22:42:25 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHE3fxXehuMBJxmDJXdkCpeZgMAg0cU8ZsU8CtzfRhrYvMQzFM4wJ/c6/KOTcXTJIYoeZo1 X-Received: by 2002:a05:6808:14a:b0:3ab:7f46:ecc5 with SMTP id h10-20020a056808014a00b003ab7f46ecc5mr10997578oie.35.1695706944763; Mon, 25 Sep 2023 22:42:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695706944; cv=none; d=google.com; s=arc-20160816; b=d6R+V14dfJMmTeh3xeGkSomKTrTA16Nqx2BjNTW4DJnHjcj5K+g+ILjLQ4ZL9B8j+0 SKt0bRWwDuka8DX9wq9AOwoyivJ2VCxWHA62C+hSdTHY7w+SWgE1lHaTUaYgqc3WqU3T sYCkVRGVcOPoAJ5Lo2VqkLN1Yy0UEdqqXiFTrSmdT8JGTqTgwel3dwNGKtqOpKFB85Bl UB7/4HwMkpWy6mJDD7h/DmQ9JPYpnDIHRryr0hjjvsD/zYpo4qFFrQBvEmeRB9nDCsG+ pdIiFX6gzw6XfDN6U7z+wjp8yAgmXJYw59+c2WBRe00rfcaSNYO5a7rMWo53aDshF7NY XmAA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject:dkim-signature; bh=TTQTtZzI2lmCTMXnt0ntU55LeXYXmdEg18y7i51Pi0s=; fh=B8WVFRl0FP+Ak9velAM7EuDpPsDOw2/sHXoh2cNdz4c=; b=UtcqpflBL+s6hH4Ifxmp90gkMZSjGCPeznmWl3kQ0iH9WGIZYzuJmyHyvhGW7kWGGg hQ28f3B2BxcFsDAfBm3iJjDH63wH+bzdH+RitiJi+8zQg9rqIgJhnHrafE3RJseKc2ZF Z5yN6wTEvpm6hfBKnKz8H99Vtxr8frp1x8ZjPRPBdKLMBjn7R2pi2xqGx8hTXPWDUO1u LdHlMMtbVha1b+ZOoREGdyl7VaAKYodWDoqOqso+Hx4UJ+pRuvBtyzQ9+aW8KnMWVZlX gAnXbyGcmlSpEZW6qc73AHq8yhJ1izJHVRoOjGcw2QlcqMz0ULfxhyxi1HGn81M9UOx5 U4xw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b="CNE/9wHO"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from snail.vger.email (snail.vger.email. [2620:137:e000::3:7]) by mx.google.com with ESMTPS id k6-20020a6568c6000000b005702c84e4c2si11801370pgt.508.2023.09.25.22.42.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Sep 2023 22:42:24 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) client-ip=2620:137:e000::3:7; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b="CNE/9wHO"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id 753678021287; Mon, 25 Sep 2023 21:17:53 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233643AbjIZERq (ORCPT + 27 others); Tue, 26 Sep 2023 00:17:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44788 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233664AbjIZERl (ORCPT ); Tue, 26 Sep 2023 00:17:41 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 89F6DCCD for ; Mon, 25 Sep 2023 21:17:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695701849; x=1727237849; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=PfDJdV1MeteTn9hq9ZkG+FRq6bGpd3Tn8MKDSNKJEJQ=; b=CNE/9wHO8LnIr9AtWhRS6a+hryPeQWiXSP34uBnKTzROmkR/hZoAq6a/ iNDomDNXUaGoU0dDfpdaXOdyEmIUzcCXxIY9f2a5d+H7WSrQBv7oG/ulP 65/1FNI7E9SR0DpuX0EQxYWquIgt0RFC0h7m7+aEAH8gX+T+fE0S2fJFz 36STBlE6MBxf+cHdgMtEHc3XB5tAdYwekSvtVQyYFEIvN92IudGgAFbeH NZHvpECQoe3NEPUxXQHET4mSXzMVqsz4fwaHBoRd2gklwtJAcN4D3KxXa KFXNMV5CV1Vu65sHTJhXluzVl8T4FBX/UTA0GynV6T3WL21gG/cHnJtd+ A==; X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="412395867" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="412395867" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="814314543" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="814314543" Received: from fvivekku-mobl.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.251.18.72]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:28 -0700 Subject: [PATCH v4 5/6] virt: sevguest: Add TSM_REPORTS support for SNP_{GET, GET_EXT}_REPORT From: Dan Williams To: linux-coco@lists.linux.dev Cc: Borislav Petkov , Tom Lendacky , Dionna Glaze , Brijesh Singh , Jeremi Piotrowski , peterz@infradead.org, linux-kernel@vger.kernel.org, x86@kernel.org, dave.hansen@linux.intel.com Date: Mon, 25 Sep 2023 21:17:28 -0700 Message-ID: <169570184829.596431.15991881056638719011.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> References: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, RCVD_IN_DNSWL_BLOCKED,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_NONE,SPF_NONE 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 (snail.vger.email [0.0.0.0]); Mon, 25 Sep 2023 21:17:53 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778077605371155382 X-GMAIL-MSGID: 1778077605371155382 The sevguest driver was a first mover in the confidential computing space. As a first mover that afforded some leeway to build the driver without concern for common infrastructure. Now that sevguest is no longer a singleton [1] the common operation of building and transmitting attestation report blobs can / should be made common. In this model the so called "TSM-provider" implementations can share a common envelope ABI even if the contents of that envelope remain vendor-specific. When / if the industry agrees on an attestation record format, that definition can also fit in the same ABI. In the meantime the kernel's maintenance burden is reduced and collaboration on the commons is increased. Convert sevguest to use CONFIG_TSM_REPORTS to retrieve the data that the SNP_GET_EXT_REPORT ioctl produces. An example flow follows for retrieving the report blob via the TSM interface utility, assuming no nonce and VMPL==2: report=/sys/kernel/config/tsm/report/report0 mkdir $report echo 2 > $report/privlevel dd if=/dev/urandom bs=64 count=1 > $report/inblob hexdump -C $report/outblob cat $report/certs rmdir $report Given that the platform implementation is free to return empty certificate data if none is available it lets configfs-tsm be simplified if it only needs to worry about one output format. The old ioctls can be lazily deprecated, the main motivation of this effort is to stop the proliferation of new ioctls, and to increase cross-vendor collaboration. Note, only compile-tested. Link: http://lore.kernel.org/r/64961c3baf8ce_142af829436@dwillia2-xfh.jf.intel.com.notmuch [1] Cc: Borislav Petkov Cc: Tom Lendacky Cc: Dionna Glaze Cc: Brijesh Singh Cc: Jeremi Piotrowski Signed-off-by: Dan Williams --- drivers/virt/coco/sev-guest/Kconfig | 1 drivers/virt/coco/sev-guest/sev-guest.c | 130 +++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/drivers/virt/coco/sev-guest/Kconfig b/drivers/virt/coco/sev-guest/Kconfig index da2d7ca531f0..1cffc72c41cb 100644 --- a/drivers/virt/coco/sev-guest/Kconfig +++ b/drivers/virt/coco/sev-guest/Kconfig @@ -5,6 +5,7 @@ config SEV_GUEST select CRYPTO select CRYPTO_AEAD2 select CRYPTO_GCM + select TSM_REPORTS help SEV-SNP firmware provides the guest a mechanism to communicate with the PSP without risk from a malicious hypervisor who wishes to read, diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index c3c9e9ea691f..646feb433b1c 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -16,10 +16,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -759,6 +761,126 @@ static u8 *get_vmpck(int id, struct snp_secrets_page_layout *layout, u32 **seqno return key; } +struct snp_msg_report_resp_hdr { + u32 status; + u32 report_size; + u8 rsvd[24]; +}; +#define SNP_REPORT_INVALID_PARAM 0x16 +#define SNP_REPORT_INVALID_KEY_SEL 0x27 + +struct snp_msg_cert_entry { + unsigned char guid[16]; + u32 offset; + u32 length; +}; + +static int sev_report_new(struct tsm_report *report, void *data) +{ + static const struct snp_msg_cert_entry zero_ent = { 0 }; + struct tsm_desc *desc = &report->desc; + struct snp_guest_dev *snp_dev = data; + struct snp_msg_report_resp_hdr hdr; + const int report_size = SZ_4K; + const int ext_size = SZ_16K; + int ret, size = report_size + ext_size; + int certs_size, cert_count, i, offset; + u8 *certs_address; + + if (desc->inblob_len != 64) + return -EINVAL; + + void *buf __free(kvfree) = kvzalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + guard(mutex)(&snp_cmd_mutex); + certs_address = buf + report_size; + struct snp_ext_report_req ext_req = { + .data = { .vmpl = desc->privlevel }, + .certs_address = (__u64)certs_address, + .certs_len = ext_size, + }; + memcpy(&ext_req.data.user_data, desc->inblob, desc->inblob_len); + + struct snp_guest_request_ioctl input = { + .msg_version = 1, + .req_data = (__u64)&ext_req, + .resp_data = (__u64)buf, + }; + struct snp_req_resp io = { + .req_data = KERNEL_SOCKPTR(&ext_req), + .resp_data = KERNEL_SOCKPTR(buf), + }; + + ret = get_ext_report(snp_dev, &input, &io); + + if (ret) + return ret; + + memcpy(&hdr, buf, sizeof(hdr)); + if (hdr.status == SNP_REPORT_INVALID_PARAM) + return -EINVAL; + if (hdr.status == SNP_REPORT_INVALID_KEY_SEL) + return -EINVAL; + if (hdr.status) + return -ENXIO; + if ((hdr.report_size + sizeof(hdr)) > report_size) + return -ENOMEM; + + void *rbuf __free(kvfree) = kvzalloc(hdr.report_size, GFP_KERNEL); + if (!rbuf) + return -ENOMEM; + + memcpy(rbuf, buf + sizeof(hdr), hdr.report_size); + report->outblob = no_free_ptr(rbuf); + report->outblob_len = hdr.report_size; + + for (i = 0; i < ext_size / sizeof(struct snp_msg_cert_entry); i++) { + struct snp_msg_cert_entry *certs = buf + report_size; + + if (memcmp(&certs[i], &zero_ent, sizeof(zero_ent)) == 0) + break; + certs_size += certs[i].length; + } + cert_count = i; + + /* No certs to report */ + if (cert_count == 0) + return 0; + + /* sanity check that the entire certs table with metadata fits */ + if ((cert_count + 1) * sizeof(zero_ent) + certs_size > ext_size) + return -ENXIO; + + void *cbuf __free(kvfree) = kvzalloc(certs_size, GFP_KERNEL); + if (!cbuf) + return -ENOMEM; + + /* Concatenate returned certs */ + for (i = 0, offset = 0; i < cert_count; i++) { + struct snp_msg_cert_entry *certs = buf + report_size; + + memcpy(cbuf + offset, certs_address + certs[i].offset, certs[i].length); + offset += certs[i].length; + } + + report->certs = no_free_ptr(cbuf); + report->certs_len = certs_size; + + return 0; +} + +static const struct tsm_ops sev_tsm_ops = { + .name = KBUILD_MODNAME, + .report_new = sev_report_new, +}; + +static void unregister_sev_tsm(void *data) +{ + tsm_unregister(&sev_tsm_ops); +} + static int __init sev_guest_probe(struct platform_device *pdev) { struct snp_secrets_page_layout *layout; @@ -832,6 +954,14 @@ static int __init sev_guest_probe(struct platform_device *pdev) snp_dev->input.resp_gpa = __pa(snp_dev->response); snp_dev->input.data_gpa = __pa(snp_dev->certs_data); + ret = tsm_register(&sev_tsm_ops, snp_dev, &tsm_report_ext_type); + if (ret) + goto e_free_cert_data; + + ret = devm_add_action_or_reset(&pdev->dev, unregister_sev_tsm, NULL); + if (ret) + goto e_free_cert_data; + ret = misc_register(misc); if (ret) goto e_free_cert_data; From patchwork Tue Sep 26 04:17:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 144741 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:cae8:0:b0:403:3b70:6f57 with SMTP id r8csp1713854vqu; Mon, 25 Sep 2023 23:43:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFcJK1NPCiWmfykayAOAhD5lyZLzpSn5SrkIAVTHfYbTymtVkqu3ELgKWV1QlaJif+yXatm X-Received: by 2002:a17:902:ce8b:b0:1c5:7d49:570e with SMTP id f11-20020a170902ce8b00b001c57d49570emr3103234plg.29.1695710631083; Mon, 25 Sep 2023 23:43:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695710631; cv=none; d=google.com; s=arc-20160816; b=n8MUsG0A4F+Xw24mcIxD6BbV4JGfMmw7vx+fsAlUPlPQSxzIOO9bLPSbqYNS/yTLmk DtUSEZAj62lCpK0WWaG42sDOkgHc23zmnJDCoYCYntBzNqLi12Sm/KpNYuosGjJkQjaT ZStpu0jwbYEZXZ7GggE/SnQ0+gryff4raDpv3H/ZXuNPvJKGO9hDwtuQMEduh87yPuQ+ 5WqNOX79MkovqdGQNkNurexe7EXtKzaUucnHy2JUPUgigcZHnyeW1wGLa9ZejmUpmiwL PrMSNWRlUHCM7zGruvkIOhsTPnpNlfgiAUzr674wsNdGVmjeRNpPAUi9Od+gS4+sXoG2 9Skw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject:dkim-signature; bh=KXLQTddE2So8t+N2SxUBXAgCZkB0aBgJBHX9zcCULEc=; fh=wTHGMrJoJKejUZCoa6m5EsJUYK1NL0cYeMxGPiMv5Kw=; b=qfXXmsMb0aDA2A1bIOgrRcY/3bE3Q7XxU9mDiBw9Pa/tQUi0926G+CyloLGaqv7euL smqQEJP4n7f5u+ymxn1nnVI7UzZG4ntPXZfIYHfNbyvnsz4XnCf7GtgOQwKAWI28vwoW 4Hu4QSS9TmSuaq9NDYE2B3cVRhZyJnRZTGORXmOT+iQaYWebhirKZJNxteVPPKLdGPZs qLV7CaaiUrRIcE2MsNZMFR6MyQgWiBJJHBjRVi+TIvANhHhQlGvMOlyvLFmblyVs1zFG nT9p3QZzoWlq7Nk0Ln2jIrFalw8KcEGybyB+jTK246mw5XMSdnbw8pf4HuTXUHeVHMlE d0AQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=NnJQ2U+Q; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from lipwig.vger.email (lipwig.vger.email. [23.128.96.33]) by mx.google.com with ESMTPS id n18-20020a170902e55200b001b82da85c5asi12700470plf.336.2023.09.25.23.43.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Sep 2023 23:43:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) client-ip=23.128.96.33; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=NnJQ2U+Q; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by lipwig.vger.email (Postfix) with ESMTP id D15A1808D201; Mon, 25 Sep 2023 21:18:25 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at lipwig.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233625AbjIZESG (ORCPT + 27 others); Tue, 26 Sep 2023 00:18:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44652 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233637AbjIZERq (ORCPT ); Tue, 26 Sep 2023 00:17:46 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AEB4011F for ; Mon, 25 Sep 2023 21:17:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695701855; x=1727237855; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4CvzD8vnm9Hmd+l6kx9YigHSx9vV/7dsCiz6scdND3s=; b=NnJQ2U+QCfN3bCHICBFxwRyBxlXyyiAAgXpFu/TZ2nCkXkMPaAwpOfe/ OSJ11TklIUZXw5VKs1VzZ/Ker6NBVDXxfhy/up3kjnrNl/yCDT8NtjaSK w0YO05YfX1/INRRBuofY4dXQe1meWqUaU1/x3+j/IWfCqPerdOI6yRqGf qZUA4h9NlaqCwyqqJaO4l6WO550l6oGo9gT+HWIz7y/+NPydV9J4UPtrA 0d0E0YtIlVkMT3N8wLbTkz0blkdVP1HNwpGa6bDFVbLCiXkqpdTqoO2NF iqwcWbgWnGuvCk7RKKfaiiQnmfrPovervYxQ/1GB6vhnZNylWXXt7Kl29 Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="360856997" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="360856997" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10843"; a="698312218" X-IronPort-AV: E=Sophos;i="6.03,177,1694761200"; d="scan'208";a="698312218" Received: from fvivekku-mobl.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.251.18.72]) by orsmga003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Sep 2023 21:17:34 -0700 Subject: [PATCH v4 6/6] virt: tdx-guest: Add Quote generation support using TSM_REPORTS From: Dan Williams To: linux-coco@lists.linux.dev Cc: Kuppuswamy Sathyanarayanan , Erdem Aktas , peterz@infradead.org, linux-kernel@vger.kernel.org, x86@kernel.org, dave.hansen@linux.intel.com Date: Mon, 25 Sep 2023 21:17:34 -0700 Message-ID: <169570185411.596431.3153227201984845022.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> References: <169570181657.596431.6178773442587231200.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lipwig.vger.email 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 (lipwig.vger.email [0.0.0.0]); Mon, 25 Sep 2023 21:18:25 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778081470830757371 X-GMAIL-MSGID: 1778081470830757371 From: Kuppuswamy Sathyanarayanan In TDX guest, the attestation process is used to verify the TDX guest trustworthiness to other entities before provisioning secrets to the guest. The first step in the attestation process is TDREPORT generation, which involves getting the guest measurement data in the format of TDREPORT, which is further used to validate the authenticity of the TDX guest. TDREPORT by design is integrity-protected and can only be verified on the local machine. To support remote verification of the TDREPORT in a SGX-based attestation, the TDREPORT needs to be sent to the SGX Quoting Enclave (QE) to convert it to a remotely verifiable Quote. SGX QE by design can only run outside of the TDX guest (i.e. in a host process or in a normal VM) and guest can use communication channels like vsock or TCP/IP to send the TDREPORT to the QE. But for security concerns, the TDX guest may not support these communication channels. To handle such cases, TDX defines a GetQuote hypercall which can be used by the guest to request the host VMM to communicate with the SGX QE. More details about GetQuote hypercall can be found in TDX Guest-Host Communication Interface (GHCI) for Intel TDX 1.0, section titled "TDG.VP.VMCALL". Trusted Security Module (TSM) [1] exposes a common ABI for Confidential Computing Guest platforms to get the measurement data via ConfigFS. Extend the TSM framework and add support to allow an attestation agent to get the TDX Quote data (included usage example below). report=/sys/kernel/config/tsm/report/report0 mkdir $report dd if=/dev/urandom bs=64 count=1 > $report/inblob hexdump -C $report/outblob rmdir $report GetQuote TDVMCALL requires TD guest pass a 4K aligned shared buffer with TDREPORT data as input, which is further used by the VMM to copy the TD Quote result after successful Quote generation. To create the shared buffer, allocate a large enough memory and mark it shared using set_memory_decrypted() in tdx_guest_init(). This buffer will be re-used for GetQuote requests in the TDX TSM handler. Although this method reserves a fixed chunk of memory for GetQuote requests, such one time allocation can help avoid memory fragmentation related allocation failures later in the uptime of the guest. Since the Quote generation process is not time-critical or frequently used, the current version uses a polling model for Quote requests and it also does not support parallel GetQuote requests. Link: https://lore.kernel.org/lkml/169342399185.3934343.3035845348326944519.stgit@dwillia2-xfh.jf.intel.com/ [1] Signed-off-by: Kuppuswamy Sathyanarayanan Reviewed-by: Erdem Aktas Signed-off-by: Dan Williams --- arch/x86/coco/tdx/tdx.c | 21 +++ arch/x86/include/asm/shared/tdx.h | 1 arch/x86/include/asm/tdx.h | 2 drivers/virt/coco/tdx-guest/Kconfig | 1 drivers/virt/coco/tdx-guest/tdx-guest.c | 229 +++++++++++++++++++++++++++++++ 5 files changed, 253 insertions(+), 1 deletion(-) diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index 1d6b863c42b0..752867b1d11b 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -104,6 +104,27 @@ int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport) } EXPORT_SYMBOL_GPL(tdx_mcall_get_report0); +/** + * tdx_hcall_get_quote() - Wrapper to request TD Quote using GetQuote + * hypercall. + * @buf: Address of the directly mapped shared kernel buffer which + * contains TDREPORT. The same buffer will be used by VMM to + * store the generated TD Quote output. + * @size: size of the tdquote buffer (4KB-aligned). + * + * Refer to section titled "TDG.VP.VMCALL" in the TDX GHCI + * v1.0 specification for more information on GetQuote hypercall. + * It is used in the TDX guest driver module to get the TD Quote. + * + * Return 0 on success or error code on failure. + */ +u64 tdx_hcall_get_quote(u8 *buf, size_t size) +{ + /* Since buf is a shared memory, set the shared (decrypted) bits */ + return _tdx_hypercall(TDVMCALL_GET_QUOTE, cc_mkdec(virt_to_phys(buf)), size, 0, 0); +} +EXPORT_SYMBOL_GPL(tdx_hcall_get_quote); + static void __noreturn tdx_panic(const char *msg) { struct tdx_hypercall_args args = { diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h index 7513b3bb69b7..9eab19950f39 100644 --- a/arch/x86/include/asm/shared/tdx.h +++ b/arch/x86/include/asm/shared/tdx.h @@ -22,6 +22,7 @@ /* TDX hypercall Leaf IDs */ #define TDVMCALL_MAP_GPA 0x10001 +#define TDVMCALL_GET_QUOTE 0x10002 #define TDVMCALL_REPORT_FATAL_ERROR 0x10003 #ifndef __ASSEMBLY__ diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 603e6d1e9d4a..ebd1cda4875f 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -52,6 +52,8 @@ bool tdx_early_handle_ve(struct pt_regs *regs); int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport); +u64 tdx_hcall_get_quote(u8 *buf, size_t size); + #else static inline void tdx_early_init(void) { }; diff --git a/drivers/virt/coco/tdx-guest/Kconfig b/drivers/virt/coco/tdx-guest/Kconfig index 14246fc2fb02..22dd59e19431 100644 --- a/drivers/virt/coco/tdx-guest/Kconfig +++ b/drivers/virt/coco/tdx-guest/Kconfig @@ -1,6 +1,7 @@ config TDX_GUEST_DRIVER tristate "TDX Guest driver" depends on INTEL_TDX_GUEST + select TSM_REPORTS help The driver provides userspace interface to communicate with the TDX module to request the TDX guest details like attestation diff --git a/drivers/virt/coco/tdx-guest/tdx-guest.c b/drivers/virt/coco/tdx-guest/tdx-guest.c index 5e44a0fa69bd..1253bf76b570 100644 --- a/drivers/virt/coco/tdx-guest/tdx-guest.c +++ b/drivers/virt/coco/tdx-guest/tdx-guest.c @@ -12,12 +12,60 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include +/* + * Intel's SGX QE implementation generally uses Quote size less + * than 8K (2K Quote data + ~5K of certificate blob). + */ +#define GET_QUOTE_BUF_SIZE SZ_8K + +#define GET_QUOTE_CMD_VER 1 + +/* TDX GetQuote status codes */ +#define GET_QUOTE_SUCCESS 0 +#define GET_QUOTE_IN_FLIGHT 0xffffffffffffffff + +/* struct tdx_quote_buf: Format of Quote request buffer. + * @version: Quote format version, filled by TD. + * @status: Status code of Quote request, filled by VMM. + * @in_len: Length of TDREPORT, filled by TD. + * @out_len: Length of Quote data, filled by VMM. + * @data: Quote data on output or TDREPORT on input. + * + * More details of Quote request buffer can be found in TDX + * Guest-Host Communication Interface (GHCI) for Intel TDX 1.0, + * section titled "TDG.VP.VMCALL" + */ +struct tdx_quote_buf { + u64 version; + u64 status; + u32 in_len; + u32 out_len; + u8 data[]; +}; + +/* Quote data buffer */ +static void *quote_data; + +/* Lock to streamline quote requests */ +static DEFINE_MUTEX(quote_lock); + +/* + * GetQuote request timeout in seconds. Expect that 30 seconds + * is enough time for QE to respond to any Quote requests. + */ +static u32 getquote_timeout = 30; + static long tdx_get_report0(struct tdx_report_req __user *req) { u8 *reportdata, *tdreport; @@ -53,6 +101,154 @@ static long tdx_get_report0(struct tdx_report_req __user *req) return ret; } +static void free_quote_buf(void *buf) +{ + size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE); + unsigned int count = len >> PAGE_SHIFT; + + if (set_memory_encrypted((unsigned long)buf, count)) { + pr_err("Failed to restore encryption mask for Quote buffer, leak it\n"); + return; + } + + free_pages_exact(buf, len); +} + +static void *alloc_quote_buf(void) +{ + size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE); + unsigned int count = len >> PAGE_SHIFT; + void *addr; + + addr = alloc_pages_exact(len, GFP_KERNEL | __GFP_ZERO); + if (!addr) + return NULL; + + if (set_memory_decrypted((unsigned long)addr, count)) { + free_pages_exact(addr, len); + return NULL; + } + + return addr; +} + +/* + * wait_for_quote_completion() - Wait for Quote request completion + * @quote_buf: Address of Quote buffer. + * @timeout: Timeout in seconds to wait for the Quote generation. + * + * As per TDX GHCI v1.0 specification, sec titled "TDG.VP.VMCALL", + * the status field in the Quote buffer will be set to GET_QUOTE_IN_FLIGHT + * while VMM processes the GetQuote request, and will change it to success + * or error code after processing is complete. So wait till the status + * changes from GET_QUOTE_IN_FLIGHT or the request being timed out. + */ +static int wait_for_quote_completion(struct tdx_quote_buf *quote_buf, u32 timeout) +{ + int i = 0; + + /* + * Quote requests usually take a few seconds to complete, so waking up + * once per second to recheck the status is fine for this use case. + */ + while (quote_buf->status == GET_QUOTE_IN_FLIGHT && i++ < timeout) { + if (msleep_interruptible(MSEC_PER_SEC)) + return -EINTR; + } + + return (i == timeout) ? -ETIMEDOUT : 0; +} + +static int tdx_report_new(struct tsm_report *report, void *data) +{ + u8 *buf, *reportdata = NULL, *tdreport = NULL; + struct tdx_quote_buf *quote_buf = quote_data; + struct tsm_desc *desc = &report->desc; + int ret; + u64 err; + + /* TODO: switch to guard(mutex_intr) */ + if (mutex_lock_interruptible("e_lock)) + return -EINTR; + + /* + * If the previous request is timedout or interrupted, and the + * Quote buf status is still in GET_QUOTE_IN_FLIGHT (owned by + * VMM), don't permit any new request. + */ + if (quote_buf->status == GET_QUOTE_IN_FLIGHT) { + ret = -EBUSY; + goto done; + } + + if (desc->inblob_len != TDX_REPORTDATA_LEN) { + ret = -EINVAL; + goto done; + } + + reportdata = kmalloc(TDX_REPORTDATA_LEN, GFP_KERNEL); + if (!reportdata) { + ret = -ENOMEM; + goto done; + } + + tdreport = kzalloc(TDX_REPORT_LEN, GFP_KERNEL); + if (!tdreport) { + ret = -ENOMEM; + goto done; + } + + memcpy(reportdata, desc->inblob, desc->inblob_len); + + /* Generate TDREPORT0 using "TDG.MR.REPORT" TDCALL */ + ret = tdx_mcall_get_report0(reportdata, tdreport); + if (ret) { + pr_err("GetReport call failed\n"); + goto done; + } + + memset(quote_data, 0, GET_QUOTE_BUF_SIZE); + + /* Update Quote buffer header */ + quote_buf->version = GET_QUOTE_CMD_VER; + quote_buf->in_len = TDX_REPORT_LEN; + + memcpy(quote_buf->data, tdreport, TDX_REPORT_LEN); + + err = tdx_hcall_get_quote(quote_data, GET_QUOTE_BUF_SIZE); + if (err) { + pr_err("GetQuote hypercall failed, status:%llx\n", err); + ret = -EIO; + goto done; + } + + ret = wait_for_quote_completion(quote_buf, getquote_timeout); + if (ret) { + pr_err("GetQuote request timedout\n"); + goto done; + } + + buf = kvmemdup(quote_buf->data, quote_buf->out_len, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto done; + } + + report->outblob = buf; + report->outblob_len = quote_buf->out_len; + + /* + * TODO: parse the PEM-formatted cert chain out of the quote buffer when + * provided + */ +done: + mutex_unlock("e_lock); + kfree(reportdata); + kfree(tdreport); + + return ret; +} + static long tdx_guest_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -82,17 +278,48 @@ static const struct x86_cpu_id tdx_guest_ids[] = { }; MODULE_DEVICE_TABLE(x86cpu, tdx_guest_ids); +static const struct tsm_ops tdx_tsm_ops = { + .name = KBUILD_MODNAME, + .report_new = tdx_report_new, +}; + static int __init tdx_guest_init(void) { + int ret; + if (!x86_match_cpu(tdx_guest_ids)) return -ENODEV; - return misc_register(&tdx_misc_dev); + ret = misc_register(&tdx_misc_dev); + if (ret) + return ret; + + quote_data = alloc_quote_buf(); + if (!quote_data) { + pr_err("Failed to allocate Quote buffer\n"); + ret = -ENOMEM; + goto free_misc; + } + + ret = tsm_register(&tdx_tsm_ops, NULL, NULL); + if (ret) + goto free_quote; + + return 0; + +free_quote: + free_quote_buf(quote_data); +free_misc: + misc_deregister(&tdx_misc_dev); + + return ret; } module_init(tdx_guest_init); static void __exit tdx_guest_exit(void) { + tsm_unregister(&tdx_tsm_ops); + free_quote_buf(quote_data); misc_deregister(&tdx_misc_dev); } module_exit(tdx_guest_exit);