Re: [PATCH 12/14] media: medkatek: vcodec: set secure mode to decoder driver

From: Jeffrey Kardatzke
Date: Wed Sep 27 2023 - 14:31:14 EST


Sounds great Hans! I'll work with Mediatek to update their code for that.

On Wed, Sep 27, 2023 at 12:26 AM Hans Verkuil <hverkuil-cisco@xxxxxxxxx> wrote:
>
> On 26/09/2023 22:59, Jeffrey Kardatzke wrote:
> > Hans,
> >
> > I've been looking through the v4l2/vbuf2 code to get an idea of the
> > details for implementing a new memory type for secure buffers. What
> > it comes down to essentially is that it would behave just like
> > V4L2_MEMORY_DMABUF, but then there would be an extra check in
> > __prepare_dmabuf (in videobuf2-core.c) when the memory type is SECURE
> > to ensure that it is actually from a secure dma-buf allocation. So
> > I'm thinking an alternate solution might be cleaner so we don't have
> > two memory types that are handled nearly identically in most of the
> > code. What do you think about a new memory flag like
> > V4L2_MEMORY_FLAG_SECURE? This would be set in vb2_queue struct like
> > the other existing memory flag. Then when it gets into
> > __prepare_dmabuf and invokes attach_dmabuf on each buffer...that call
> > could then check for the existence of that flag, and if it's there it
> > could validate it is actually secure memory. Then in various other
> > dmabuf vb2_mem_ops (maybe alloc, get_userptr, vaddr and mmap) those
> > could also check for the secure flag, and if present return an
> > error/null. Then also in the driver specific vb2_ops for queue_setup,
> > the MTK driver could recognize the flag there and then configure
> > itself for secure mode.
> >
> > How does that sound as an overall strategy?
>
> Yes, I actually had the same thought.
>
> You would also need a new capability: V4L2_BUF_CAP_SUPPORTS_SECURE_MEMORY
>
> It makes more sense than creating a new V4L2_MEMORY_ type, and it still
> is handled at the right place (creating the buffers).
>
> Regards,
>
> Hans
>
> >
> > Cheers,
> > Jeff
> >
> > On Mon, Sep 25, 2023 at 9:51 AM Jeffrey Kardatzke <jkardatzke@xxxxxxxxxx> wrote:
> >>
> >> On Mon, Sep 25, 2023 at 2:00 AM Hans Verkuil <hverkuil-cisco@xxxxxxxxx> wrote:
> >>>
> >>> On 22/09/2023 21:17, Jeffrey Kardatzke wrote:
> >>>> On Fri, Sep 22, 2023 at 1:44 AM Hans Verkuil <hverkuil-cisco@xxxxxxxxx> wrote:
> >>>>>
> >>>>> On 22/09/2023 05:28, Yunfei Dong (董云飞) wrote:
> >>>>>> Hi Hans,
> >>>>>>
> >>>>>> Thanks for your help to give some good advice.
> >>>>>> On Wed, 2023-09-20 at 09:20 +0200, Hans Verkuil wrote:
> >>>>>>>
> >>>>>>>>>>> In any case, using a control to switch to secure mode and using
> >>>>>>> a control
> >>>>>>>>>>> to convert a dmabuf fd to a secure handle seems a poor choice to
> >>>>>>> me.
> >>>>>>>>>>>
> >>>>>>>>>>> I was wondering if it wouldn't be better to create a new
> >>>>>>> V4L2_MEMORY_ type,
> >>>>>>>>>>> e.g. V4L2_MEMORY_DMABUF_SECURE (or perhaps _DMABUF_OPTEE). That
> >>>>>>> ensures that
> >>>>>>>>>>> once you create buffers for the first time, the driver can
> >>>>>>> switch into secure
> >>>>>>>>>>> mode, and until all buffers are released again you know that the
> >>>>>>> driver will
> >>>>>>>>>>> stay in secure mode.
> >>>>>>>>>>
> >>>>>>>>>> Why do you think the control for setting secure mode is a poor
> >>>>>>> choice?
> >>>>>>>>>> There's various places in the driver code where functionality
> >>>>>>> changes
> >>>>>>>>>> based on being secure/non-secure mode, so this is very much a
> >>>>>>> 'global'
> >>>>>>>>>> setting for the driver. It could be inferred based off a new
> >>>>>>> memory
> >>>>>>>>>> type for the queues...which then sets that flag in the driver;
> >>>>>>> but
> >>>>>>>>>> that seems like it would be more fragile and would require
> >>>>>>> checking
> >>>>>>>>>> for incompatible output/capture memory types. I'm not against
> >>>>>>> another
> >>>>>>>>>> way of doing this; but didn't see why you think the proposed
> >>>>>>> method is
> >>>>>>>>>> a poor choice.
> >>>>>>>>>
> >>>>>>>>> I assume you are either decoding to secure memory all the time, or
> >>>>>>> not
> >>>>>>>>> at all. That's something you would want to select the moment you
> >>>>>>> allocate
> >>>>>>>>> the first buffer. Using the V4L2_MEMORY_ value would be the
> >>>>>>> natural place
> >>>>>>>>> for that. A control can typically be toggled at any time, and it
> >>>>>>> makes
> >>>>>>>>> no sense to do that for secure streaming.
> >>>>>>>>>
> >>>>>>>>> Related to that: if you pass a dmabuf fd you will need to check
> >>>>>>> somewhere
> >>>>>>>>> if the fd points to secure memory or not. You don't want to mix
> >>>>>>> the two
> >>>>>>>>> but you want to check that at VIDIOC_QBUF time.
> >>>>>>>>>
> >>>>>>>>> Note that the V4L2_MEMORY_ value is already checked in the v4l2
> >>>>>>> core,
> >>>>>>>>> drivers do not need to do that.
> >>>>>>>>
> >>>>>>>> Just to clarify a bit, and make sure I understand this too. You are
> >>>>>>> proposing to
> >>>>>>>> introduce something like:
> >>>>>>>>
> >>>>>>>> V4L2_MEMORY_SECURE_DMABUF
> >>>>>>>>
> >>>>>>>> Which like V4L2_MEMORY_DMABUF is meant to import dmabuf, while
> >>>>>>> telling the
> >>>>>>>> driver that the memory is secure according to the definition of
> >>>>>>> "secure" for the
> >>>>>>>> platform its running on.
> >>>>>>>>
> >>>>>>>> This drivers also allocate secure SHM (a standard tee concept) and
> >>>>>>> have internal
> >>>>>>>> allocation for reconstruction buffer and some hw specific reference
> >>>>>>> metadata. So
> >>>>>>>> the idea would be that it would keep allocation using the dmabuf
> >>>>>>> heap internal
> >>>>>>>> APIs ? And decide which type of memory based on the memory type
> >>>>>>> found in the
> >>>>>>>> queue?
> >>>>>>>
> >>>>>>> Yes. Once you request the first buffer you basically tell the driver
> >>>>>>> whether it
> >>>>>>> will operate in secure or non-secure mode, and that stays that way
> >>>>>>> until all
> >>>>>>> buffers are freed. I think that makes sense.
> >>>>>>>
> >>>>>>
> >>>>>> According to iommu's information, the dma operation for secure and non-
> >>>>>> secure are the same, whether just need to add one memory type in v4l2
> >>>>>> framework the same as V4L2_MEMORY_DMABUF? The dma operation in
> >>>>>> videobuf2-dma-contig.c can use the same functions.
> >>>>>
> >>>>> So if I pass a non-secure dma fd to the capture queue of the codec, who
> >>>>> will check that it can't write the data to that fd? Since doing so would
> >>>>> expose the video. Presumably at some point the tee code will prevent that?
> >>>>> (I sincerely hope so!)
> >>>>
> >>>> It is entirely the job of the TEE to prevent this. Nothing in the
> >>>> kernel should allow exploitation of what happens in the TEE no matter
> >>>> what goes on in the kernel
> >>>>
> >>>>>
> >>>>> Having a separate V4L2_MEMORY_DMABUF_SECURE type is to indicate to the
> >>>>> driver that 1) it can expect secure dmabuf fds, 2) it can configure itself
> >>>>> for that (that avoids using a control to toggle between normal and secure mode),
> >>>>> and at VIDIOC_QBUF time it is easy for the V4L2 core to verify that the
> >>>>> fd that is passed in is for secure memory. This means that mistakes by
> >>>>> userspace are caught at QBUF time.
> >>>>>
> >>>>> Of course, this will not protect you (people can disable this check by
> >>>>> recompiling the kernel), that still has to be done by the firmware, but
> >>>>> it catches userspace errors early on.
> >>>>>
> >>>>> Also, while for this hardware the DMA operation is the same, that might
> >>>>> not be the case for other hardware.
> >>>>
> >>>> That's a really good point. So one of the other models that is used
> >>>> for secure video decoding is to send the encrypted buffer into the
> >>>> video decoder directly (i.e. V4L2_MEMORY_MMAP) and then also send in
> >>>> all the corresponding crypto parameters (i.e. algorithm, IV,
> >>>> encryption pattern, etc.). Then the video driver internally does the
> >>>> decryption and decode in one operation. That's not what we want to
> >>>> use here for Mediatek; but I've done other integrations that work that
> >>>> way (that was for VAAPI [1], not V4L2...but there are other ARM
> >>>> implementations that do operate that way). So if we end up requiring
> >>>> V4L2_MEMORY_DMABUF_SECURE to indicate secure mode and enforce it on
> >>>> output+capture, that'll close off other potential solutions in the
> >>>> future.
> >>>>
> >>>> Expanding on your point about DMA operations being different on
> >>>> various hardware, that also makes me think a general check for this in
> >>>> v4l2 code may also be limiting. There are various ways secure video
> >>>> pipelines are done, so leaving these checks up to the individual
> >>>> drivers that implement secure video decode may be more pragmatic. If
> >>>> there's a generic V4L2 _CID_SECURE_MODE control, that makes it more
> >>>> general for how drivers can handle secure video decode.
> >>>
> >>> No, using a control for this is really wrong.
> >>>
> >>> The reason why I want it as a separate memory type is that that is
> >>> what you use when you call VIDIOC_REQBUFS, and that ioctl is also
> >>> when things are locked down in a driver. As long as no buffers have
> >>> been allocated, you can still change formats, parameters, etc. But
> >>> once buffers are allocated, most of that can't be changed, since
> >>> changing e.g. the format would also change the buffer sizes.
> >>>
> >>> It also locks down who owns the buffers by storing the file descriptor.
> >>> This prevents other processes from hijacking the I/O streaming, only
> >>> the owner can stream buffers.
> >>>
> >>> So it is a natural point in the sequence for selecting secure
> >>> buffers.
> >>>
> >>> If you request V4L2_MEMORY_DMABUF_SECURE for the output, then the
> >>> capture side must also use DMABUF_SECURE. Whether or not you can
> >>> use regular DMABUF for the output side and select DMABUF_SECURE
> >>> on the capture side is a driver decision. It can be useful to
> >>> support this for testing the secure capture using regular video
> >>> streams (something Nicolas discussed as well), but it depends on
> >>> the hardware whether you can use that technique.
> >>
> >> OK, that does work for the additional cases I mentioned. And for
> >> testing...we would still want to use DMABUF_SECURE on both ends for
> >> Mediatek at least (that's the only way they support it). But rather
> >> than having to bother with a clearkey implementation...we can just do
> >> something that directly copies compressed video into the secure
> >> dmabufs and then exercises the whole pipeline from there. This same
> >> thing happens with the 'clear lead' that is sometimes there with
> >> encrypted video (where the first X seconds are unencrypted and then it
> >> switches to encrypted...but you're still using the secure video
> >> pipeline on the unencrypted frames in that case).
> >>
> >>
> >>>
> >>> Regards,
> >>>
> >>> Hans
> >>>
> >>>>
> >>>> [1] - https://github.com/intel/libva/blob/master/va/va.h#L2177
> >>>>
> >>>>>
> >>>>> Regards,
> >>>>>
> >>>>> Hans
> >>>>>
> >>>>>>
> >>>>>> Best Regards,
> >>>>>> Yunfei Dong
> >>>>>>
> >>>>>
> >>>
>