* Re: [PATCH v2] tee: fix missing shm reference cleanup in tee_ioctl_supp_recv
2026-05-05 15:30 ` [PATCH v2] " Qihang
@ 2026-05-06 2:18 ` Qihang
2026-05-07 7:31 ` Jens Wiklander
2026-05-07 7:47 ` Jens Wiklander
2026-05-07 9:45 ` [PATCH v3] tee: fix params_from_user() error path " Qihang
2 siblings, 1 reply; 13+ messages in thread
From: Qihang @ 2026-05-06 2:18 UTC (permalink / raw)
To: jens.wiklander, sumit.garg; +Cc: op-tee
Hi Jens, Sumit,
While reworking this, I noticed that there may be two slightly
different cleanup issues involved here.
One appears to be in tee_ioctl_supp_recv() itself. Another may be in a
qcomtee-specific error path where MEMREF references can already have
been acquired before the backend rejects the parameters.
I am not entirely sure where you would prefer the boundary between the
core fix and any backend-specific fix to be.
Would you prefer that I keep the current patch strictly focused on the
tee_ioctl_supp_recv() cleanup path first, and handle any qcomtee-side
issue separately if needed?
Thanks,
Qihang
On Tue, May 5, 2026 at 11:30 PM Qihang <q.h.hack.winter@gmail.com> wrote:
>
> params_from_user() acquires tee_shm references for MEMREF parameters and
> expects the caller to release those references with tee_shm_put() during
> cleanup.
>
> tee_ioctl_open_session(), tee_ioctl_invoke(), and
> tee_ioctl_object_invoke() all do this, but tee_ioctl_supp_recv() only
> frees the parameter array and does not drop any acquired shared-memory
> references.
>
> Fix this by using a common helper to release MEMREF references before
> freeing the parameter array, and apply it to tee_ioctl_supp_recv() as
> well.
>
> Signed-off-by: Qihang <q.h.hack.winter@gmail.com>
> ---
> v2:
> - rename helper to free_params()
> - drop alloc_num_params and use num_params directly
>
> drivers/tee/tee_core.c | 46 +++++++++++++++++-------------------------
> 1 file changed, 19 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> index ef9642d72672..8cdf2ec7e74f 100644
> --- a/drivers/tee/tee_core.c
> +++ b/drivers/tee/tee_core.c
> @@ -530,6 +530,21 @@ static int params_to_user(struct tee_ioctl_param __user *uparams,
> return 0;
> }
>
> +static void free_params(struct tee_param *params, size_t num_params)
> +{
> + size_t n;
> +
> + if (!params)
> + return;
> +
> + for (n = 0; n < num_params; n++)
> + if (tee_param_is_memref(params + n) &&
> + params[n].u.memref.shm)
> + tee_shm_put(params[n].u.memref.shm);
> +
> + kfree(params);
> +}
> +
> static int tee_ioctl_open_session(struct tee_context *ctx,
> struct tee_ioctl_buf_data __user *ubuf)
> {
> @@ -595,16 +610,7 @@ static int tee_ioctl_open_session(struct tee_context *ctx,
> */
> if (rc && have_session && ctx->teedev->desc->ops->close_session)
> ctx->teedev->desc->ops->close_session(ctx, arg.session);
> -
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> -
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -657,14 +663,7 @@ static int tee_ioctl_invoke(struct tee_context *ctx,
> }
> rc = params_to_user(uparams, arg.num_params, params);
> out:
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -716,14 +715,7 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx,
> }
> rc = params_to_user(uparams, arg.num_params, params);
> out:
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -861,7 +853,7 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx,
>
> rc = params_to_supp(ctx, uarg->params, num_params, params);
> out:
> - kfree(params);
> + free_params(params, num_params);
> return rc;
> }
>
> --
> 2.39.5 (Apple Git-154)
>
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2] tee: fix missing shm reference cleanup in tee_ioctl_supp_recv
2026-05-06 2:18 ` Qihang
@ 2026-05-07 7:31 ` Jens Wiklander
0 siblings, 0 replies; 13+ messages in thread
From: Jens Wiklander @ 2026-05-07 7:31 UTC (permalink / raw)
To: Qihang; +Cc: sumit.garg, op-tee
Hi Qihang,
On Wed, May 6, 2026 at 4:18 AM Qihang <q.h.hack.winter@gmail.com> wrote:
>
> Hi Jens, Sumit,
>
> While reworking this, I noticed that there may be two slightly
> different cleanup issues involved here.
>
> One appears to be in tee_ioctl_supp_recv() itself. Another may be in a
> qcomtee-specific error path where MEMREF references can already have
> been acquired before the backend rejects the parameters.
>
> I am not entirely sure where you would prefer the boundary between the
> core fix and any backend-specific fix to be.
>
> Would you prefer that I keep the current patch strictly focused on the
> tee_ioctl_supp_recv() cleanup path first, and handle any qcomtee-side
> issue separately if needed?
qcomtee-specific changes should preferably go into a separate patch.
In this case, I suspect the fix is to add a similar tee_shm_put() as
we have in supp_check_recv_params() in drivers/tee/optee/supp.c.
Cheers,
Jens
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2] tee: fix missing shm reference cleanup in tee_ioctl_supp_recv
2026-05-05 15:30 ` [PATCH v2] " Qihang
2026-05-06 2:18 ` Qihang
@ 2026-05-07 7:47 ` Jens Wiklander
2026-05-07 9:45 ` [PATCH v3] tee: fix params_from_user() error path " Qihang
2 siblings, 0 replies; 13+ messages in thread
From: Jens Wiklander @ 2026-05-07 7:47 UTC (permalink / raw)
To: Qihang; +Cc: sumit.garg, op-tee
Hi Qihang,
On Tue, May 5, 2026 at 5:30 PM Qihang <q.h.hack.winter@gmail.com> wrote:
>
> params_from_user() acquires tee_shm references for MEMREF parameters and
> expects the caller to release those references with tee_shm_put() during
> cleanup.
>
> tee_ioctl_open_session(), tee_ioctl_invoke(), and
> tee_ioctl_object_invoke() all do this, but tee_ioctl_supp_recv() only
> frees the parameter array and does not drop any acquired shared-memory
> references.
>
> Fix this by using a common helper to release MEMREF references before
> freeing the parameter array, and apply it to tee_ioctl_supp_recv() as
> well.
>
> Signed-off-by: Qihang <q.h.hack.winter@gmail.com>
> ---
> v2:
> - rename helper to free_params()
> - drop alloc_num_params and use num_params directly
>
> drivers/tee/tee_core.c | 46 +++++++++++++++++-------------------------
> 1 file changed, 19 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> index ef9642d72672..8cdf2ec7e74f 100644
> --- a/drivers/tee/tee_core.c
> +++ b/drivers/tee/tee_core.c
> @@ -530,6 +530,21 @@ static int params_to_user(struct tee_ioctl_param __user *uparams,
> return 0;
> }
>
> +static void free_params(struct tee_param *params, size_t num_params)
> +{
> + size_t n;
> +
> + if (!params)
> + return;
> +
> + for (n = 0; n < num_params; n++)
> + if (tee_param_is_memref(params + n) &&
> + params[n].u.memref.shm)
> + tee_shm_put(params[n].u.memref.shm);
> +
> + kfree(params);
> +}
> +
> static int tee_ioctl_open_session(struct tee_context *ctx,
> struct tee_ioctl_buf_data __user *ubuf)
> {
> @@ -595,16 +610,7 @@ static int tee_ioctl_open_session(struct tee_context *ctx,
> */
> if (rc && have_session && ctx->teedev->desc->ops->close_session)
> ctx->teedev->desc->ops->close_session(ctx, arg.session);
> -
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> -
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -657,14 +663,7 @@ static int tee_ioctl_invoke(struct tee_context *ctx,
> }
> rc = params_to_user(uparams, arg.num_params, params);
> out:
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -716,14 +715,7 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx,
> }
> rc = params_to_user(uparams, arg.num_params, params);
> out:
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -861,7 +853,7 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx,
>
> rc = params_to_supp(ctx, uarg->params, num_params, params);
> out:
> - kfree(params);
> + free_params(params, num_params);
This doesn't work. The supp_recv() callback is special compared to
open_session(), invoke_func(), and object_invoke_func() callbacks.
supp_recv() replaces the supplied parameters with other parameters.
Eventually inserted memrefs are reference-counted separately, and
adding it here too would only add unnecessary updates (supp_recv()
would need to increase them, only so they can be decreased here).
However, I think a comment before the call to supp_recv() to remind us
of that would be nice.
However, there's a bug that needs to be fixed if params_from_user()
fails. One way of dealing with that is:
rc = params_from_user(ctx, params, num_params, uarg->params);
if (rc) {
free_params(params, num_params);
return rc;
}
and then keep the end of tee_ioctl_supp_recv() unchanged.
Cheers,
Jens
> return rc;
> }
>
> --
> 2.39.5 (Apple Git-154)
>
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v3] tee: fix params_from_user() error path in tee_ioctl_supp_recv
2026-05-05 15:30 ` [PATCH v2] " Qihang
2026-05-06 2:18 ` Qihang
2026-05-07 7:47 ` Jens Wiklander
@ 2026-05-07 9:45 ` Qihang
2026-05-07 10:40 ` Jens Wiklander
2026-05-07 15:39 ` [PATCH v4] " Qihang
2 siblings, 2 replies; 13+ messages in thread
From: Qihang @ 2026-05-07 9:45 UTC (permalink / raw)
To: Jens Wiklander; +Cc: Sumit Garg, op-tee, Qihang
params_from_user() may acquire tee_shm references for MEMREF parameters
before failing after partially processing the supplied parameter array.
In tee_ioctl_supp_recv(), those references are currently not released on
that error path.
Fix this by freeing MEMREF references before returning when
params_from_user() fails.
Keep the final cleanup path in tee_ioctl_supp_recv() unchanged since
supp_recv() may consume and replace the supplied parameters, unlike the
other TEE ioctl callback paths.
Signed-off-by: Qihang <q.h.hack.winter@gmail.com>
---
v3:
- only free MEMREF references when params_from_user() fails
- keep tee_ioctl_supp_recv() final cleanup unchanged
- follow Jens' review on supp_recv() parameter ownership semantics
v2:
- rename helper to free_params()
- drop alloc_num_params and use num_params directly
drivers/tee/tee_core.c | 54 ++++++++++++++++++++----------------------
1 file changed, 26 insertions(+), 28 deletions(-)
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index ef9642d72672..2fd3a00b47c7 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -530,6 +530,21 @@ static int params_to_user(struct tee_ioctl_param __user *uparams,
return 0;
}
+static void free_params(struct tee_param *params, size_t num_params)
+{
+ size_t n;
+
+ if (!params)
+ return;
+
+ for (n = 0; n < num_params; n++)
+ if (tee_param_is_memref(params + n) &&
+ params[n].u.memref.shm)
+ tee_shm_put(params[n].u.memref.shm);
+
+ kfree(params);
+}
+
static int tee_ioctl_open_session(struct tee_context *ctx,
struct tee_ioctl_buf_data __user *ubuf)
{
@@ -595,16 +610,7 @@ static int tee_ioctl_open_session(struct tee_context *ctx,
*/
if (rc && have_session && ctx->teedev->desc->ops->close_session)
ctx->teedev->desc->ops->close_session(ctx, arg.session);
-
- if (params) {
- /* Decrease ref count for all valid shared memory pointers */
- for (n = 0; n < arg.num_params; n++)
- if (tee_param_is_memref(params + n) &&
- params[n].u.memref.shm)
- tee_shm_put(params[n].u.memref.shm);
- kfree(params);
- }
-
+ free_params(params, arg.num_params);
return rc;
}
@@ -657,14 +663,7 @@ static int tee_ioctl_invoke(struct tee_context *ctx,
}
rc = params_to_user(uparams, arg.num_params, params);
out:
- if (params) {
- /* Decrease ref count for all valid shared memory pointers */
- for (n = 0; n < arg.num_params; n++)
- if (tee_param_is_memref(params + n) &&
- params[n].u.memref.shm)
- tee_shm_put(params[n].u.memref.shm);
- kfree(params);
- }
+ free_params(params, arg.num_params);
return rc;
}
@@ -716,14 +715,7 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx,
}
rc = params_to_user(uparams, arg.num_params, params);
out:
- if (params) {
- /* Decrease ref count for all valid shared memory pointers */
- for (n = 0; n < arg.num_params; n++)
- if (tee_param_is_memref(params + n) &&
- params[n].u.memref.shm)
- tee_shm_put(params[n].u.memref.shm);
- kfree(params);
- }
+ free_params(params, arg.num_params);
return rc;
}
@@ -846,9 +838,15 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx,
return -ENOMEM;
rc = params_from_user(ctx, params, num_params, uarg->params);
- if (rc)
- goto out;
+ if (rc) {
+ free_params(params, num_params);
+ return rc;
+ }
+ /*
+ * supp_recv() may consume and replace the supplied parameters, so the
+ * final cleanup cannot use free_params() like the other ioctl paths.
+ */
rc = ctx->teedev->desc->ops->supp_recv(ctx, &func, &num_params, params);
if (rc)
goto out;
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v3] tee: fix params_from_user() error path in tee_ioctl_supp_recv
2026-05-07 9:45 ` [PATCH v3] tee: fix params_from_user() error path " Qihang
@ 2026-05-07 10:40 ` Jens Wiklander
2026-05-07 15:39 ` [PATCH v4] " Qihang
1 sibling, 0 replies; 13+ messages in thread
From: Jens Wiklander @ 2026-05-07 10:40 UTC (permalink / raw)
To: Qihang; +Cc: Sumit Garg, op-tee
Hi,
On Thu, May 7, 2026 at 11:46 AM Qihang <q.h.hack.winter@gmail.com> wrote:
>
> params_from_user() may acquire tee_shm references for MEMREF parameters
> before failing after partially processing the supplied parameter array.
>
> In tee_ioctl_supp_recv(), those references are currently not released on
> that error path.
>
> Fix this by freeing MEMREF references before returning when
> params_from_user() fails.
>
> Keep the final cleanup path in tee_ioctl_supp_recv() unchanged since
> supp_recv() may consume and replace the supplied parameters, unlike the
> other TEE ioctl callback paths.
>
> Signed-off-by: Qihang <q.h.hack.winter@gmail.com>
> ---
> v3:
> - only free MEMREF references when params_from_user() fails
> - keep tee_ioctl_supp_recv() final cleanup unchanged
> - follow Jens' review on supp_recv() parameter ownership semantics
>
> v2:
> - rename helper to free_params()
> - drop alloc_num_params and use num_params directly
>
> drivers/tee/tee_core.c | 54 ++++++++++++++++++++----------------------
> 1 file changed, 26 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> index ef9642d72672..2fd3a00b47c7 100644
> --- a/drivers/tee/tee_core.c
> +++ b/drivers/tee/tee_core.c
> @@ -530,6 +530,21 @@ static int params_to_user(struct tee_ioctl_param __user *uparams,
> return 0;
> }
>
> +static void free_params(struct tee_param *params, size_t num_params)
> +{
> + size_t n;
> +
> + if (!params)
> + return;
> +
> + for (n = 0; n < num_params; n++)
> + if (tee_param_is_memref(params + n) &&
> + params[n].u.memref.shm)
Please fold up. It fits on one line.
> + tee_shm_put(params[n].u.memref.shm);
> +
> + kfree(params);
> +}
> +
> static int tee_ioctl_open_session(struct tee_context *ctx,
> struct tee_ioctl_buf_data __user *ubuf)
> {
> @@ -595,16 +610,7 @@ static int tee_ioctl_open_session(struct tee_context *ctx,
> */
> if (rc && have_session && ctx->teedev->desc->ops->close_session)
> ctx->teedev->desc->ops->close_session(ctx, arg.session);
> -
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> -
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -657,14 +663,7 @@ static int tee_ioctl_invoke(struct tee_context *ctx,
> }
> rc = params_to_user(uparams, arg.num_params, params);
> out:
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -716,14 +715,7 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx,
> }
> rc = params_to_user(uparams, arg.num_params, params);
> out:
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -846,9 +838,15 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx,
> return -ENOMEM;
>
> rc = params_from_user(ctx, params, num_params, uarg->params);
> - if (rc)
> - goto out;
> + if (rc) {
> + free_params(params, num_params);
> + return rc;
> + }
>
> + /*
> + * supp_recv() may consume and replace the supplied parameters, so the
> + * final cleanup cannot use free_params() like the other ioctl paths.
> + */
> rc = ctx->teedev->desc->ops->supp_recv(ctx, &func, &num_params, params);
> if (rc)
> goto out;
> --
> 2.39.5 (Apple Git-154)
>
There are a few warnings:
AR drivers/base/firmware_loader/built-in.a
AR drivers/base/built-in.a
drivers/tee/tee_core.c: In function ‘tee_ioctl_open_session’:
drivers/tee/tee_core.c:552:16: warning: unused variable ‘n’ [-Wunused-variable]
552 | size_t n;
| ^
drivers/tee/tee_core.c: In function ‘tee_ioctl_invoke’:
drivers/tee/tee_core.c:622:16: warning: unused variable ‘n’ [-Wunused-variable]
622 | size_t n;
| ^
drivers/tee/tee_core.c: In function ‘tee_ioctl_object_invoke’:
drivers/tee/tee_core.c:676:16: warning: unused variable ‘n’ [-Wunused-variable]
676 | size_t n;
| ^
Cheers,
Jens
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v4] tee: fix params_from_user() error path in tee_ioctl_supp_recv
2026-05-07 9:45 ` [PATCH v3] tee: fix params_from_user() error path " Qihang
2026-05-07 10:40 ` Jens Wiklander
@ 2026-05-07 15:39 ` Qihang
2026-05-11 13:18 ` Jens Wiklander
1 sibling, 1 reply; 13+ messages in thread
From: Qihang @ 2026-05-07 15:39 UTC (permalink / raw)
To: Jens Wiklander; +Cc: Sumit Garg, op-tee, Qihang
params_from_user() may acquire tee_shm references for MEMREF parameters
before failing after partially processing the supplied parameter array.
In tee_ioctl_supp_recv(), those references are currently not released on
that error path.
Fix this by freeing MEMREF references before returning when
params_from_user() fails.
Keep the final cleanup path in tee_ioctl_supp_recv() unchanged since
supp_recv() may consume and replace the supplied parameters, unlike the
other TEE ioctl callback paths.
Signed-off-by: Qihang <q.h.hack.winter@gmail.com>
---
v4:
- fold free_params() memref check onto one line
- remove unused local variables left behind by the cleanup refactoring
v3:
- only free MEMREF references when params_from_user() fails
- keep tee_ioctl_supp_recv() final cleanup unchanged
- follow Jens' review on supp_recv() parameter ownership semantics
v2:
- rename helper to free_params()
- drop alloc_num_params and use num_params directly
drivers/tee/tee_core.c | 56 +++++++++++++++++++-----------------------
1 file changed, 25 insertions(+), 31 deletions(-)
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index ef9642d72672..1aac50c7c1de 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -530,11 +530,24 @@ static int params_to_user(struct tee_ioctl_param __user *uparams,
return 0;
}
+static void free_params(struct tee_param *params, size_t num_params)
+{
+ size_t n;
+
+ if (!params)
+ return;
+
+ for (n = 0; n < num_params; n++)
+ if (tee_param_is_memref(params + n) && params[n].u.memref.shm)
+ tee_shm_put(params[n].u.memref.shm);
+
+ kfree(params);
+}
+
static int tee_ioctl_open_session(struct tee_context *ctx,
struct tee_ioctl_buf_data __user *ubuf)
{
int rc;
- size_t n;
struct tee_ioctl_buf_data buf;
struct tee_ioctl_open_session_arg __user *uarg;
struct tee_ioctl_open_session_arg arg;
@@ -595,16 +608,7 @@ static int tee_ioctl_open_session(struct tee_context *ctx,
*/
if (rc && have_session && ctx->teedev->desc->ops->close_session)
ctx->teedev->desc->ops->close_session(ctx, arg.session);
-
- if (params) {
- /* Decrease ref count for all valid shared memory pointers */
- for (n = 0; n < arg.num_params; n++)
- if (tee_param_is_memref(params + n) &&
- params[n].u.memref.shm)
- tee_shm_put(params[n].u.memref.shm);
- kfree(params);
- }
-
+ free_params(params, arg.num_params);
return rc;
}
@@ -612,7 +616,6 @@ static int tee_ioctl_invoke(struct tee_context *ctx,
struct tee_ioctl_buf_data __user *ubuf)
{
int rc;
- size_t n;
struct tee_ioctl_buf_data buf;
struct tee_ioctl_invoke_arg __user *uarg;
struct tee_ioctl_invoke_arg arg;
@@ -657,14 +660,7 @@ static int tee_ioctl_invoke(struct tee_context *ctx,
}
rc = params_to_user(uparams, arg.num_params, params);
out:
- if (params) {
- /* Decrease ref count for all valid shared memory pointers */
- for (n = 0; n < arg.num_params; n++)
- if (tee_param_is_memref(params + n) &&
- params[n].u.memref.shm)
- tee_shm_put(params[n].u.memref.shm);
- kfree(params);
- }
+ free_params(params, arg.num_params);
return rc;
}
@@ -672,7 +668,6 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx,
struct tee_ioctl_buf_data __user *ubuf)
{
int rc;
- size_t n;
struct tee_ioctl_buf_data buf;
struct tee_ioctl_object_invoke_arg __user *uarg;
struct tee_ioctl_object_invoke_arg arg;
@@ -716,14 +711,7 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx,
}
rc = params_to_user(uparams, arg.num_params, params);
out:
- if (params) {
- /* Decrease ref count for all valid shared memory pointers */
- for (n = 0; n < arg.num_params; n++)
- if (tee_param_is_memref(params + n) &&
- params[n].u.memref.shm)
- tee_shm_put(params[n].u.memref.shm);
- kfree(params);
- }
+ free_params(params, arg.num_params);
return rc;
}
@@ -846,9 +834,15 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx,
return -ENOMEM;
rc = params_from_user(ctx, params, num_params, uarg->params);
- if (rc)
- goto out;
+ if (rc) {
+ free_params(params, num_params);
+ return rc;
+ }
+ /*
+ * supp_recv() may consume and replace the supplied parameters, so the
+ * final cleanup cannot use free_params() like the other ioctl paths.
+ */
rc = ctx->teedev->desc->ops->supp_recv(ctx, &func, &num_params, params);
if (rc)
goto out;
--
2.39.5 (Apple Git-154)
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v4] tee: fix params_from_user() error path in tee_ioctl_supp_recv
2026-05-07 15:39 ` [PATCH v4] " Qihang
@ 2026-05-11 13:18 ` Jens Wiklander
0 siblings, 0 replies; 13+ messages in thread
From: Jens Wiklander @ 2026-05-11 13:18 UTC (permalink / raw)
To: Qihang; +Cc: Sumit Garg, op-tee
Hi,
On Thu, May 7, 2026 at 5:39 PM Qihang <q.h.hack.winter@gmail.com> wrote:
>
> params_from_user() may acquire tee_shm references for MEMREF parameters
> before failing after partially processing the supplied parameter array.
>
> In tee_ioctl_supp_recv(), those references are currently not released on
> that error path.
>
> Fix this by freeing MEMREF references before returning when
> params_from_user() fails.
>
> Keep the final cleanup path in tee_ioctl_supp_recv() unchanged since
> supp_recv() may consume and replace the supplied parameters, unlike the
> other TEE ioctl callback paths.
>
> Signed-off-by: Qihang <q.h.hack.winter@gmail.com>
> ---
> v4:
> - fold free_params() memref check onto one line
> - remove unused local variables left behind by the cleanup refactoring
>
> v3:
> - only free MEMREF references when params_from_user() fails
> - keep tee_ioctl_supp_recv() final cleanup unchanged
> - follow Jens' review on supp_recv() parameter ownership semantics
>
> v2:
> - rename helper to free_params()
> - drop alloc_num_params and use num_params directly
>
> drivers/tee/tee_core.c | 56 +++++++++++++++++++-----------------------
> 1 file changed, 25 insertions(+), 31 deletions(-)
Looks good. I'm picking up this.
Cheers,
Jens
>
> diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> index ef9642d72672..1aac50c7c1de 100644
> --- a/drivers/tee/tee_core.c
> +++ b/drivers/tee/tee_core.c
> @@ -530,11 +530,24 @@ static int params_to_user(struct tee_ioctl_param __user *uparams,
> return 0;
> }
>
> +static void free_params(struct tee_param *params, size_t num_params)
> +{
> + size_t n;
> +
> + if (!params)
> + return;
> +
> + for (n = 0; n < num_params; n++)
> + if (tee_param_is_memref(params + n) && params[n].u.memref.shm)
> + tee_shm_put(params[n].u.memref.shm);
> +
> + kfree(params);
> +}
> +
> static int tee_ioctl_open_session(struct tee_context *ctx,
> struct tee_ioctl_buf_data __user *ubuf)
> {
> int rc;
> - size_t n;
> struct tee_ioctl_buf_data buf;
> struct tee_ioctl_open_session_arg __user *uarg;
> struct tee_ioctl_open_session_arg arg;
> @@ -595,16 +608,7 @@ static int tee_ioctl_open_session(struct tee_context *ctx,
> */
> if (rc && have_session && ctx->teedev->desc->ops->close_session)
> ctx->teedev->desc->ops->close_session(ctx, arg.session);
> -
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> -
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -612,7 +616,6 @@ static int tee_ioctl_invoke(struct tee_context *ctx,
> struct tee_ioctl_buf_data __user *ubuf)
> {
> int rc;
> - size_t n;
> struct tee_ioctl_buf_data buf;
> struct tee_ioctl_invoke_arg __user *uarg;
> struct tee_ioctl_invoke_arg arg;
> @@ -657,14 +660,7 @@ static int tee_ioctl_invoke(struct tee_context *ctx,
> }
> rc = params_to_user(uparams, arg.num_params, params);
> out:
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -672,7 +668,6 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx,
> struct tee_ioctl_buf_data __user *ubuf)
> {
> int rc;
> - size_t n;
> struct tee_ioctl_buf_data buf;
> struct tee_ioctl_object_invoke_arg __user *uarg;
> struct tee_ioctl_object_invoke_arg arg;
> @@ -716,14 +711,7 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx,
> }
> rc = params_to_user(uparams, arg.num_params, params);
> out:
> - if (params) {
> - /* Decrease ref count for all valid shared memory pointers */
> - for (n = 0; n < arg.num_params; n++)
> - if (tee_param_is_memref(params + n) &&
> - params[n].u.memref.shm)
> - tee_shm_put(params[n].u.memref.shm);
> - kfree(params);
> - }
> + free_params(params, arg.num_params);
> return rc;
> }
>
> @@ -846,9 +834,15 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx,
> return -ENOMEM;
>
> rc = params_from_user(ctx, params, num_params, uarg->params);
> - if (rc)
> - goto out;
> + if (rc) {
> + free_params(params, num_params);
> + return rc;
> + }
>
> + /*
> + * supp_recv() may consume and replace the supplied parameters, so the
> + * final cleanup cannot use free_params() like the other ioctl paths.
> + */
> rc = ctx->teedev->desc->ops->supp_recv(ctx, &func, &num_params, params);
> if (rc)
> goto out;
> --
> 2.39.5 (Apple Git-154)
>
^ permalink raw reply [flat|nested] 13+ messages in thread