lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 27 Oct 2022 12:16:10 +1300
From:   Kai Huang <kai.huang@...el.com>
To:     linux-kernel@...r.kernel.org, kvm@...r.kernel.org
Cc:     linux-mm@...ck.org, seanjc@...gle.com, pbonzini@...hat.com,
        dave.hansen@...el.com, dan.j.williams@...el.com,
        rafael.j.wysocki@...el.com, kirill.shutemov@...ux.intel.com,
        reinette.chatre@...el.com, len.brown@...el.com,
        tony.luck@...el.com, peterz@...radead.org, ak@...ux.intel.com,
        isaku.yamahata@...el.com, chao.gao@...el.com,
        sathyanarayanan.kuppuswamy@...ux.intel.com, bagasdotme@...il.com,
        sagis@...gle.com, imammedo@...hat.com, kai.huang@...el.com
Subject: [PATCH v6 11/21] x86/virt/tdx: Sanity check all TDX memory ranges are convertible memory

All TDX-usable memory ranges were built during early kernel boot, and
they were not verified that they are truly convertible memory since CMRs
were not available until now.

Explicitly check all TDX memory ranges to make sure they are convertible
memory before passing those ranges to the TDX module.

Signed-off-by: Kai Huang <kai.huang@...el.com>
---

v5 -> v6:
 - Added a comment to explain two contiguous CMRs case (Isaku).
 - Rebase due to using 'tdx_memblock' to represent TDX memory, thus
   removed using memblock directly, and the handling of excluding
   first 1MB as TDX memory.

 v3 -> v4 (no feedback on v4):
 - Changed to use memblock from e820.
 - Simplified changelog a lot.

---
 arch/x86/virt/vmx/tdx/tdx.c | 61 +++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 7d7205615873..ff3ef7ed4509 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -483,6 +483,59 @@ static int tdx_get_sysinfo(void)
 	return check_cmrs(tdx_cmr_array, &tdx_cmr_num);
 }
 
+/* Check whether the first range is the subrange of the second */
+static bool is_subrange(u64 r1_start, u64 r1_end, u64 r2_start, u64 r2_end)
+{
+	return r1_start >= r2_start && r1_end <= r2_end;
+}
+
+/* Check whether the address range is covered by any CMR or not. */
+static bool range_covered_by_cmr(struct cmr_info *cmr_array, int cmr_num,
+				 u64 start, u64 end)
+{
+	int i;
+
+	for (i = 0; i < cmr_num; i++) {
+		struct cmr_info *cmr = &cmr_array[i];
+
+		if (is_subrange(start, end, cmr->base, cmr->base + cmr->size))
+			return true;
+	}
+
+	return false;
+}
+
+/*
+ * Check whether all memory regions in memblock are TDX convertible
+ * memory.  Return 0 if all memory regions are convertible, or error.
+ */
+static int sanity_check_tdx_memory(void)
+{
+	struct tdx_memblock *tmb;
+
+	list_for_each_entry(tmb, &tdx_memlist, list) {
+		u64 start = tmb->start_pfn << PAGE_SHIFT;
+		u64 end = tmb->end_pfn << PAGE_SHIFT;
+
+		/*
+		 * Note: The spec doesn't say two CMRs cannot be
+		 * contiguous.  Theoretically a memory region crossing
+		 * two contiguous CMRs (but still falls into the two
+		 * CMRs) should be treated as covered by CMR.  But this
+		 * is purely theoretically thing that doesn't occur in
+		 * practice.
+		 */
+		if (!range_covered_by_cmr(tdx_cmr_array, tdx_cmr_num, start,
+					end)) {
+			pr_err("[0x%llx, 0x%llx) is not fully convertible memory\n",
+					start, end);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 /*
  * Detect and initialize the TDX module.
  *
@@ -511,6 +564,14 @@ static int init_tdx_module(void)
 	if (ret)
 		goto out;
 
+	/*
+	 * TDX memory ranges were built during kernel boot.  Need to
+	 * make sure all those ranges are truly convertible memory
+	 * before passing them to the TDX module.
+	 */
+	ret = sanity_check_tdx_memory();
+	if (ret)
+		goto out;
 	/*
 	 * Return -EINVAL until all steps of TDX module initialization
 	 * process are done.
-- 
2.37.3

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