RE: [PATCH v38 3/7] firmware: imx: add driver for NXP EdgeLock Enclave

"Pankaj Gupta (OSS)" <[email protected]>
Newsgroups dev.linux.lists.sashiko-reviews,dev.linux.lists.imx,org.kernel.vger.linux-devicetree
Message-ID <GV2PR04MB122719F7A74C3AD65F4A3E08695A32@GV2PR04MB12271.eurprd04.prod.outlook.com>
> > +int ele_get_info(struct se_if_priv *priv, struct ele_dev_info
> > +*s_info) {
>
> [ ... ]
>
> > +   ret = ele_msg_send_rcv(priv, tx_msg, ELE_GET_INFO_REQ_MSG_SZ,
> rx_msg,
> > +                          ELE_GET_INFO_RSP_MSG_SZ);
> > +   if (ret < 0) {
> > +           ele_get_info_cleanup(priv, get_info_data, get_info_addr,
> > +get_info_len);
>
> [Severity: High]
> If an enclave command times out, ele_msg_send_rcv() returns -ETIMEDOUT and
> the error path immediately calls ele_get_info_cleanup(), which frees the DMA
> buffer. If the firmware is still executing and completes the transaction later, could
> it perform a DMA write into physical memory that has been reallocated to
> another subsystem?
>
> > +           return ret;
> > +   }
>
[Already taken care in 5/7]
At 3/7 the cleanup frees unconditionally (gen_pool_free/dma_free_coherent) and
the timeout leg only does a bare atomic_set(\&priv->fw_busy, 1),
which cannot fence an in-flight enclave DMA.
The symbols that fix it (se_is_fw_busy_ctx/se_mark_fw_busy, priv_dev_ctx) do not exist at 3/7.
It is resolved by PATCH v33 5/7 (fb107010a07b, "firmware: imx: adds miscdev"),
which adds per-context fw_busy ownership and rewrites ele_get_info_cleanup() to
 quarantine (return without freeing) the buffer while the owning context is still busy.

> [ ... ]
>
> > +int ele_debug_dump(struct se_if_priv *priv) {
>
> [ ... ]
>
> > +           rx_msg->header.size -= 2;
> > +
> > +           if (rx_msg->header.size > 2)
> > +                   rx_msg->header.size--;
> > +
> > +           for (i = 0; i < rx_msg->header.size; i += 2)
> > +                   dev_info(priv->dev, "%s%02x_%02x: 0x%08x 0x%08x",
> > +                            FW_DBG_DUMP_FIXED_STR, msg_ex_cnt, i,
> > +                            rx_msg->data[i + 1], rx_msg->data[i + 2]);
>
> [Severity: Low]
> Does this loop read past the actual message payload length? If the firmware
> returns an odd number of payload words, the remaining size is not even. The
> loop body would execute when exactly 1 word remains but print both rx_msg-
> >data[i + 1] and rx_msg->data[i + 2].
>
Not an issue.
rx_msg->data[i + 2], would be printed as 0x00000000.

> > +
> > +           msg_ex_cnt++;
> > +   } while (keep_logging);
> > +
> > +   return ret;
> > +}
>
> > diff --git a/drivers/firmware/imx/se_ctrl.c
> > b/drivers/firmware/imx/se_ctrl.c index 0000000000000..53091cc37e7e0
> > 100644
> > --- /dev/null
> > +++ b/drivers/firmware/imx/se_ctrl.c
>
> [ ... ]
>
> > +static void se_if_probe_cleanup(void *plat_dev) {
> > +   struct platform_device *pdev = plat_dev;
> > +   struct device *dev = &pdev->dev;
> > +   struct se_if_priv *priv;
> > +
> > +   priv = dev_get_drvdata(dev);
> > +   if (!priv)
> > +           return;
> > +
> > +   if (priv->rx_chan)
> > +           mbox_free_channel(priv->rx_chan);
> > +   if (priv->tx_chan)
> > +           mbox_free_channel(priv->tx_chan);
> > +
> > +   /*
> > +    * Being device managed buffer, no need to free the buffer allocated
> > +    * in se probe to store encrypted IMEM.
> > +    */
> > +
> > +   /*
> > +    * No need to check, if reserved memory is allocated
> > +    * before calling for its release. Or clearing the
> > +    * un-set bit.
> > +    */
> > +   of_reserved_mem_device_release(dev);
> > +
> > +   dev_set_drvdata(dev, NULL);
> > +
> > +   kfree(priv);
>
> [Severity: High]
> Similarly, does this teardown path free device-managed DMA memory without
> waiting for or aborting a potentially busy firmware transaction?

Superseded by patch 5/7.

The teardown safety concern is valid in isolation on commit 3/7 ("firmware: imx: add driver for NXP EdgeLock Enclave"),
which only has the minimal skeleton.
It is resolved in commit 5/7 ("firmware: imx: adds miscdev") where `se_if_probe_cleanup()` is rewritten to:

1. `atomic_set(&priv->going_away, 1)` — circuit-breaker that causes new `ele_msg_send_rcv()` callers to return `-ENODEV` without arming a transaction.
2. `complete_all(&priv->waiting_rsp_clbk_hdl.done)` — wakes any thread currently blocked waiting for a FW response.
3. `cancel_work_sync(&priv->fw_busy_work)` — drains the late-response workqueue.
4. `kref_put(&priv->refcount, se_if_priv_release)` replaces the bare `kfree(priv)` — `priv` and all embedded objects (completions, spinlocks) are freed only after all reference holders have dropped their ref.

The IMEM DMA buffer (`dmam_alloc_coherent`) is devres-managed and was never freed by `kfree(priv)` in either version; devres releases it automatically after the devm action returns

>
> > +}
>
> [ ... ]
>
> > +static int se_resume(struct device *dev) {
> > +   struct se_if_priv *priv = dev_get_drvdata(dev);
> > +   struct se_fw_load_info *load_fw;
> > +   int ret = 0;
> > +
> > +   load_fw = get_load_fw_instance(priv);
> > +
> > +   if (load_fw->imem_mgmt) {
> > +           ret = se_restore_imem_state(priv, &load_fw->imem);
> > +           if (ret)
> > +                   dev_warn(dev, "Failure restoring IMEM state[0x%x]",
> ret);
> > +   }
> > +
> > +   return 0;
>
> [Severity: Medium]
> Should this return the actual error instead of 0? se_restore_imem_state()
> documents that it returns -EIO so the PM subsystem knows the enclave is non-
> functional after resume, but the failure is caught here and 0 is unconditionally
> returned, breaking the expected power management error handling semantics.
>
Accepted will fix in v39.

> > +}
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260820-imx-se-if-v38-0-
> [email protected]?part=3

NXP Confidential
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.