Linux Confidential Computing Development
 help / color / mirror / Atom feed
From: Dave Hansen <dave.hansen@intel.com>
To: Chao Gao <chao.gao@intel.com>,
	kvm@vger.kernel.org, linux-coco@lists.linux.dev,
	linux-kernel@vger.kernel.org
Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com,
	djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com,
	kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org,
	pbonzini@redhat.com, reinette.chatre@intel.com,
	rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com,
	tony.lindgren@linux.intel.com, vannapurve@google.com,
	vishal.l.verma@intel.com, yilun.xu@linux.intel.com,
	xiaoyao.li@intel.com, yan.y.zhao@intel.com,
	Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
	Borislav Petkov <bp@alien8.de>,
	x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>
Subject: Re: [PATCH v9 11/23] x86/virt/seamldr: Allocate and populate a module update request
Date: Fri, 15 May 2026 11:24:28 -0700	[thread overview]
Message-ID: <7d7fff5a-53a5-439e-9ff8-dcbd97f473cd@intel.com> (raw)
In-Reply-To: <20260513151045.1420990-12-chao.gao@intel.com>

On 5/13/26 08:09, Chao Gao wrote:
> There are two important ABIs here:
> 
> 'struct tdx_image'	- The on-disk and in-memory format for a TDX
> 			  module update image.
> 'struct seamldr_params'	- The in-memory ABI passed to the TDX module
> 			  loader. Points to a single 'struct tdx_image'

	... broken up into 4k pages

> Userspace supplies the update image in struct tdx_image format. The image
> consists of a header followed by a sigstruct and the module binary.
> 
> P-SEAMLDR, however, consumes struct seamldr_params rather than the image
> directly. Parse the struct tdx_image provided by userspace and populate a
> matching struct seamldr_params.

This is doing it again. It's taking the key imperative and burying it.
It should be:

=>
Userspace supplies the update image in struct tdx_image format. The
image consists of a header followed by a sigstruct and the module
binary. P-SEAMLDR, however, consumes struct seamldr_params rather than
the image directly.

Parse the struct tdx_image provided by userspace and populate a matching
struct seamldr_params.
<=

> Validate the struct tdx_image header before using it, because the header is
> consumed solely by the kernel to locate the sigstruct and module within
> the image. Do not validate the payload itself. The sigstruct and module
> pages are passed through to P-SEAMLDR, which validates them as part of the
> update flow.
> 
> Signed-off-by: Chao Gao <chao.gao@intel.com>
> ---
> sigstruct_pages_pa_list currently has only one entry, but it will grow to
> four pages in the future. Keep it as an array for symmetry with
> module_pages_pa_list and for extensibility.

That's a good note. It can go above the ---.

> + * The seamldr_params "scenario" field specifies the operation mode:
> + * 0: Install TDX module from scratch (not used by kernel)
> + * 1: Update existing TDX module to a compatible version
> + */
> +#define SEAMLDR_SCENARIO_UPDATE		1
> +
> +/*
> + * This is called the "SEAMLDR_PARAMS" data structure and is defined
> + * in "SEAM Loader (SEAMLDR) Interface Specification".
> + *
> + * It describes the TDX module that will be installed.

Yeah, but that's not super useful.

	This is the in-memory ABI that the kernel passes to the P-
	SEAMLDR to update the TDX module. It breaks the TDX module image
	up in page-size pieces.

Better?

> + */
> +struct seamldr_params {
> +	u32	version;
> +	u32	scenario;
> +	u64	sigstruct_pages_pa_list[SEAMLDR_MAX_NR_SIG_PAGES];
> +	u8	reserved[104];
> +	u64	module_nr_pages;
> +	u64	module_pages_pa_list[SEAMLDR_MAX_NR_MODULE_PAGES];
> +} __packed;
> +
> +static_assert(sizeof(struct seamldr_params) == 4096);
> +
>  /*
>   * Serialize P-SEAMLDR calls since the hardware only allows a single CPU to
>   * interact with P-SEAMLDR simultaneously. Use raw version as the calls can
> @@ -43,6 +71,89 @@ int seamldr_get_info(struct seamldr_info *seamldr_info)
>  }
>  EXPORT_SYMBOL_FOR_MODULES(seamldr_get_info, "tdx-host");
>  
> +#define TDX_IMAGE_VERSION_2		0x200
> +
> +struct tdx_image_header {
> +	u16	version; // This ABI is always 0x200

That comment reads strangely in here. Did I ask you to write that?

> +	u16	checksum;
> +	u8	signature[8];
> +	u32	sigstruct_nr_pages;
> +	u32	module_nr_pages;
> +	u8	reserved[4076];
> +} __packed;
> +
> +#define HEADER_SIZE sizeof(struct tdx_image_header)
> +static_assert(HEADER_SIZE == 4096);
> +
> +/* Intel TDX module update ABI structure. aka. "TDX module blob". */
> +struct tdx_image {
> +	struct tdx_image_header header;
> +	u8 payload[]; // Contains sigstruct pages followed by module pages
> +};
> +
> +static void populate_pa_list(u64 *pa_list, u32 max_entries, const u8 *start, u32 nr_pages)

