Devicetree
 help / color / mirror / Atom feed
From: Frank Li <Frank.li@oss.nxp.com>
To: sashiko-reviews@lists.linux.dev
Cc: pankaj.gupta@oss.nxp.com, Frank.Li@kernel.org,
	imx@lists.linux.dev, robh@kernel.org, devicetree@vger.kernel.org,
	conor+dt@kernel.org
Subject: Re: [PATCH v35 5/7] firmware: imx: adds miscdev
Date: Thu, 6 Aug 2026 11:31:29 -0500	[thread overview]
Message-ID: <anS24Uf5jI7auJxS@SMW015318> (raw)
In-Reply-To: <20260806112724.89B351F000E9@smtp.kernel.org>

On Thu, Aug 06, 2026 at 11:27:24AM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
> - [Critical] The driver allows userspace to embed arbitrary DMA addresses in permitted firmware commands, enabling arbitrary physical memory overwrite.
> - [High] The `se_if_open_gate` structure can be accessed after it is freed if an `open()` system call races with driver unbind.
> - [High] A concurrent `close()` racing with driver unbind causes a Use-After-Free on the mailbox channel `priv->tx_chan` due to premature unlinking.
> - [High] Firmware session and storage handles can be permanently leaked if response validation or userspace memory copies fail, bypassing the tracking of allocated handles.
> - [High] Signal interruption converts an interruptible wait into an unkillable uninterruptible wait for up to 5000 seconds.
> --
>
> --- Patch [5]: [PATCH v35 5/7] firmware: imx: adds miscdev ---
> commit a678d58783e842f1a853a0ba674864702cf30910
> Author: Pankaj Gupta <pankaj.gupta@nxp.com>
> Subject: firmware: imx: adds miscdev
>
> This commit adds a character driver to communicate with the NXP secure
> enclave hardware. It provides an ioctl interface for userspace applications
> to send commands, manage shared memory, and restricts invalid or disallowed
> firmware commands.
>
> Closes: https://sashiko.dev/#/patchset/20260805-imx-se-if-v34-0-7e4713d14e0a@nxp.com?part=5
>
> > diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c
> > --- a/drivers/firmware/imx/ele_base_msg.c
> > +++ b/drivers/firmware/imx/ele_base_msg.c
> > @@ -15,13 +15,57 @@
> >
> >  #define FW_DBG_DUMP_FIXED_STR		"ELE"
> >
> > +int ele_uapi_allowed_base_cmd(struct se_if_priv *priv,
> > +			      struct se_msg_hdr *header)
> > +{
> > +	switch (header->command) {
> > +	case ELE_PING_REQ: return 0;
> > +	case ELE_DEBUG_DUMP_REQ: return 0;
> > +	case ELE_OEM_AUTH_CONTAINER_REQ: return 0;
> > +	case ELE_OEM_VERIFY_IMAGE_REQ: return 0;
> > +	case ELE_OEM_REL_CONTAINER_REQ: return 0;
> > +	case ELE_FW_LIFE_CYCLE_REQ: return 0;
> > +	case ELE_READ_FUSE_REQ: return 0;
> > +	case ELE_GET_FW_VERS_REQ: return 0;
> > +	case ELE_RETURN_LIFE_CYCLE_REQ: return 0;
> > +	case ELE_GET_EVENT_REQ: return 0;
> > +	case ELE_COMMIT_REQ: return 0;
> > +	case ELE_GEN_KEY_BLOB_REQ: return 0;
> > +	case ELE_GET_FW_STATUS_REQ: return 0;
> > +	case ELE_XIP_DECRYPT_REQ: return 0;
> > +	case ELE_WRITE_FUSE: return 0;
> > +	case ELE_GET_INFO_REQ: return 0;
> > +	case ELE_DEV_ATTEST_REQ: return 0;
> > +	case ELE_WRITE_SHADOW_FUSE_REQ: return 0;
> > +	case ELE_READ_SHADOW_FUSE_REQ: return 0;
> > +	default:
> > +		return -EACCES;
> > +	}
> > +}
>
> [Severity: Critical]
> Does this allowlist permit userspace to embed arbitrary DMA addresses without
> kernel validation?
>
> Commands like ELE_GET_INFO_REQ accept physical DMA addresses directly in
> their payloads. Because se_chk_tx_msg_hdr() only validates the command header
> against this list and performs no payload sanitization, could an unprivileged
> user embed arbitrary physical addresses (e.g., kernel text) leading to the
> hardware enclave overwriting arbitrary memory?

