[REPORT] tee: tee_ioctl_supp_recv() missing tee_shm_put() cleanup for memref params

Qihang <[email protected]> Wed, 29 Apr 2026 11:07:22 +0800
Newsgroups org.trustedfirmware.lists.op-tee
Message-ID <CAH78Gvtd_reUt1mCasR=grZuLWWHcn4-ox3bXWXNEvbTOV3UGA@mail.gmail.com>
Hi,

I would like to report a likely shared-memory reference leak in
drivers/tee/tee_core.c, in tee_ioctl_supp_recv().

The issue is that tee_ioctl_supp_recv() calls params_from_user(), which
acquires references for MEMREF-type parameters via tee_shm_get_from_id(),
but the cleanup path only frees the params array and does not drop the
acquired shm references.

Relevant code in tee_ioctl_supp_recv():

  rc = params_from_user(ctx, params, num_params, uarg->params);
  if (rc)
          goto out;

  rc = ctx->teedev->desc->ops->supp_recv(ctx, &func, &num_params, params);
  if (rc)
          goto out;
  ...
out:
  kfree(params);
  return rc;

By contrast, other callers of params_from_user() in tee_core.c do release
MEMREF references on cleanup, for example:
- tee_ioctl_open_session()
- tee_ioctl_invoke()
- tee_ioctl_object_invoke()

The helper comment in param_from_user_memref() also states that the caller
is responsible for calling tee_shm_put() on all resolved pointers.

Reachability / trigger paths:

1. qcomtee backend:
   qcomtee registers .supp_recv = qcomtee_supp_recv on a non-privileged
   tee device path. qcomtee_supp_recv() rejects any non-meta parameter
   after the first one:
     for (i = 1; i < *num_params; i++)
             if (params[i].attr)
                     return -EINVAL;
   This allows a path where params_from_user() has already acquired a shm
   reference for a MEMREF parameter, then qcomtee_supp_recv() returns an
   error, and tee_ioctl_supp_recv() exits without tee_shm_put().

2. Partial failure before backend callback:
   if params_from_user() successfully resolves an earlier MEMREF parameter
   and then fails on a later parameter, tee_ioctl_supp_recv() still goes
   to the same cleanup path without dropping already acquired shm refs.

This means the issue is not just a backend-specific quirk: the core ioctl
cleanup path itself is missing tee_shm_put() handling.

Impact:
- leaked shared-memory references
- shared-memory objects may remain pinned and never reach final release
- repeated triggering can cause resource exhaustion / DoS

This does not appear to be a UAF, since refcount_t saturation prevents
wraparound. The impact looks limited to resource leakage and availability.

If useful, I can also prepare a patch.

Thanks,
Qihang