dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Taimuraz Kaitmazov" <taimuraz@kaitmazov.com>
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v3] accel/amdxdna: use READ_ONCE/WRITE_ONCE on the command header
Date: Wed, 26 Aug 2026 22:27:51 +0000	[thread overview]
Message-ID: <20260826222752.3909C1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260826221334.625974-1-taimuraz@kaitmazov.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] The patch fails to resolve the TOCTOU vulnerability because it issues multiple independent `READ_ONCE(cmd->header)` calls instead of storing a single local snapshot.

Pre-existing issues:
- [High] Undefined behavior caused by passing a `NULL` source pointer to `memcpy()` when parsing an empty command payload.
- [High] Uninitialized kernel stack memory is sent to the hardware mailbox, causing an information leak.
--

commit c8e0faf1355b7f70321f8abedf7d99ec0ac63c46
Author: Taimuraz Kaitmazov <taimuraz@kaitmazov.com>

    accel/amdxdna: use READ_ONCE/WRITE_ONCE on the command header

This commit attempts to fix a TOCTOU race condition in the command header
parsing by using READ_ONCE and WRITE_ONCE macros. It aims to read the
user-mapped command header once into a local variable to prevent the
compiler from splitting loads.

> diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c
> index 888e857ec5582..02027522210d9 100644
> --- a/drivers/accel/amdxdna/amdxdna_ctx.c
> +++ b/drivers/accel/amdxdna/amdxdna_ctx.c
> @@ -123,10 +123,11 @@ void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
>  	if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN)
>  		num_masks = 0;
>  	else
> -		num_masks = 1 + FIELD_GET(AMDXDNA_CMD_EXTRA_CU_MASK, cmd->header);
> +		num_masks = 1 + FIELD_GET(AMDXDNA_CMD_EXTRA_CU_MASK,
> +					  READ_ONCE(cmd->header));
>  
>  	if (size) {
> -		count = FIELD_GET(AMDXDNA_CMD_COUNT, cmd->header);
> +		count = FIELD_GET(AMDXDNA_CMD_COUNT, READ_ONCE(cmd->header));

[Severity: High]
Does this actually fix the race condition? The commit message explicitly
claims to fix this by reading the header "once into a local with
READ_ONCE()".

Because READ_ONCE() enforces a volatile memory access, the compiler is
forced to issue multiple distinct memory loads for the opcode,
EXTRA_CU_MASK, and COUNT fields.

Could the fields still be fetched from different snapshots of the header,
maintaining the TOCTOU vulnerability?

>  		if (unlikely(count <= num_masks ||
>  			     count * sizeof(u32) +
>  			     offsetof(struct amdxdna_cmd, data[0]) >
> @@ -151,7 +152,7 @@ u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo)
>  	if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN)
>  		return INVALID_CU_IDX;
>  
> -	num_masks = 1 + FIELD_GET(AMDXDNA_CMD_EXTRA_CU_MASK, cmd->header);
> +	num_masks = 1 + FIELD_GET(AMDXDNA_CMD_EXTRA_CU_MASK, READ_ONCE(cmd->header));

[Severity: High]
Does this suffer from the same issue? amdxdna_cmd_get_op() already reads
the header, and here it is read again with a separate READ_ONCE(), rather
than using a single local variable.

[ ... ]

> @@ -169,12 +170,15 @@ int amdxdna_cmd_set_error(struct amdxdna_gem_obj *abo,
>  	struct amdxdna_client *client = job->hwctx->client;
>  	struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
>  	struct amdxdna_cmd_chain *cc = NULL;
> +	u32 header;
>  
>  	if (!cmd)
>  		return -ENOMEM;
>  
> -	cmd->header &= ~AMDXDNA_CMD_STATE;
> -	cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, error_state);
> +	header = READ_ONCE(cmd->header);
> +	header &= ~AMDXDNA_CMD_STATE;
> +	header |= FIELD_PREP(AMDXDNA_CMD_STATE, error_state);
> +	WRITE_ONCE(cmd->header, header);
>  
>  	if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN) {

[Severity: High]
Does this code read the header again after modifying it?

amdxdna_cmd_get_op() internally does a READ_ONCE(cmd->header), which
happens right after the write. Could it end up reading a newly injected
opcode if userspace modifies the header concurrently?

[Severity: High]
This isn't a bug introduced by this patch, but could this trigger undefined
behavior if a user passes an empty payload?

If a userspace application configures a command buffer with
count <= num_masks, amdxdna_cmd_get_payload() can validly return NULL:

drivers/accel/amdxdna/amdxdna_ctx.c:amdxdna_cmd_get_payload() {
    ...
		if (unlikely(count <= num_masks ||
			     count * sizeof(u32) +
			     offsetof(struct amdxdna_cmd, data[0]) >
			     abo->mem.size)) {
			*size = 0;
			return NULL;
		}
    ...
}

In drivers/accel/amdxdna/aie2_message.c:aie2_init_exec_cu_req(), the
returned pointer is passed directly to memcpy() without validation:

	cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
	if (cmd_len > sizeof(cu_req->payload))
		return -EINVAL;

	cu_req->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
	if (cu_req->cu_idx == INVALID_CU_IDX)
		return -EINVAL;

	memcpy(cu_req->payload, cmd, cmd_len);

Passing a NULL pointer to memcpy() triggers undefined behavior according
to the C standard, even if the length is 0. Will this cause a kernel
panic if panic_on_warn is enabled when UBSAN catches this?

[Severity: High]
This is a pre-existing issue, but does this leak uninitialized stack
memory to the hardware mailbox?

In drivers/accel/amdxdna/aie2_message.c:aie2_execbuf(), an uninitialized
union is allocated on the stack:

	union exec_req req;
    ...
	ret = aie2_init_exec_req(&req, cmd_abo, &msg.send_size, &msg.opcode);

If aie2_init_exec_cu_req() processes a small payload (e.g. cmd_len = 0),
the remainder of the payload array retains uninitialized stack contents:

	memcpy(cu_req->payload, cmd, cmd_len);
	*size = sizeof(*cu_req);

Could the remaining 76 bytes of uninitialized kernel stack memory be
transmitted when xdna_mailbox_send_msg() is called?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260826221334.625974-1-taimuraz@kaitmazov.com?part=1

  reply	other threads:[~2026-08-26 22:27 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-26 14:30 [PATCH 0/2] accel/amdxdna: make the shared command header safe to read Taimuraz Kaitmazov
2026-08-26 14:30 ` [PATCH 1/2] accel/amdxdna: check the command chain payload before using it Taimuraz Kaitmazov
2026-08-26 14:43   ` sashiko-bot
2026-08-26 14:30 ` [PATCH 2/2] accel/amdxdna: use READ_ONCE/WRITE_ONCE on the command header Taimuraz Kaitmazov
2026-08-26 14:50   ` sashiko-bot
2026-08-26 15:31 ` [PATCH v2 0/2] accel/amdxdna: make the shared command header safe to read Taimuraz Kaitmazov
2026-08-26 15:31   ` [PATCH v2 1/2] accel/amdxdna: check the command chain payload before using it Taimuraz Kaitmazov
2026-08-26 15:48     ` sashiko-bot
2026-08-26 21:32     ` Lizhi Hou
2026-08-26 22:13       ` [PATCH v3] accel/amdxdna: use READ_ONCE/WRITE_ONCE on the command header Taimuraz Kaitmazov
2026-08-26 22:27         ` sashiko-bot [this message]
2026-08-26 15:31   ` [PATCH v2 2/2] " Taimuraz Kaitmazov
2026-08-26 23:16     ` Lizhi Hou
2026-08-27  0:20       ` Taimuraz Kaitmazov

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=20260826222752.3909C1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=taimuraz@kaitmazov.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;
as well as URLs for NNTP newsgroup(s).