This one may security hole, you need check payload to make sure DMA
address is in ranges.

>
> > diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c
> > --- a/drivers/firmware/imx/ele_common.c
> > +++ b/drivers/firmware/imx/ele_common.c
> [ ... ]
> > @@ -71,7 +122,7 @@ int ele_msg_rcv(struct se_if_device_ctx *dev_ctx, struct se_clbk_handle *se_clbk
> > +		if (ret == -ERESTARTSYS) {
> > +			/*
> > +			 * Record that a signal was observed, then continue waiting non-
> > +			 * interruptibly until the response arrives or the timeout
> > +			 * expires. The caller can surface the interruption to userspace
> > +			 * after the protocol transaction is brought back to a
> > +			 * synchronized state.
> > +			 */
> > +			if (is_rsp_wait_with_timeout &&
> > +			    READ_ONCE(se_clbk_hdl->rx_msg)) {
> > +				WRITE_ONCE(se_clbk_hdl->signal_rcvd, true);
> > +				wait_uninterruptible = true;
> > +				continue;
> > +			}
> > +			break;
> > +		}
>
> [Severity: High]
> Can this loop trap a process in an unkillable state for a very long time?
>
> If a process is interrupted by a signal while waiting in ele_msg_rcv(), the
> code converts the interruptible wait into an uninterruptible one by setting
> wait_uninterruptible = true. Given that SE_RCV_MSG_LONG_TIMEOUT_MS is 5000
> seconds, this could leave the task unkillable for over an hour, potentially
> triggering the kernel's hung task watchdog.


This one need double check.

Other high problem need your judgement.

Frank

>
> > diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c
> > --- a/drivers/firmware/imx/se_ctrl.c
> > +++ b/drivers/firmware/imx/se_ctrl.c
> [ ... ]
> > +static void dlink_n_cleanup_dev_ctx(struct se_if_device_ctx *dev_ctx, bool is_fclose)
> > +{
> > +	struct se_if_priv *priv = dev_ctx->priv;
> > +
> > +	if (is_fclose) {
> > +		scoped_guard(mutex, &priv->modify_lock)
> > +			dlink_dev_ctx(dev_ctx);
> > +	}
> > +
> > +	cleanup_dev_ctx(dev_ctx, is_fclose);
> > +}
>
> [Severity: High]
> Does unlinking dev_ctx before executing cleanup_dev_ctx() open a race
> condition during driver unbind?
>
> In se_if_probe_cleanup(), the unbind thread iterates over priv->dev_ctx_list
> to gracefully close contexts. By unlinking the context here before the
> cleanup completes, the unbind thread won't see it, won't block on fops_lock,
> and might call mbox_free_channel(priv->tx_chan) prematurely. This could cause
> the concurrent close thread to send on a freed channel in ele_msg_send().
>
> [ ... ]
> > +	rsp_status_err =
> > +		se_val_rsp_hdr_n_status(priv, rx_msg, tx_msg->header.command,
> > +					cmd_snd_rcv_rsp_info.rx_buf_sz,
> > +					tx_msg->header.ver == priv->if_defs->base_api_ver);
> > +
> > +	if (!rsp_status_err) {
> > +		err = se_dev_ctx_cpy_out_data(dev_ctx);
> > +		if (err < 0) {
> > +			se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info);
> > +			return err;
> > +		}
> > +	}
> > +
> > +	/* Copy data from the buffer */
> > +	print_hex_dump_debug("to user ", DUMP_PREFIX_OFFSET, 4, 4, rx_msg,
> > +			     cmd_snd_rcv_rsp_info.rx_buf_sz, false);
> > +
> > +	if (copy_to_user(u64_to_user_ptr(cmd_snd_rcv_rsp_info.rx_buf), rx_msg,
> > +			 cmd_snd_rcv_rsp_info.rx_buf_sz)) {
> > +		dev_err(priv->dev, "%s: Failed to copy to user.", dev_ctx->devname);
> > +		err = -EFAULT;
> > +	}
> > +
> > +	cleanup_err = se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info);
> > +
> > +	if (cleanup_err && !err)
> > +		err = cleanup_err;
> > +
> > +	if (!err && !rsp_status_err)
> > +		fw_api_specific_ops(dev_ctx, rx_msg);
>
> [Severity: High]
> Could this error handling sequence leak firmware session or storage handles?
>
> If the firmware successfully executes an ELE_SESSION_OPEN_REQ, it allocates a
> handle. However, if a user submits an intentionally truncated rx_buf_sz
> (causing se_val_rsp_hdr_n_status() to fail) or a bad user pointer (causing
> copy_to_user() to fail), the function skips calling fw_api_specific_ops().
> This leaves the handle untracked by the kernel, preventing cleanup and
> leaking hardware resources.
>
> [ ... ]
> > +/* Open a character device. */
> > +static int se_if_fops_open(struct inode *nd, struct file *fp)
> > +{
> > +	struct miscdevice *miscdev = fp->private_data;
> > +	struct se_if_open_gate *gate;
> > +	struct se_if_device_ctx *misc_dev_ctx;
> > +	struct se_if_device_ctx *dev_ctx;
> > +	struct se_if_priv *priv;
> > +	int err = 0;
> > +
> > +	gate = container_of(miscdev, struct se_if_open_gate, miscdev);
> > +
> > +	if (!se_if_open_gate_get(gate))
> > +		return -ENODEV;
>
> [Severity: High]
> Is there a use-after-free risk if open() races with driver unbind?
>
> When the module unbinds, se_if_probe_cleanup() calls misc_deregister(),
> which does not fully synchronize with active open() calls. If the unbind
> thread drops the final reference to priv in se_if_priv_release(),
> se_if_open_gate_put() frees the gate object. A concurrent se_if_fops_open()
> might then attempt to access the refcount of this already freed gate pointer.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260806-imx-se-if-v35-0-11b25bb308ef@nxp.com?part=5

  reply	other threads:[~2026-08-06 16:31 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-06 11:51 [PATCH v35 0/7] firmware: imx: driver for NXP secure-enclave pankaj.gupta
2026-08-06 11:51 ` [PATCH v35 1/7] Documentation/firmware: add imx/se to other_interfaces pankaj.gupta
2026-08-06 11:08   ` sashiko-bot
2026-08-06 11:51 ` [PATCH v35 2/7] dt-bindings: arm: fsl: add imx-se-fw binding doc pankaj.gupta
2026-08-06 11:51 ` [PATCH v35 3/7] firmware: imx: add driver for NXP EdgeLock Enclave pankaj.gupta
2026-08-06 11:17   ` sashiko-bot
2026-08-06 16:08     ` Frank Li
2026-08-06 11:51 ` [PATCH v35 4/7] firmware: imx: device context dedicated to priv pankaj.gupta
2026-08-06 11:15   ` sashiko-bot
2026-08-06 11:51 ` [PATCH v35 5/7] firmware: imx: adds miscdev pankaj.gupta
2026-08-06 11:27   ` sashiko-bot
2026-08-06 16:31     ` Frank Li [this message]
2026-08-06 11:51 ` [PATCH v35 6/7] arm64: dts: imx8ulp: add secure enclave node pankaj.gupta
2026-08-06 11:13   ` sashiko-bot
2026-08-06 11:51 ` [PATCH v35 7/7] arm64: dts: imx8ulp: add reserved memory for EdgeLock Enclave pankaj.gupta

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=anS24Uf5jI7auJxS@SMW015318 \
    --to=frank.li@oss.nxp.com \
    --cc=Frank.Li@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=imx@lists.linux.dev \
    --cc=pankaj.gupta@oss.nxp.com \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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