The naming in there is painful. How about:

populate_pa_list(u64 *pa_list, u32 pa_list_len,
		 const u8 *vmalloc_addr, u32 vmalloc_len_pages)

> +{
> +	int i;
> +
> +	nr_pages = MIN(nr_pages, max_entries);

This seems wonky. Should it really be silently suppressing things if
either the allocation or source is too small? I get not wanting to
overflow, but this seems strange.

> +	for (i = 0; i < nr_pages; i++) {
> +		pa_list[i] = vmalloc_to_pfn(start) << PAGE_SHIFT;
> +		start += PAGE_SIZE;
> +	}

At the point that you modify 'start', it's not 'start' any more. Use
another variable. This would do, for instance:

	for (i = 0; i < nr_pages; i++) {
		unsigned long offset = i * PAGE_SIZE;

		pa_list[i] = vmalloc_to_pfn(&start[offset]);
	}


> +static void populate_seamldr_params(struct seamldr_params *params,
> +				    const u8 *sig, u32 sig_nr_pages,
> +				    const u8 *mod, u32 mod_nr_pages)
> +{
> +	params->version			= 0;
> +	params->scenario		= SEAMLDR_SCENARIO_UPDATE;
> +	params->module_nr_pages		= mod_nr_pages;
> +
> +	populate_pa_list(params->sigstruct_pages_pa_list, SEAMLDR_MAX_NR_SIG_PAGES,
> +			 sig, sig_nr_pages);
> +	populate_pa_list(params->module_pages_pa_list, SEAMLDR_MAX_NR_MODULE_PAGES,
> +			 mod, mod_nr_pages);
> +}

Yes, this is starting to look OK. Nit: vertically align the "*_PAGES" args:


	populate_pa_list(params->sigstruct_pages_pa_list, SEAMLDR_...,
			 sig, sig_nr_pages);
	populate_pa_list(params->module_pages_pa_list,    SEAMLDR_...,
			 mod, mod_nr_pages);


> +static int init_seamldr_params(struct seamldr_params *params, const u8 *data, u32 size)
> +{
> +	const struct tdx_image *image		= (const void *)data;
> +	const struct tdx_image_header *header	= &image->header;
> +
> +	u32 sigstruct_len	= header->sigstruct_nr_pages * PAGE_SIZE;
> +	u32 module_len		= header->module_nr_pages * PAGE_SIZE;
> +
> +	u8 *header_start	= (u8 *)header;
> +	u8 *header_end		= header_start + HEADER_SIZE;
> +
> +	u8 *sigstruct_start	= header_end;
> +	u8 *sigstruct_end	= sigstruct_start + sigstruct_len;
> +
> +	u8 *module_start	= sigstruct_end;
> +
> +	/* Check the calculated payload size against the data size. */
> +	if (HEADER_SIZE + sigstruct_len + module_len != size)
> +		return -EINVAL;
> +
> +	/*
> +	 * Don't care about user passing the wrong file, but protect
> +	 * kernel ABI by preventing accepting garbage.
> +	 */

How does this "protect kernel ABI"?

> +	if (header->version != TDX_IMAGE_VERSION_2)
> +		return -EINVAL;
> +
> +	if (memcmp(header->signature, "TDX-BLOB", sizeof(header->signature)))
> +		return -EINVAL;
> +
> +	if (memchr_inv(header->reserved, 0, sizeof(header->reserved)))
> +		return -EINVAL;
> +
> +	populate_seamldr_params(params, sigstruct_start, header->sigstruct_nr_pages,
> +				module_start, header->module_nr_pages);

Please work on the vertical alignment if there's a pattern. For
instance, it makes things pop if the two "header->"'s are vertically
aligned.

  parent reply	other threads:[~2026-05-15 18:24 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-13 15:09 [PATCH v9 00/23] Runtime TDX module update support Chao Gao
2026-05-13 15:09 ` [PATCH v9 01/23] x86/virt/tdx: Consolidate TDX global initialization states Chao Gao
2026-05-15 16:14   ` Dave Hansen
2026-05-13 15:09 ` [PATCH v9 02/23] x86/virt/tdx: Move TDX_FEATURES0 bits to asm/tdx.h Chao Gao
2026-05-15 16:15   ` Dave Hansen
2026-05-13 15:09 ` [PATCH v9 03/23] x86/virt/tdx: Move low level SEAMCALL helpers out of <asm/tdx.h> Chao Gao
2026-05-13 15:09 ` [PATCH v9 04/23] coco/tdx-host: Introduce a "tdx_host" device Chao Gao
2026-05-15 16:21   ` Dave Hansen
2026-05-13 15:09 ` [PATCH v9 05/23] coco/tdx-host: Expose TDX module version Chao Gao
2026-05-15 16:53   ` Dave Hansen
2026-05-13 15:09 ` [PATCH v9 06/23] x86/virt/seamldr: Introduce a wrapper for P-SEAMLDR SEAMCALLs Chao Gao
2026-05-15 17:02   ` Dave Hansen
2026-05-15 17:07   ` Dave Hansen
2026-05-13 15:09 ` [PATCH v9 07/23] x86/virt/seamldr: Add a helper to retrieve P-SEAMLDR information Chao Gao
2026-05-15 17:18   ` Dave Hansen
2026-05-13 15:09 ` [PATCH v9 08/23] coco/tdx-host: Expose P-SEAMLDR information via sysfs Chao Gao
2026-05-15 17:23   ` Dave Hansen
2026-05-15 17:28   ` Dave Hansen
2026-05-13 15:09 ` [PATCH v9 09/23] coco/tdx-host: Don't expose P-SEAMLDR information on CPUs with erratum Chao Gao
2026-05-15 17:26   ` Dave Hansen
2026-05-13 15:09 ` [PATCH v9 10/23] coco/tdx-host: Implement firmware upload sysfs ABI for TDX module updates Chao Gao
2026-05-15 18:05   ` Dave Hansen
2026-05-13 15:09 ` [PATCH v9 11/23] x86/virt/seamldr: Allocate and populate a module update request Chao Gao
2026-05-15  6:05   ` Chao Gao
2026-05-15 18:24   ` Dave Hansen [this message]
2026-05-15 18:44     ` Edgecombe, Rick P
2026-05-15 18:59       ` Dave Hansen
2026-05-15 19:43   ` Dave Hansen
2026-05-13 15:09 ` [PATCH v9 12/23] x86/virt/seamldr: Introduce skeleton for TDX module updates Chao Gao
2026-05-13 15:09 ` [PATCH v9 13/23] x86/virt/seamldr: Abort updates after a failed step Chao Gao
2026-05-13 15:09 ` [PATCH v9 14/23] x86/virt/seamldr: Shut down the current TDX module Chao Gao
2026-05-13 15:09 ` [PATCH v9 15/23] x86/virt/tdx: Reset software states during TDX module shutdown Chao Gao
2026-05-13 15:09 ` [PATCH v9 16/23] x86/virt/seamldr: Install a new TDX module Chao Gao
2026-05-13 15:10 ` [PATCH v9 17/23] x86/virt/seamldr: Do TDX per-CPU initialization after module installation Chao Gao
2026-05-13 15:10 ` [PATCH v9 18/23] x86/virt/tdx: Restore TDX module state Chao Gao
2026-05-13 15:10 ` [PATCH v9 19/23] x86/virt/tdx: Refresh TDX module version after update Chao Gao
2026-05-13 15:10 ` [PATCH v9 20/23] x86/virt/tdx: Reject updates during compatibility-sensitive operations Chao Gao
2026-05-15  6:12   ` Chao Gao
2026-05-13 15:10 ` [PATCH v9 21/23] x86/virt/tdx: Enable TDX module runtime updates Chao Gao
2026-05-13 15:10 ` [PATCH v9 22/23] coco/tdx-host: Document TDX module update compatibility criteria Chao Gao
2026-05-13 15:10 ` [PATCH v9 23/23] x86/virt/tdx: Document TDX module update Chao Gao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7d7fff5a-53a5-439e-9ff8-dcbd97f473cd@intel.com \
    --to=dave.hansen@intel.com \
    --cc=binbin.wu@linux.intel.com \
    --cc=bp@alien8.de \
    --cc=chao.gao@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=djbw@kernel.org \
    --cc=hpa@zytor.com \
    --cc=ira.weiny@intel.com \
    --cc=kai.huang@intel.com \
    --cc=kas@kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-coco@lists.linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=nik.borisov@suse.com \
    --cc=paulmck@kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=reinette.chatre@intel.com \
    --cc=rick.p.edgecombe@intel.com \
    --cc=sagis@google.com \
    --cc=seanjc@google.com \
    --cc=tglx@kernel.org \
    --cc=tony.lindgren@linux.intel.com \
    --cc=vannapurve@google.com \
    --cc=vishal.l.verma@intel.com \
    --cc=x86@kernel.org \
    --cc=xiaoyao.li@intel.com \
    --cc=yan.y.zhao@intel.com \
    --cc=yilun.xu@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox