[PATCH -next] firmware: imx: se_ctrl: roll back iobuf reservation on setup failure
From: pankaj . gupta
Date: Thu Jun 11 2026 - 06:23:06 EST
From: Pankaj Gupta <pankaj.gupta@xxxxxxx>
se_ioctl_setup_iobuf_handler() reserves space from the per-file shared
memory pool before copying user data and linking a buffer descriptor.
If copy_from_user() or add_b_desc_to_pending_list() fails after the
reservation, the function returns without restoring shared_mem->pos,
which permanently consumes part of the shared memory pool for that file
descriptor.
Also, add_b_desc_to_pending_list() failure currently falls through to
the copy_to_user() path, which can return an ELE address to userspace
even though setup failed.
Fix this by rolling back the reserved shared-memory position on
pre-link failures and by unlinking the descriptor before rolling back
the pool reservation when copy_to_user() fails after descriptor
insertion.
Fixes: b87b30bbdfb2 ("firmware: drivers: imx: adds miscdev")
Reported-by: sashiko-bot <sashiko-bot@xxxxxxxxxx>
Closes: https://sashiko.dev/#/patchset/20260528091532.3331051-1-pankaj.gupta@xxxxxxx?part=1
Signed-off-by: Pankaj Gupta <pankaj.gupta@xxxxxxx>
---
drivers/firmware/imx/se_ctrl.c | 37 +++++++++++++++++++++++++---------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c
index 5b23485fe42c..e42e5e23f48a 100644
--- a/drivers/firmware/imx/se_ctrl.c
+++ b/drivers/firmware/imx/se_ctrl.c
@@ -365,16 +365,16 @@ static void se_dev_ctx_shared_mem_cleanup(struct se_if_device_ctx *dev_ctx)
se_shared_mem_mgmt->non_secure_mem.pos = 0;
}
-static int add_b_desc_to_pending_list(void *shared_ptr_with_pos,
- struct se_ioctl_setup_iobuf *io,
- struct se_if_device_ctx *dev_ctx)
+static struct se_buf_desc *add_b_desc_to_pending_list(void *shared_ptr_with_pos,
+ struct se_ioctl_setup_iobuf *io,
+ struct se_if_device_ctx *dev_ctx)
{
struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt;
- struct se_buf_desc *b_desc;
+ struct se_buf_desc *b_desc = NULL;
b_desc = kzalloc_obj(*b_desc, GFP_KERNEL);
if (!b_desc)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
b_desc->shared_buf_ptr = shared_ptr_with_pos;
b_desc->usr_buf_ptr = io->user_buf;
@@ -398,7 +398,7 @@ static int add_b_desc_to_pending_list(void *shared_ptr_with_pos,
list_add_tail(&b_desc->link, &se_shared_mem_mgmt->pending_out);
}
- return 0;
+ return b_desc;
}
/* interface for managed res to unregister a character device */
@@ -641,7 +641,8 @@ static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx,
{
struct se_shared_mem *shared_mem = NULL;
struct se_ioctl_setup_iobuf io = {0};
- size_t aligned_len;
+ struct se_buf_desc *b_desc = NULL;
+ size_t aligned_len = 0;
int err = 0;
u32 pos;
@@ -703,14 +704,18 @@ static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx,
dev_err(dev_ctx->priv->dev,
"%s: Failed copy data to shared memory.",
dev_ctx->devname);
- return -EFAULT;
+ err = -EFAULT;
+ goto rollback;
}
}
- err = add_b_desc_to_pending_list(shared_mem->ptr + pos, &io, dev_ctx);
- if (err < 0)
+ b_desc = add_b_desc_to_pending_list(shared_mem->ptr + pos, &io, dev_ctx);
+ if (IS_ERR(b_desc)) {
+ err = PTR_ERR(b_desc);
dev_err(dev_ctx->priv->dev, "%s: Failed to allocate/link b_desc.",
dev_ctx->devname);
+ goto rollback;
+ }
copy:
/* Provide the EdgeLock Enclave address to user space only if success.*/
@@ -718,6 +723,18 @@ static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx,
dev_err(dev_ctx->priv->dev, "%s: Failed to copy iobuff setup to user.",
dev_ctx->devname);
err = -EFAULT;
+ if (b_desc) {
+ list_del(&b_desc->link);
+ kfree(b_desc);
+ }
+ goto rollback;
+ }
+ return err;
+
+rollback:
+ if (aligned_len) {
+ memset(shared_mem->ptr + pos, 0, aligned_len);
+ shared_mem->pos = pos;
}
return err;
--
2.43.0