* [PATCH v2 0/2] tdx-guest: Make Quote buffer size dynamic
@ 2026-07-17 21:43 Peter Fang
2026-07-17 21:43 ` [PATCH v2 1/2] x86/tdx: Add helper to query maximum TD Quote size Peter Fang
2026-07-17 21:43 ` [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically Peter Fang
0 siblings, 2 replies; 9+ messages in thread
From: Peter Fang @ 2026-07-17 21:43 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe,
Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Peter Fang
Hi,
This series changes the TDX attestation driver's Quote buffer size from
a fixed constant to a value queried from the TDX module. So effectively:
s/FIXED_BUF_SIZE/queried_buf_size/g
...in the TDX guest driver.
Terminology
===========
A "TD Quote" is an attestation structure signed with a platform key. It
contains information about a TDX guest and the platform it's running on.
The "Quote buffer" in the TDX guest driver is a memory buffer shared
between the TDX guest and the host VMM to retrieve TD Quotes. It has a
header defined in the GHCI spec [1].
Device Identifier Composition Engine ("DICE") provides a framework for
layering attestation evidence. This replaces the SGX model of contacting
an Intel server to obtain a certificate.
Problem
=======
The fixed-size Quote buffer approach is not sustainable. As
cryptographic algorithms evolve, TD Quote sizes also grow. A previous
commit [2] increased the guest driver's fixed-size Quote buffer to 128
KB to accommodate DICE Quotes, but it may still be insufficient when
those Quotes use post-quantum cryptography (PQC). PQC certificate chains
are roughly 10x-15x larger than conventional ones, which can increase
Quote sizes significantly.
What's in this series
=====================
To avoid changing the driver whenever the Quote buffer becomes too
small, newer TDX modules report their maximum Quote size via a metadata
field. The guest driver uses this value for its Quote buffer when
available. Older TDX modules continue to use the 128 KB buffer.
The changes do not affect configfs-tsm-report ABIs.
Patch 1/2: Add a helper to read the QUOTE_MAX_SIZE metadata field.
Patch 2/2: Replace the fixed Quote buffer size with the queried value,
when available.
AI use
======
I used Claude:claude-opus-4-8 to proofread this cover letter and the
changelogs. The series also underwent AI code review (Claude:claude-opus-4-7),
but the feedback was limited to style suggestions.
v1: https://lore.kernel.org/all/20260612110853.3188196-1-peter.fang@intel.com/
Changes in v2:
- Collect Reviewed-by tags. [Kiryl, Xiaoyao, Binbin, Sathya]
- Keep the explicit (u32) cast in tdx_get_max_quote_size(). [Binbin]
- Calculate the Quote buffer size with struct_size_t(). [Kiryl, Binbin]
- Add __GFP_NOWARN to the allocation since its size comes from the
host. [sashiko]
- Rename quote_data_size to quote_data_len. [Sathya]
- Drop the Assisted-by tags, as AI was not used to write the code.
[1] Guest Hypervisor Communication Interface (GHCI) Specification,
Version 1.5, Section "TDG.VP.VMCALL<GetQuote>"
[2] 43185067c6fd ("configfs-tsm-report: tdx_guest: Increase Quote buffer
size to 128KB")
Kuppuswamy Sathyanarayanan (1):
virt: tdx-guest: Allocate Quote buffer dynamically
Peter Fang (1):
x86/tdx: Add helper to query maximum TD Quote size
arch/x86/coco/tdx/tdx.c | 19 +++++++++
arch/x86/include/asm/shared/tdx.h | 1 +
arch/x86/include/asm/tdx.h | 2 +
drivers/virt/coco/tdx-guest/tdx-guest.c | 55 ++++++++++++++++++-------
4 files changed, 62 insertions(+), 15 deletions(-)
base-commit: a13c140cc289c0b7b3770bce5b3ad42ab35074aa
--
2.53.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/2] x86/tdx: Add helper to query maximum TD Quote size
2026-07-17 21:43 [PATCH v2 0/2] tdx-guest: Make Quote buffer size dynamic Peter Fang
@ 2026-07-17 21:43 ` Peter Fang
2026-07-17 21:43 ` [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically Peter Fang
1 sibling, 0 replies; 9+ messages in thread
From: Peter Fang @ 2026-07-17 21:43 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe,
Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Peter Fang
TDX attestation report ("Quote") sizes can grow with newer cryptographic
schemes, so guests can no longer rely on a fixed-size buffer for the
Quote.
Newer TDX modules report the maximum Quote size via a TD-scope metadata
field. Add a helper to query the size instead of exposing tdg_vm_rd()
directly, as it can read arbitrary metadata fields.
Thanks to Xu Yilun for suggesting this in an off-list discussion.
Reviewed-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: Peter Fang <peter.fang@intel.com>
---
v2:
- Keep the explicit (u32) cast to document the metadata field width. [Binbin]
- Note that Xu Yilun's suggestion was made in an off-list discussion. [Sathya]
- Drop the Assisted-by tags, as the code was not written by AI.
---
arch/x86/coco/tdx/tdx.c | 19 +++++++++++++++++++
arch/x86/include/asm/shared/tdx.h | 1 +
arch/x86/include/asm/tdx.h | 2 ++
3 files changed, 22 insertions(+)
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index 29b6f1ed59ec..fa2ed012e736 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -198,6 +198,25 @@ u64 tdx_hcall_get_quote(u8 *buf, size_t size)
}
EXPORT_SYMBOL_GPL(tdx_hcall_get_quote);
+/**
+ * tdx_get_max_quote_size() - Get the maximum TD Quote size
+ *
+ * Read the maximum size of a TD Quote from a 4-byte TD metadata field. The TDX
+ * guest driver uses it to size the buffer for Quote retrieval. Older TDX
+ * modules do not support this field and return an error.
+ *
+ * Return: Maximum Quote size in bytes on success, or 0 on failure.
+ */
+u32 tdx_get_max_quote_size(void)
+{
+ u64 val, ret;
+
+ ret = tdg_vm_rd(TDCS_QUOTE_MAX_SIZE, &val);
+
+ return ret ? 0 : (u32)val;
+}
+EXPORT_SYMBOL_GPL(tdx_get_max_quote_size);
+
static void __noreturn tdx_panic(const char *msg)
{
struct tdx_module_args args = {
diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
index f20e91d7ac35..a58751321613 100644
--- a/arch/x86/include/asm/shared/tdx.h
+++ b/arch/x86/include/asm/shared/tdx.h
@@ -50,6 +50,7 @@
/* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */
#define TDCS_CONFIG_FLAGS 0x1110000300000016
#define TDCS_TD_CTLS 0x1110000300000017
+#define TDCS_QUOTE_MAX_SIZE 0x9010000200000008
#define TDCS_NOTIFY_ENABLES 0x9100000000000010
#define TDCS_TOPOLOGY_ENUM_CONFIGURED 0x9100000000000019
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 89e97d5761d8..a75dbbe004bd 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -83,6 +83,8 @@ int tdx_mcall_extend_rtmr(u8 index, u8 *data);
u64 tdx_hcall_get_quote(u8 *buf, size_t size);
+u32 tdx_get_max_quote_size(void);
+
void __init tdx_dump_attributes(u64 td_attr);
void __init tdx_dump_td_ctls(u64 td_ctls);
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically
2026-07-17 21:43 [PATCH v2 0/2] tdx-guest: Make Quote buffer size dynamic Peter Fang
2026-07-17 21:43 ` [PATCH v2 1/2] x86/tdx: Add helper to query maximum TD Quote size Peter Fang
@ 2026-07-17 21:43 ` Peter Fang
2026-07-20 13:35 ` Dave Hansen
1 sibling, 1 reply; 9+ messages in thread
From: Peter Fang @ 2026-07-17 21:43 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe,
Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu, Peter Fang
From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
The TDX attestation driver currently uses a fixed 128 KB Quote buffer
shared with the host VMM. This may be too small for Quotes using schemes
such as post-quantum cryptography (PQC), where larger certificate chains
can increase the Quote size significantly.
Allocate the Quote buffer based on the size reported by the TDX module
instead of always reserving a fixed-size buffer. This avoids wasting
memory on platforms that do not require larger Quotes. Older platforms
fall back to the default 128 KB buffer.
Because the Quote buffer must be physically contiguous, its size is
bound by the buddy allocator's maximum page order (4 MB), which should
be sufficient for current attestation needs.
struct tdx_quote_buf has a trailing flexible array, so use struct_size_t()
to calculate the buffer size.
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Reviewed-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Signed-off-by: Peter Fang <peter.fang@intel.com>
---
v2:
- Use struct_size_t() instead of offsetof() to compute the buffer size. [Kiryl, Binbin]
- Pass __GFP_NOWARN to alloc_pages_exact() so an oversized size fails quietly. [sashiko]
- Reword the description to avoid implying Quotes can exceed the 4 MB limit. [Binbin]
- Rename quote_data_size to quote_data_len. [Sathya]
- Drop the Assisted-by tags, as the code was not written by AI.
---
drivers/virt/coco/tdx-guest/tdx-guest.c | 55 ++++++++++++++++++-------
1 file changed, 40 insertions(+), 15 deletions(-)
diff --git a/drivers/virt/coco/tdx-guest/tdx-guest.c b/drivers/virt/coco/tdx-guest/tdx-guest.c
index d0303e31e816..ce2c2ef74676 100644
--- a/drivers/virt/coco/tdx-guest/tdx-guest.c
+++ b/drivers/virt/coco/tdx-guest/tdx-guest.c
@@ -162,7 +162,7 @@ static void tdx_mr_deinit(const struct attribute_group *mr_grp)
* DICE-based attestation uses layered evidence that requires
* larger Quote size (~100K).
*/
-#define GET_QUOTE_BUF_SIZE SZ_128K
+#define GET_QUOTE_DEFAULT_BUF_SIZE SZ_128K
#define GET_QUOTE_CMD_VER 1
@@ -170,7 +170,7 @@ static void tdx_mr_deinit(const struct attribute_group *mr_grp)
#define GET_QUOTE_SUCCESS 0
#define GET_QUOTE_IN_FLIGHT 0xffffffffffffffff
-#define TDX_QUOTE_MAX_LEN (GET_QUOTE_BUF_SIZE - sizeof(struct tdx_quote_buf))
+#define TDX_QUOTE_BUF_LEN(n) struct_size_t(struct tdx_quote_buf, data, n)
/* struct tdx_quote_buf: Format of Quote request buffer.
* @version: Quote format version, filled by TD.
@@ -191,8 +191,9 @@ struct tdx_quote_buf {
u8 data[];
};
-/* Quote data buffer */
+/* Quote data buffer and length */
static void *quote_data;
+static size_t quote_data_len;
/* Lock to streamline quote requests */
static DEFINE_MUTEX(quote_lock);
@@ -209,9 +210,8 @@ static long tdx_get_report0(struct tdx_report_req __user *req)
USER_SOCKPTR(req->tdreport));
}
-static void free_quote_buf(void *buf)
+static void free_quote_buf(void *buf, size_t len)
{
- size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE);
unsigned int count = len >> PAGE_SHIFT;
if (set_memory_encrypted((unsigned long)buf, count)) {
@@ -222,19 +222,44 @@ static void free_quote_buf(void *buf)
free_pages_exact(buf, len);
}
-static void *alloc_quote_buf(void)
+static size_t get_quote_buf_size(void)
{
- size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE);
- unsigned int count = len >> PAGE_SHIFT;
+ size_t buf_size = GET_QUOTE_DEFAULT_BUF_SIZE;
+ u32 quote_size;
+
+ quote_size = tdx_get_max_quote_size();
+
+ if (quote_size)
+ /* Reported size does not include GetQuote header */
+ buf_size = TDX_QUOTE_BUF_LEN(quote_size);
+
+ return PAGE_ALIGN(buf_size);
+}
+
+static void *alloc_quote_buf(size_t *buflen)
+{
+ unsigned int count;
+ size_t len;
void *addr;
- addr = alloc_pages_exact(len, GFP_KERNEL | __GFP_ZERO);
+ len = get_quote_buf_size();
+
+ /*
+ * This fails if the requested size exceeds the buddy allocator's
+ * maximum order. Use __GFP_NOWARN since the size comes from the host
+ * and should fail quietly rather than warn.
+ */
+ addr = alloc_pages_exact(len, GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
if (!addr)
return NULL;
+ count = len >> PAGE_SHIFT;
+
if (set_memory_decrypted((unsigned long)addr, count))
return NULL;
+ *buflen = len;
+
return addr;
}
@@ -285,7 +310,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
if (desc->inblob_len != TDX_REPORTDATA_LEN)
return -EINVAL;
- memset(quote_data, 0, GET_QUOTE_BUF_SIZE);
+ memset(quote_data, 0, quote_data_len);
/* Update Quote buffer header */
quote_buf->version = GET_QUOTE_CMD_VER;
@@ -296,7 +321,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
if (ret)
return ret;
- err = tdx_hcall_get_quote(quote_data, GET_QUOTE_BUF_SIZE);
+ err = tdx_hcall_get_quote(quote_data, quote_data_len);
if (err) {
pr_err("GetQuote hypercall failed, status:%llx\n", err);
return -EIO;
@@ -315,7 +340,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
out_len = READ_ONCE(quote_buf->out_len);
- if (out_len > TDX_QUOTE_MAX_LEN)
+ if (TDX_QUOTE_BUF_LEN(out_len) > quote_data_len)
return -EFBIG;
buf = kvmemdup(quote_buf->data, out_len, GFP_KERNEL);
@@ -417,7 +442,7 @@ static int __init tdx_guest_init(void)
if (ret)
goto deinit_mr;
- quote_data = alloc_quote_buf();
+ quote_data = alloc_quote_buf("e_data_len);
if (!quote_data) {
pr_err("Failed to allocate Quote buffer\n");
ret = -ENOMEM;
@@ -431,7 +456,7 @@ static int __init tdx_guest_init(void)
return 0;
free_quote:
- free_quote_buf(quote_data);
+ free_quote_buf(quote_data, quote_data_len);
free_misc:
misc_deregister(&tdx_misc_dev);
deinit_mr:
@@ -444,7 +469,7 @@ module_init(tdx_guest_init);
static void __exit tdx_guest_exit(void)
{
tsm_report_unregister(&tdx_tsm_ops);
- free_quote_buf(quote_data);
+ free_quote_buf(quote_data, quote_data_len);
misc_deregister(&tdx_misc_dev);
tdx_mr_deinit(tdx_attr_groups[0]);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically
2026-07-17 21:43 ` [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically Peter Fang
@ 2026-07-20 13:35 ` Dave Hansen
2026-07-21 6:49 ` Peter Fang
0 siblings, 1 reply; 9+ messages in thread
From: Dave Hansen @ 2026-07-20 13:35 UTC (permalink / raw)
To: Peter Fang, Dave Hansen, Kiryl Shutsemau, Rick Edgecombe,
Kuppuswamy Sathyanarayanan
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, linux-kernel, linux-coco, kvm, Xiaoyao Li,
Binbin Wu
On 7/17/26 14:43, Peter Fang wrote:
> From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
>
> The TDX attestation driver currently uses a fixed 128 KB Quote buffer
> shared with the host VMM. This may be too small for Quotes using schemes
> such as post-quantum cryptography (PQC), where larger certificate chains
> can increase the Quote size significantly.
>
> Allocate the Quote buffer based on the size reported by the TDX module
> instead of always reserving a fixed-size buffer. This avoids wasting
> memory on platforms that do not require larger Quotes. Older platforms
> fall back to the default 128 KB buffer.
>
> Because the Quote buffer must be physically contiguous, its size is
> bound by the buddy allocator's maximum page order (4 MB), which should
> be sufficient for current attestation needs.
This is all talking about post-quantum-crypto and all that fancy stuff.
Isn't the important part here that the old TDX module ABI had static
quote sizes and now they're dynamic? Now, the reason it changed is all
the fancy stuff.
But the ABI changed. Right?
> -static void *alloc_quote_buf(void)
> +static size_t get_quote_buf_size(void)
> {
> - size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE);
> - unsigned int count = len >> PAGE_SHIFT;
> + size_t buf_size = GET_QUOTE_DEFAULT_BUF_SIZE;
> + u32 quote_size;
> +
> + quote_size = tdx_get_max_quote_size();
> +
> + if (quote_size)
> + /* Reported size does not include GetQuote header */
> + buf_size = TDX_QUOTE_BUF_LEN(quote_size);
> +
> + return PAGE_ALIGN(buf_size);
> +}
This code is almost nonsensical on the surface.
It _really_ needs some commenting. Things like:
/* Start with the default quote buffer size: */
...
/* Override the default when ... */
You could even comment the function to say what it is trying to do overall.
> +static void *alloc_quote_buf(size_t *buflen)
> +{
> + unsigned int count;
> + size_t len;
> void *addr;
>
> - addr = alloc_pages_exact(len, GFP_KERNEL | __GFP_ZERO);
> + len = get_quote_buf_size();
> +
> + /*
> + * This fails if the requested size exceeds the buddy allocator's
> + * maximum order. Use __GFP_NOWARN since the size comes from the host
> + * and should fail quietly rather than warn.
> + */
> + addr = alloc_pages_exact(len, GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
Bad Sashiko. Bad.
The host may be untrusted, but it's also a critical part of the system.
Are we sure we want to be completely quiet?
I used to see little dmesg warnings about TCP window shenanigans from
random systems on the Internet. Maybe that's not how we do things today,
but if a random dude on the Internet can spew one line to dmesg, is it
that crazy that a bad VMM be able to spew a warning?
> if (!addr)
> return NULL;
>
> + count = len >> PAGE_SHIFT;
> +
> if (set_memory_decrypted((unsigned long)addr, count))
> return NULL;
>
> + *buflen = len;
> +
> return addr;
> }
This feels weird to me.
If the upper-layer function needs to know the size, why not have it just
call get_quote_buf_size()? Then there's no pass-by-address.
> @@ -285,7 +310,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
> if (desc->inblob_len != TDX_REPORTDATA_LEN)
> return -EINVAL;
>
> - memset(quote_data, 0, GET_QUOTE_BUF_SIZE);
> + memset(quote_data, 0, quote_data_len);
>
> /* Update Quote buffer header */
> quote_buf->version = GET_QUOTE_CMD_VER;
> @@ -296,7 +321,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
> if (ret)
> return ret;
>
> - err = tdx_hcall_get_quote(quote_data, GET_QUOTE_BUF_SIZE);
> + err = tdx_hcall_get_quote(quote_data, quote_data_len);
> if (err) {
> pr_err("GetQuote hypercall failed, status:%llx\n", err);
> return -EIO;
> @@ -315,7 +340,7 @@ static int tdx_report_new_locked(struct tsm_report *report, void *data)
>
> out_len = READ_ONCE(quote_buf->out_len);
>
> - if (out_len > TDX_QUOTE_MAX_LEN)
> + if (TDX_QUOTE_BUF_LEN(out_len) > quote_data_len)
> return -EFBIG;
>
> buf = kvmemdup(quote_buf->data, out_len, GFP_KERNEL);
> @@ -417,7 +442,7 @@ static int __init tdx_guest_init(void)
> if (ret)
> goto deinit_mr;
>
> - quote_data = alloc_quote_buf();
> + quote_data = alloc_quote_buf("e_data_len);
> if (!quote_data) {
> pr_err("Failed to allocate Quote buffer\n");
> ret = -ENOMEM;
> @@ -431,7 +456,7 @@ static int __init tdx_guest_init(void)
> return 0;
>
> free_quote:
> - free_quote_buf(quote_data);
> + free_quote_buf(quote_data, quote_data_len);
> free_misc:
> misc_deregister(&tdx_misc_dev);
> deinit_mr:
> @@ -444,7 +469,7 @@ module_init(tdx_guest_init);
> static void __exit tdx_guest_exit(void)
> {
> tsm_report_unregister(&tdx_tsm_ops);
> - free_quote_buf(quote_data);
> + free_quote_buf(quote_data, quote_data_len);
> misc_deregister(&tdx_misc_dev);
> tdx_mr_deinit(tdx_attr_groups[0]);
> }
So, yeah, this patch isn't gigantic. But it's also fundamentally not
doing a _nice_ refactoring the way we expect them to be done.
1. Refactor old code to make it nice for adding features
2. Add the feature
If this was doing it the nice way, we would *actually* have something
that's really close to s/GET_QUOTE_BUF_SIZE/quote_data_len/. But,
instead, this chose to cram the mechanical changes and the new feature
together.
Can we do it the right way, please? If for nothing else, for practice.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically
2026-07-20 13:35 ` Dave Hansen
@ 2026-07-21 6:49 ` Peter Fang
2026-07-21 13:48 ` Dave Hansen
0 siblings, 1 reply; 9+ messages in thread
From: Peter Fang @ 2026-07-21 6:49 UTC (permalink / raw)
To: Dave Hansen
Cc: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe,
Kuppuswamy Sathyanarayanan, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, x86, H. Peter Anvin, linux-kernel, linux-coco,
kvm, Xiaoyao Li, Binbin Wu
On Mon, Jul 20, 2026 at 06:35:29AM -0700, Dave Hansen wrote:
> On 7/17/26 14:43, Peter Fang wrote:
> > From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> >
> > The TDX attestation driver currently uses a fixed 128 KB Quote buffer
> > shared with the host VMM. This may be too small for Quotes using schemes
> > such as post-quantum cryptography (PQC), where larger certificate chains
> > can increase the Quote size significantly.
> >
> > Allocate the Quote buffer based on the size reported by the TDX module
> > instead of always reserving a fixed-size buffer. This avoids wasting
> > memory on platforms that do not require larger Quotes. Older platforms
> > fall back to the default 128 KB buffer.
> >
> > Because the Quote buffer must be physically contiguous, its size is
> > bound by the buddy allocator's maximum page order (4 MB), which should
> > be sufficient for current attestation needs.
>
> This is all talking about post-quantum-crypto and all that fancy stuff.
>
> Isn't the important part here that the old TDX module ABI had static
> quote sizes and now they're dynamic? Now, the reason it changed is all
> the fancy stuff.
>
> But the ABI changed. Right?
Ah yes... I should call out that the size of
/sys/kernel/config/tsm/report/$name/outblob will no longer be fixed.
I'll update this. Thanks.
>
> > -static void *alloc_quote_buf(void)
> > +static size_t get_quote_buf_size(void)
> > {
> > - size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE);
> > - unsigned int count = len >> PAGE_SHIFT;
> > + size_t buf_size = GET_QUOTE_DEFAULT_BUF_SIZE;
> > + u32 quote_size;
> > +
> > + quote_size = tdx_get_max_quote_size();
> > +
> > + if (quote_size)
> > + /* Reported size does not include GetQuote header */
> > + buf_size = TDX_QUOTE_BUF_LEN(quote_size);
> > +
> > + return PAGE_ALIGN(buf_size);
> > +}
>
> This code is almost nonsensical on the surface.
>
> It _really_ needs some commenting. Things like:
>
> /* Start with the default quote buffer size: */
>
> ...
>
> /* Override the default when ... */
>
>
> You could even comment the function to say what it is trying to do overall.
Got it. I'll improve this pattern and add more comments.
>
> > +static void *alloc_quote_buf(size_t *buflen)
> > +{
> > + unsigned int count;
> > + size_t len;
> > void *addr;
> >
> > - addr = alloc_pages_exact(len, GFP_KERNEL | __GFP_ZERO);
> > + len = get_quote_buf_size();
> > +
> > + /*
> > + * This fails if the requested size exceeds the buddy allocator's
> > + * maximum order. Use __GFP_NOWARN since the size comes from the host
> > + * and should fail quietly rather than warn.
> > + */
> > + addr = alloc_pages_exact(len, GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
>
> Bad Sashiko. Bad.
>
> The host may be untrusted, but it's also a critical part of the system.
> Are we sure we want to be completely quiet?
>
> I used to see little dmesg warnings about TCP window shenanigans from
> random systems on the Internet. Maybe that's not how we do things today,
> but if a random dude on the Internet can spew one line to dmesg, is it
> that crazy that a bad VMM be able to spew a warning?
That makes sense... I actually argued with AI about this but it kept
saying this is kind of like DoSing the guest. But thinking about it
more, tainting the guest is probably the right thing to do... At least
the guest sees a big splat about why attestation is failing. I'll remove
the __GFP_NOWARN. Thanks.
>
> > if (!addr)
> > return NULL;
> >
> > + count = len >> PAGE_SHIFT;
> > +
> > if (set_memory_decrypted((unsigned long)addr, count))
> > return NULL;
> >
> > + *buflen = len;
> > +
> > return addr;
> > }
>
> This feels weird to me.
>
> If the upper-layer function needs to know the size, why not have it just
> call get_quote_buf_size()? Then there's no pass-by-address.
Got it. I'll fix this.
>
[ ... ]
>
> So, yeah, this patch isn't gigantic. But it's also fundamentally not
> doing a _nice_ refactoring the way we expect them to be done.
>
> 1. Refactor old code to make it nice for adding features
> 2. Add the feature
>
> If this was doing it the nice way, we would *actually* have something
> that's really close to s/GET_QUOTE_BUF_SIZE/quote_data_len/. But,
> instead, this chose to cram the mechanical changes and the new feature
> together.
>
> Can we do it the right way, please? If for nothing else, for practice.
Yes I'll separate out the refactoring so that the dynamic buffer thing
is on its own. Thanks for the feedback.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically
2026-07-21 6:49 ` Peter Fang
@ 2026-07-21 13:48 ` Dave Hansen
2026-07-21 16:43 ` Edgecombe, Rick P
2026-07-22 6:39 ` Peter Fang
0 siblings, 2 replies; 9+ messages in thread
From: Dave Hansen @ 2026-07-21 13:48 UTC (permalink / raw)
To: Peter Fang
Cc: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe,
Kuppuswamy Sathyanarayanan, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, x86, H. Peter Anvin, linux-kernel, linux-coco,
kvm, Xiaoyao Li, Binbin Wu
On 7/20/26 23:49, Peter Fang wrote:
...
>> This is all talking about post-quantum-crypto and all that fancy stuff.
>>
>> Isn't the important part here that the old TDX module ABI had static
>> quote sizes and now they're dynamic? Now, the reason it changed is all
>> the fancy stuff.
>>
>> But the ABI changed. Right?
>
> Ah yes... I should call out that the size of
> /sys/kernel/config/tsm/report/$name/outblob will no longer be fixed.
> I'll update this. Thanks.
No. I mean the TDX Module ABI changed.
That's why we need new kernel patches.
>> The host may be untrusted, but it's also a critical part of the system.
>> Are we sure we want to be completely quiet?
>>
>> I used to see little dmesg warnings about TCP window shenanigans from
>> random systems on the Internet. Maybe that's not how we do things today,
>> but if a random dude on the Internet can spew one line to dmesg, is it
>> that crazy that a bad VMM be able to spew a warning?
>
> That makes sense... I actually argued with AI about this but it kept
> saying this is kind of like DoSing the guest. But thinking about it
> more, tainting the guest is probably the right thing to do... At least
> the guest sees a big splat about why attestation is failing. I'll remove
> the __GFP_NOWARN. Thanks.
This does seem like the kind of high-level TDX policy that we all need
to be aligned on and probably document somewhere. The basic question is
whether a TDX guest should be quiet or verbose in the face of host
malfunction or malfeasance.
Kirill and Rick, what do you think?
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically
2026-07-21 13:48 ` Dave Hansen
@ 2026-07-21 16:43 ` Edgecombe, Rick P
2026-07-22 7:36 ` Peter Fang
2026-07-22 6:39 ` Peter Fang
1 sibling, 1 reply; 9+ messages in thread
From: Edgecombe, Rick P @ 2026-07-21 16:43 UTC (permalink / raw)
To: Hansen, Dave, Fang, Peter
Cc: kvm@vger.kernel.org, bp@alien8.de, kas@kernel.org, Li, Xiaoyao,
x86@kernel.org, sathyanarayanan.kuppuswamy@linux.intel.com,
mingo@redhat.com, dave.hansen@linux.intel.com, tglx@kernel.org,
linux-coco@lists.linux.dev, hpa@zytor.com,
linux-kernel@vger.kernel.org, binbin.wu@linux.intel.com
On Tue, 2026-07-21 at 06:48 -0700, Dave Hansen wrote:
> > > The host may be untrusted, but it's also a critical part of the system.
> > > Are we sure we want to be completely quiet?
> > >
> > > I used to see little dmesg warnings about TCP window shenanigans from
> > > random systems on the Internet. Maybe that's not how we do things today,
> > > but if a random dude on the Internet can spew one line to dmesg, is it
> > > that crazy that a bad VMM be able to spew a warning?
> >
> > That makes sense... I actually argued with AI about this but it kept
> > saying this is kind of like DoSing the guest.
A guest DOSing another guest is relevant, but the host DOSing the guest is not a
threat model we should or even can care about. If userspace or the kernel
decides to kill the guest, that is its prerogative. At most it's a functional
bug and not a security one.
But... doesn't this size come from the TDX module? In which case there is no
hope of defense from anything.
> > But thinking about it
> > more, tainting the guest is probably the right thing to do... At least
> > the guest sees a big splat about why attestation is failing. I'll remove
> > the __GFP_NOWARN. Thanks.
>
> This does seem like the kind of high-level TDX policy that we all need
> to be aligned on and probably document somewhere. The basic question is
> whether a TDX guest should be quiet or verbose in the face of host
> malfunction or malfeasance.
>
> Kirill and Rick, what do you think?
We discussed something similar around the set_memory_en/decrypted() failures.
But that was around whether to panic or just warn. Not be silent. If the host is
mucking around, I think security conscious guests would want to know, and even
have the option to pass panic_on_warn. So yea I think we should assume the
default TDX user is security conscious. "Warn on untrusted host weird behavior"
seems like a good policy.
BUT, is this number coming from the untrusted host or the TDX module? I cant
find TDCS_QUOTE_MAX_SIZE in the docs. If it is coming from the TDX module then
we are not talking about security considerations at all. It's just a functional
"do you want to know if things are failing". Not sure why this one would be
special in that regard. If we think it will fail so often that we don't want a
warning, then we probably need another solution.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically
2026-07-21 13:48 ` Dave Hansen
2026-07-21 16:43 ` Edgecombe, Rick P
@ 2026-07-22 6:39 ` Peter Fang
1 sibling, 0 replies; 9+ messages in thread
From: Peter Fang @ 2026-07-22 6:39 UTC (permalink / raw)
To: Dave Hansen
Cc: Dave Hansen, Kiryl Shutsemau, Rick Edgecombe,
Kuppuswamy Sathyanarayanan, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, x86, H. Peter Anvin, linux-kernel, linux-coco,
kvm, Xiaoyao Li, Binbin Wu
On Tue, Jul 21, 2026 at 06:48:24AM -0700, Dave Hansen wrote:
> On 7/20/26 23:49, Peter Fang wrote:
> ...
> >> This is all talking about post-quantum-crypto and all that fancy stuff.
> >>
> >> Isn't the important part here that the old TDX module ABI had static
> >> quote sizes and now they're dynamic? Now, the reason it changed is all
> >> the fancy stuff.
> >>
> >> But the ABI changed. Right?
> >
> > Ah yes... I should call out that the size of
> > /sys/kernel/config/tsm/report/$name/outblob will no longer be fixed.
> > I'll update this. Thanks.
>
> No. I mean the TDX Module ABI changed.
>
> That's why we need new kernel patches.
Ah sorry I misunderstood. I'll make that clear in the changelog. Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically
2026-07-21 16:43 ` Edgecombe, Rick P
@ 2026-07-22 7:36 ` Peter Fang
0 siblings, 0 replies; 9+ messages in thread
From: Peter Fang @ 2026-07-22 7:36 UTC (permalink / raw)
To: Edgecombe, Rick P
Cc: Hansen, Dave, kvm@vger.kernel.org, bp@alien8.de, kas@kernel.org,
Li, Xiaoyao, x86@kernel.org,
sathyanarayanan.kuppuswamy@linux.intel.com, mingo@redhat.com,
dave.hansen@linux.intel.com, tglx@kernel.org,
linux-coco@lists.linux.dev, hpa@zytor.com,
linux-kernel@vger.kernel.org, binbin.wu@linux.intel.com
On Tue, Jul 21, 2026 at 09:43:57AM -0700, Edgecombe, Rick P wrote:
> On Tue, 2026-07-21 at 06:48 -0700, Dave Hansen wrote:
> > > > The host may be untrusted, but it's also a critical part of the system.
> > > > Are we sure we want to be completely quiet?
> > > >
> > > > I used to see little dmesg warnings about TCP window shenanigans from
> > > > random systems on the Internet. Maybe that's not how we do things today,
> > > > but if a random dude on the Internet can spew one line to dmesg, is it
> > > > that crazy that a bad VMM be able to spew a warning?
> > >
> > > That makes sense... I actually argued with AI about this but it kept
> > > saying this is kind of like DoSing the guest.
>
> A guest DOSing another guest is relevant, but the host DOSing the guest is not a
> threat model we should or even can care about. If userspace or the kernel
> decides to kill the guest, that is its prerogative. At most it's a functional
> bug and not a security one.
Hmm good point. So maybe treat this more like a bug than an attack. Then
the direction is clearer.
I went back to my debate with AI and found what spooked me:
"Letting untrusted input reach a WARN is a well-known
anti-pattern precisely because of panic_on_warn — it's why
syzkaller treats any WARN as a bug."
-> but this is more of a bug than an untrusted input
"'Fail hard to defend against the attacking host' buys you zero
additional protection, while adding log-spam and a
benign-misconfig panic vector."
-> but there is also no point in limping along
>
> But... doesn't this size come from the TDX module? In which case there is no
> hope of defense from anything.
Yes it's directly from the TDX module. So maybe it's more of a question
of how loud this failure should be. There is already a:
pr_err("Failed to allocate Quote buffer\n");
... later if buffer allocation fails, so the user will see something in
dmesg. But maybe it's too subtle...
>
> > > But thinking about it
> > > more, tainting the guest is probably the right thing to do... At least
> > > the guest sees a big splat about why attestation is failing. I'll remove
> > > the __GFP_NOWARN. Thanks.
> >
> > This does seem like the kind of high-level TDX policy that we all need
> > to be aligned on and probably document somewhere. The basic question is
> > whether a TDX guest should be quiet or verbose in the face of host
> > malfunction or malfeasance.
> >
> > Kirill and Rick, what do you think?
>
> We discussed something similar around the set_memory_en/decrypted() failures.
> But that was around whether to panic or just warn. Not be silent. If the host is
> mucking around, I think security conscious guests would want to know, and even
> have the option to pass panic_on_warn. So yea I think we should assume the
> default TDX user is security conscious. "Warn on untrusted host weird behavior"
> seems like a good policy.
Sounds good to me. Thanks for providing more background.
>
> BUT, is this number coming from the untrusted host or the TDX module? I cant
> find TDCS_QUOTE_MAX_SIZE in the docs. If it is coming from the TDX module then
> we are not talking about security considerations at all. It's just a functional
> "do you want to know if things are failing". Not sure why this one would be
> special in that regard. If we think it will fail so often that we don't want a
> warning, then we probably need another solution.
Another consideration I had at the time was that this happens before
attestation. And not being able to do attestation felt like a big enough
red flag (I'm assuming something in the guest would scream). So that led
me to think that perhaps a warn would be too noisy. But I'm good with
following the TDX policy and just warn.
I think this tilts the scale towards keeping the warn. Let me know if
anyone thinks otherwise. Thanks for the discussion!
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-07-22 7:36 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-17 21:43 [PATCH v2 0/2] tdx-guest: Make Quote buffer size dynamic Peter Fang
2026-07-17 21:43 ` [PATCH v2 1/2] x86/tdx: Add helper to query maximum TD Quote size Peter Fang
2026-07-17 21:43 ` [PATCH v2 2/2] virt: tdx-guest: Allocate Quote buffer dynamically Peter Fang
2026-07-20 13:35 ` Dave Hansen
2026-07-21 6:49 ` Peter Fang
2026-07-21 13:48 ` Dave Hansen
2026-07-21 16:43 ` Edgecombe, Rick P
2026-07-22 7:36 ` Peter Fang
2026-07-22 6:39 ` Peter Fang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox