Re: [PATCH 25/26] media: Implement best effort media device removal safety sans refcounting

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 13/03/2023 17:53, Sakari Ailus wrote:
> Hi Hans,
> 
> On Mon, Mar 13, 2023 at 03:39:25PM +0100, Hans Verkuil wrote:
>> On 13/03/2023 15:02, Sakari Ailus wrote:
>>> Hi Hans,
>>>
>>> On Mon, Mar 13, 2023 at 02:46:27PM +0100, Hans Verkuil wrote:
>>>> On 03/03/2023 12:08, Sakari Ailus wrote:
>>>>> Hi Hans,
>>>>>
>>>>> On Fri, Mar 03, 2023 at 09:54:40AM +0100, Hans Verkuil wrote:
>>>>>> On 03/03/2023 09:39, Hans Verkuil wrote:
>>>>>>> On 01/02/2023 22:45, Sakari Ailus wrote:
>>>>>>>> Add a new helper data structure media_devnode_compat_ref, which is used to
>>>>>>>> prevent user space from calling IOCTLs or other system calls to the media
>>>>>>>> device that has been already unregistered.
>>>>>>>>
>>>>>>>> The media device's memory may of course still be released during the call
>>>>>>>> but there is only so much that can be done to this without the driver
>>>>>>>> managing the lifetime of the resources it needs somehow.
>>>>>>>>
>>>>>>>> This patch should be reverted once all drivers have been converted to manage
>>>>>>>> their resources' lifetime.
>>>>>>>>
>>>>>>>> Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx>
>>>>>>>> ---
>>>>>>>>  drivers/media/mc/mc-device.c  | 60 ++++++++++++++++++++++++++++++-----
>>>>>>>>  drivers/media/mc/mc-devnode.c | 21 ++++++++----
>>>>>>>>  include/media/media-devnode.h | 29 +++++++++++++++++
>>>>>>>>  3 files changed, 96 insertions(+), 14 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/media/mc/mc-device.c b/drivers/media/mc/mc-device.c
>>>>>>>> index 3a1db5fdbba7..22fdaa6370ea 100644
>>>>>>>> --- a/drivers/media/mc/mc-device.c
>>>>>>>> +++ b/drivers/media/mc/mc-device.c
>>>>>>>> @@ -45,18 +45,34 @@ static inline void __user *media_get_uptr(__u64 arg)
>>>>>>>>  	return (void __user *)(uintptr_t)arg;
>>>>>>>>  }
>>>>>>>>  
>>>>>>>> +static void compat_ref_release(struct kref *kref)
>>>>>>>> +{
>>>>>>>> +	struct media_devnode_compat_ref *ref =
>>>>>>>> +		container_of_const(kref, struct media_devnode_compat_ref, kref);
>>>>>>>> +
>>>>>>>> +	kfree(ref);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>  static int media_device_open(struct media_devnode *devnode, struct file *filp)
>>>>>>>>  {
>>>>>>>>  	struct media_device *mdev = to_media_device(devnode);
>>>>>>>>  	struct media_device_fh *fh;
>>>>>>>>  	unsigned long flags;
>>>>>>>>  
>>>>>>>> +	if (devnode->ref && (!atomic_read(&devnode->ref->registered) ||
>>>>>>>> +			     !kref_get_unless_zero(&devnode->ref->kref)))
>>>>>>>> +		return -ENXIO;
>>>>>>>> +
>>>>>>>
>>>>>>> This seems pointless: if the media device is unregistered, then the device
>>>>>>> node disappears and it can't be opened anymore.
>>>>>>>
>>>>>>> I'm confused by this patch in general: when media_device_unregister() is called,
>>>>>>> it is no longer possible to call ioctls and basically do anything except close
>>>>>>> the open fh.
>>>>>>>
>>>>>>> So what am I missing here? It all looks odd.
>>>>>>
>>>>>> I read up on this a bit more, and I think this patch is bogus: drivers not
>>>>>> converted to the release() callback will indeed just crash, but that's no
>>>>>> different than many existing drivers, media or otherwise, when you forcibly
>>>>>> unbind them. It's broken today, and since you have to be root to unbind, I
>>>>>> would say that we can just leave it as-is rather than introducing a rather
>>>>>> ugly workaround. I don't think it will help anyway, since most likely
>>>>>> such drivers will also fails if the application has a video device open
>>>>>> when the device is unbound.
>>>>>
>>>>> The main difference is whether accessing such a file handle will access
>>>>> released memory always or whether that is possible only during a very brief
>>>>> amount of time.
>>>>>
>>>>
>>>> I still don't like this. It was broken before, and it is broken now (perhaps a
>>>> bit less broken, but still...).
>>>>
>>>> There is a right fix now, and drivers that are likely to be removed forcibly
>>>> should be converted. This patch just makes it more likely that such drivers
>>>> won't be converted since it is less likely to hit this, so people will just
>>>> think that this is 'good enough'. And it makes the code a lot uglier.
>>>
>>> I agree, although converting the drivers is easier said than done. Note
>>> that also DVB is affected by this, not just V4L2. There are quite a few DVB
>>> USB devices.
>>>
>>> The behaviour before this set (since ~ 2017) is restored by the last few
>>> patches, without these we're on pre-2017 behaviour which basically means
>>> that all media IOCTLs on file handles the device of which is gone, will
>>> always access released memory. That was quite bad, too.
>>
>> Why?
>>
>> I have a filehandle open on /dev/mediaX. Now I unbind the device. That will
>> unregister the media device, which will cause all file ops on the filehandle
>> to return immediately, except for close().
>>
>> And close() just frees the devnode from what I can see.
>>
>> There is a race if the device is unbound while in an ioctl, then all bets are
>> off without proper life-time management.
>>
>> If it crashes after an unbind in the close() call, then something else is
>> wrong, it shouldn't do that.
>>
>> What happens if you do 'sleep 20 </dev/mediaX', then unbind the device?
>>
>> I feel that I am missing something here.
> 
> Actually these seems to be a bug in the 25th patch --- testing the devnode
> registration needs to take place before checking for fops.
> 
> After fixing that, the difference of issuing read(2) after unregistering
> the device is between (probably) crashing and graciously failing. The
> underlying problem is that without the 25th patch there pretty much is a
> guarantee devnode has been released by the time it is accessed.

Ah, it's a result of patch 06/26. Now devnode is embedded in struct media_device,
which in turn is embedded in a device's state structure. And when that is freed,
the devnode is also freed.

This is wrong IMHO: either struct media_devnode or struct media_device has to
be dynamically allocated. Embedding devices in a larger state structure causes
exactly these types of problems.

In this case I would just keep dynamically allocating the devnode. What is the reason
for reverting that patch? The commit log doesn't say.

Regards,

	Hans



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux