lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAFA6WYOvMnvdhLvgOzLMyugRLPc62pHdJEGAhhwDJHRrVxCs1Q@mail.gmail.com>
Date: Mon, 25 Nov 2024 11:44:30 +0530
From: Sumit Garg <sumit.garg@...aro.org>
To: Amirreza Zarrabi <quic_azarrabi@...cinc.com>
Cc: Jens Wiklander <jens.wiklander@...aro.org>, op-tee@...ts.trustedfirmware.org, 
	linux-kernel@...r.kernel.org, linux-arm-msm@...r.kernel.org
Subject: Re: [PATCH RFC 3/3] tee: introduce orphan tee_shm and default context

On Mon, 25 Nov 2024 at 03:00, Amirreza Zarrabi
<quic_azarrabi@...cinc.com> wrote:
>
>
> Hi Sumit,
>
> Thank you so much for the comemnts :).
>
> On 11/23/2024 9:32 PM, Sumit Garg wrote:
> > Hi Amirreza,
> >
> > Thanks for proposing this.
> >
> > On Fri, 22 Nov 2024 at 06:38, Amirreza Zarrabi
> > <quic_azarrabi@...cinc.com> wrote:
> >>
> >>
> >> On 11/21/2024 11:08 PM, Jens Wiklander wrote:
> >>
> >> Hi Jens,
> >>
> >>> Hi Amirreza,
> >>>
> >>> On Thu, Nov 21, 2024 at 2:37 AM Amirreza Zarrabi
> >>> <quic_azarrabi@...cinc.com> wrote:
> >>>>
> >>>> The default context has a lifespan similar to the tee_device.
> >
> > Since it's associated with tee_device context, let's call it obvious
> > via renaming it as device context instead (s/def_ctx/dev_ctx/ in this
> > patch).
> >
>
> Make sense, I'll rename it.
>
> >>>> It is used as a context for shared memory if the context to which the
> >>>> shared memory belongs is released, making the tee_shm an orphan.
> >>>> This allows the driver implementing shm_unregister to safely make
> >>>> subsequent calls, such as to a supplicant if needed.
> >>>>
> >>>> It also enables users to free the shared memory while the driver is
> >>>> blocked on unregister_tee_device safely.
> >>>>
> >>>> Preferably, this should be used for all driver internal uses, using
> >>>> teedev_get_def_context rather than calling teedev_open.
> >
> > Makes sense to me.
> >
> >>>>
> >>>> Signed-off-by: Amirreza Zarrabi <quic_azarrabi@...cinc.com>
> >>>> ---
> >>>>  drivers/tee/optee/core.c    |  2 +-
> >>>>  drivers/tee/optee/ffa_abi.c |  2 +-
> >>>>  drivers/tee/optee/smc_abi.c |  2 +-
> >>>>  drivers/tee/tee_core.c      | 83 +++++++++++++++++++++++++++++----------------
> >>>>  drivers/tee/tee_private.h   |  3 --
> >>>>  drivers/tee/tee_shm.c       | 18 ++--------
> >>>>  include/linux/tee_core.h    | 15 ++++++++
> >>>>  include/linux/tee_drv.h     |  7 ----
> >>>>  8 files changed, 73 insertions(+), 59 deletions(-)
> >>>>
> >>>> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> >>>> index c75fddc83576..78d43d0c8014 100644
> >>>> --- a/drivers/tee/optee/core.c
> >>>> +++ b/drivers/tee/optee/core.c
> >>>> @@ -173,7 +173,7 @@ void optee_remove_common(struct optee *optee)
> >>>>
> >>>>         optee_notif_uninit(optee);
> >>>>         optee_shm_arg_cache_uninit(optee);
> >>>> -       teedev_close_context(optee->ctx);
> >>>> +
> >>>>         /*
> >>>>          * The two devices have to be unregistered before we can free the
> >>>>          * other resources.
> >>>> diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
> >>>> index f3af5666bb11..6ad94f0788ad 100644
> >>>> --- a/drivers/tee/optee/ffa_abi.c
> >>>> +++ b/drivers/tee/optee/ffa_abi.c
> >>>> @@ -949,7 +949,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
> >>>>         optee_shm_arg_cache_init(optee, arg_cache_flags);
> >>>>         mutex_init(&optee->rpmb_dev_mutex);
> >>>>         ffa_dev_set_drvdata(ffa_dev, optee);
> >>>> -       ctx = teedev_open(optee->teedev);
> >>>> +       ctx = teedev_get_def_context(optee->teedev);
> >>>>         if (IS_ERR(ctx)) {
> >>>>                 rc = PTR_ERR(ctx);
> >>>>                 goto err_rhashtable_free;
> >>>> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> >>>> index e9456e3e74cc..c77a3e631d04 100644
> >>>> --- a/drivers/tee/optee/smc_abi.c
> >>>> +++ b/drivers/tee/optee/smc_abi.c
> >>>> @@ -1722,7 +1722,7 @@ static int optee_probe(struct platform_device *pdev)
> >>>>         mutex_init(&optee->rpmb_dev_mutex);
> >>>>
> >>>>         platform_set_drvdata(pdev, optee);
> >>>> -       ctx = teedev_open(optee->teedev);
> >>>> +       ctx = teedev_get_def_context(optee->teedev);
> >>>>         if (IS_ERR(ctx)) {
> >>>>                 rc = PTR_ERR(ctx);
> >>>>                 goto err_supp_uninit;
> >>>> diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
> >>>> index 93f3b330aec8..805e1336089d 100644
> >>>> --- a/drivers/tee/tee_core.c
> >>>> +++ b/drivers/tee/tee_core.c
> >>>> @@ -57,7 +57,6 @@ struct tee_context *teedev_open(struct tee_device *teedev)
> >>>>                 goto err;
> >>>>         }
> >>>>
> >>>> -       kref_init(&ctx->refcount);
> >>>>         ctx->teedev = teedev;
> >>>>         INIT_LIST_HEAD(&ctx->list_shm);
> >>>>         rc = teedev->desc->ops->open(ctx);
> >>>> @@ -73,36 +72,43 @@ struct tee_context *teedev_open(struct tee_device *teedev)
> >>>>  }
> >>>>  EXPORT_SYMBOL_GPL(teedev_open);
> >>>>
> >>>> -void teedev_ctx_get(struct tee_context *ctx)
> >>>> +struct tee_context *teedev_get_def_context(struct tee_device *teedev)
> >>>>  {
> >>>> -       if (ctx->releasing)
> >>>> -               return;
> >>>> +       int rc;
> >>>> +       struct tee_context *ctx = &teedev->def_ctx;
> >>>>
> >>>> -       kref_get(&ctx->refcount);
> >>>> -}
> >>>> +       ctx->teedev = teedev;
> >>>> +       INIT_LIST_HEAD(&ctx->list_shm);
> >>>> +       rc = teedev->desc->ops->open(ctx);
> >>>> +       if (rc)
> >>>> +               return ERR_PTR(rc);
> >>>
> >>> I think ctx->teedev and ctx->list_shm must always be initialized or
> >>> &teedev->def_ctx can't be used in teedev_close_context().
> >>
> >> True, but &teedev->def_ctx is never used in teedev_close_context().
> >> The closing of the &teedev->def_ctx simply ignored. So once opened,
> >> &teedev->def_ctx will always remain open until the tee_device is alive.
> >>
> >>> We could initialize teedev->def_ctx on the first call to teedev_open()
> >>> on that tee_device. We need a way to tell the
> >>> teedev->desc->ops->open() to the backed driver that it's initializing
> >>> the default context though, or optee_open() can't handle the
> >>> tee-supplicant case properly.
> >>>
> >>
> >> That's a good point. This way, it is guaranteed that there is one def_ctx
> >> per teedev. There should be a way to tell the open() callback that it is
> >> a def_ctx, so it is not registered as a supplicant context.
> >>
> >>
> >>> Should we allow this function to be called more than once for each teedev?
> >>
> >> Yes, moving to teedev_open() will fix the issue.
> >>
> >>> Do we need serialization in this function if it's called after the
> >>> driver is probed?
> >>>
> >>
> >> True. I'll make sure there is no race.
> >>
> >>>>
> >>>> -static void teedev_ctx_release(struct kref *ref)
> >>>> -{
> >>>> -       struct tee_context *ctx = container_of(ref, struct tee_context,
> >>>> -                                              refcount);
> >>>> -       ctx->releasing = true;
> >>>> -       ctx->teedev->desc->ops->release(ctx);
> >>>> -       kfree(ctx);
> >>>> +       return ctx;
> >>>>  }
> >>>> +EXPORT_SYMBOL_GPL(teedev_get_def_context);
> >>>>
> >>>> -void teedev_ctx_put(struct tee_context *ctx)
> >>>> +void teedev_close_context(struct tee_context *ctx)
> >>>>  {
> >>>> -       if (ctx->releasing)
> >>>> +       struct tee_device *teedev = ctx->teedev;
> >>>> +       struct tee_shm *shm;
> >>>> +
> >>>> +       if (ctx == &teedev->def_ctx)
> >>>>                 return;
> >>>>
> >>>> -       kref_put(&ctx->refcount, teedev_ctx_release);
> >>>> -}
> >>>> +       teedev->desc->ops->release(ctx);
> >>>>
> >>>> -void teedev_close_context(struct tee_context *ctx)
> >>>> -{
> >>>> -       struct tee_device *teedev = ctx->teedev;
> >>>> +       mutex_lock(&teedev->mutex);
> >>>> +       list_for_each_entry(shm, &ctx->list_shm, link) {
> >>>> +               /* Context released. However, shm still holding a teedev reference.
> >>>> +                * Replace shm->ctx with the default context so that tee_shm_get_from_id()
> >>>> +                * fails (i.e. it is not accessible from userspace) but shm still
> >>>> +                * holds a valid context for further clean up, e.g. shm_unregister().
> >>>> +                */
> >>>
> >>> /*
> >>>  * Please format
> >>>  * multiline comments
> >>>  * like this. Please
> >>>  * keep the lines at
> >>>  * max 80 columns
> >>>  * here and at other
> >>>  * places in the patch-
> >>>  * set.
> >>>  */
> >>>
> >>
> >> Ack.
> >>
> >>>> +               shm->ctx = &teedev->def_ctx;
> >>>
> >>> shm->ctx will always point to a valid context, even if it is the
> >>> default context. It seems that we can always get hold of the correct
> >>> teedev via shm->ctx->teedev. Do we need "tee: revert removal of
> >>> redundant teedev in struct tee_shm"?
> >>>
> >>
> >> It was there in case we wanted to use NULL, but with def_ctx, it is not
> >> necessary. I am withdrawing that commit. :).
> >>
> >>> Shouldn't the shm be removed from the ctx->list_shm and be moved to
> >>> teedev->def_ctx.list_shm?
> >
> > +1
> >
>
> Ack.
>
> >>>
> >>
> >> Not really. If we put shm in the teedev->def_ctx.list_shm, by the time
> >> we are closing the def_ctx, the list is guaranteed to be empty.
> >>
> >> However, I understand it is cleaner and more consistent to do that rather
> >> than making changes to tee_shm_put().
> >>
> >> I'll do it.
> >>
> >>>> +       }
> >>>> +       mutex_unlock(&teedev->mutex);
> >>>>
> >>>> -       teedev_ctx_put(ctx);
> >>>> +       kfree(ctx);
> >>>>         tee_device_put(teedev);
> >>>>  }
> >>>>  EXPORT_SYMBOL_GPL(teedev_close_context);
> >>>> @@ -946,6 +952,8 @@ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc,
> >>>>
> >>>>         teedev->desc = teedesc;
> >>>>         teedev->pool = pool;
> >>>> +       /* Only open default context when teedev_get_def_context() called. */
> >>>> +       teedev->def_ctx.teedev = NULL;
> >
> > Why don't you open the device context here only? This will associate
> > it automatically with teedev lifespan and then
> > teedev_get_def_context() will just return a reference to that.
> >
> > -Sumit
> >
>
> So my assumption is that the tee_devic_alloc() is called as part of
> the driver initialization; there is no guarantee that at this time the
> driver is actually ready to accept any open() callback.
>

The drivers should be able to handle open() callback since we already
check for !teedesc->ops->open in the beginning of tee_devic_alloc().
Also, we need to open a device context for !TEE_DESC_PRIVILEGED such
that we don't open a supplicant device context there.

-Sumit

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