HI Ilias,

On Mon, Oct 19, 2026 at 10:35 AM Ilias Apalodimas
<[email protected]> wrote:
>
> Hi Igor,
>
> On Mon, 12 Oct 2026 at 22:56, Igor Opaniuk
> <[email protected]> wrote:
> >
> > The supplicant switched the eMMC to the RPMB hardware partition when the
> > device was first used and only switched back when the OP-TEE session was
> > released. Between two RPMB requests other users of the same device switch
> > it back to the user area: libavb does so for every partition read while
> > verifying a chain, and the Android bootmeth reads boot/vendor_boot right
> > after verification.
> >
> > With RPMB left selected those reads hit the RPMB partition, and the next
> > RPMB frames were routed to whatever partition the other user left
> > selected, which ends in status timeouts and I/O errors (seen with
> > the AVB TA on QEMU's emulated eMMC).
> >
> > Select the RPMB partition around every data request and restore the
> > previously selected partition afterwards.
>
> Overall this seems correct, a few comments below.
>
> [...]
>
> > +/*
> > + * The RPMB hardware partition is selected for the duration of a single
> > + * request only. Between two requests other users of the same eMMC, for
> > + * instance libavb reading the user area while verifying a chain of
> > + * partitions, switch the device back to the user area. Keeping RPMB
> > + * selected across requests would make those reads, and the following RPMB
> > + * frames, hit the wrong partition.
> > + */
> > +static int select_rpmb_part(struct optee_private *priv)
> > +{
> > +       int rc;
> > +
> > +       priv->rpmb_original_part = mmc_get_blk_desc(priv->rpmb_mmc)->hwpart;
> > +       rc = blk_select_hwpart_devnum(UCLASS_MMC, priv->rpmb_dev_id,
> > +                                     MMC_PART_RPMB);
> > +       if (rc)
> > +               debug("Device id %d: cannot select RPMB partition: %d\n",
> > +                     priv->rpmb_dev_id, rc);
> > +
> > +       return rc;
> > +}
> > +
> > +static void restore_part(struct optee_private *priv)
> > +{
> > +       int rc;
> > +
> > +       rc = blk_select_hwpart_devnum(UCLASS_MMC, priv->rpmb_dev_id,
> > +                                     priv->rpmb_original_part);
> > +       if (rc)
> > +               debug("%s: blk_select_hwpart_devnum() failed: %d\n",
> > +                     __func__, rc);
> > +}
> > +
> >  static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
> >  {
> >         struct mmc *mmc = find_mmc_device(dev_id);
> > @@ -130,6 +146,7 @@ static u32 rpmb_process_request(struct optee_private 
> > *priv, void *req,
> >  {
> >         struct rpmb_req *sreq = req;
> >         struct mmc *mmc;
> > +       int rc;
> >
> >         if (req_size < sizeof(*sreq))
> >                 return TEE_ERROR_BAD_PARAMETERS;
> > @@ -139,9 +156,13 @@ static u32 rpmb_process_request(struct optee_private 
> > *priv, void *req,
> >                 mmc = get_mmc(priv, sreq->dev_id);
>
> get_mmc already selects rpmb_original_part, which we now always overwrite.
>
> Cant we fold in select_rpmb_part() into get_mmc?

Right, that assignment in get_mmc() is a leftover from when it also
switched to RPMB;

Folded the fix in for v3


>
> >                 if (!mmc)
> >                         return TEE_ERROR_ITEM_NOT_FOUND;
> > -               if (mmc_rpmb_route_frames(mmc, RPMB_REQ_DATA(req),
> > -                                         req_size - sizeof(struct 
> > rpmb_req),
> > -                                         rsp, rsp_size))
> > +               if (select_rpmb_part(priv))
> > +                       return TEE_ERROR_ITEM_NOT_FOUND;
> > +               rc = mmc_rpmb_route_frames(mmc, RPMB_REQ_DATA(req),
> > +                                          req_size - sizeof(struct 
> > rpmb_req),
> > +                                          rsp, rsp_size);
> > +               restore_part(priv);
> > +               if (rc)
> >                         return TEE_ERROR_BAD_PARAMETERS;
> >                 return TEE_SUCCESS;
> >
> >
> > --
> > 2.53.0
> >
>
> Thanks
> /Ilias

Reply via email to