From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Nicola Fiorillo <nicfio@gmail.com>
Cc: Sakari Ailus <sakari.ailus@linux.intel.com>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Hans Verkuil <hverkuil@kernel.org>,
Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com>,
linux-media@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 1/2] media: v4l2-subdev: Fix NULL pointer dereference in subdev_open()
Date: Thu, 8 Oct 2026 07:48:42 +0200 [thread overview]
Message-ID: <20261008054842.GB683793@killaraus.ideasonboard.com> (raw)
In-Reply-To: <20261008042600.275884-2-nicfio@gmail.com>
On Thu, Oct 08, 2026 at 06:25:59AM +0200, Nicola Fiorillo wrote:
> Unbinding a driver while something opens a /dev/v4l-subdevN node oopses
> the kernel:
>
> BUG: kernel NULL pointer dereference, address: 0000000000000008
> RIP: 0010:subdev_open+0x8a/0x190 [videodev]
> Call Trace:
> v4l2_open+0xa9/0x100 [videodev]
> chrdev_open+0xb2/0x230
> do_dentry_open+0x14c/0x440
> vfs_open+0x2e/0xe0
> path_openat+0x82e/0x12d0
> do_filp_open+0xc4/0x170
> do_sys_openat2+0xae/0xe0
> __x64_sys_openat+0x55/0xa0
>
> v4l2_device_unregister_subdev() clears sd->v4l2_dev, then unregisters
> the media entity, which clears sd->entity.graph_obj.mdev, and only then
> unregisters the device node. Drivers that call media_device_unregister()
> before v4l2_device_unregister(), as vimc does, clear
> sd->entity.graph_obj.mdev even earlier, while the sub-device nodes are
> still registered. subdev_open() dereferences both pointers. v4l2_open()
> has checked that the node is registered, but it drops videodev_lock
> before calling fops->open(), so the whole unregistration can run in
> between. Reordering v4l2_device_unregister_subdev() would not help in
> the second case, and checking the two pointers in subdev_open() would
> only narrow the window.
>
> Neither pointer is needed in subdev_open(). Both record that the
> sub-device is registered, and are cleared on purpose when it goes away,
> while open() runs on behalf of the device node. The node has its own
> pointer to the same v4l2_device, vdev->v4l2_dev, which is set when the
> node is registered and never cleared, and the V4L2 core already relies
> on it for as long as the node exists: v4l2_release() dereferences it on
> every close. The sub-device's entity is registered with
> vdev->v4l2_dev->mdev, so that is also the media device to take the
> module reference through.
>
> That reference goes through mdev->dev->driver, which the driver core
> clears once the media device's own driver has been unbound, as when
> syzbot unbinds vimc. Read it once with READ_ONCE(), as
> dev_driver_string() does, and fail the open with -ENODEV if it is gone:
> unbinding does not unload the module, so the pointer read is either
> still valid or NULL.
>
> With this, subdev_open() no longer reads a pointer that the V4L2 core or
> the driver core clears when a driver is unbound. It can still run on a
> sub-device that has just been unregistered, exactly like a file handle
> opened an instant earlier. The lifetime of the sub-device and of the
> media device when a driver goes away with file handles open, and module
> unloading, are a separate, known limitation that this does not address.
>
> Reproduced on a CHUWI Hi10 X1 (Alder Lake-N, IPU6) running 6.12.86, at
We don't develop or test patcheson 6.12.86.
> cycle 7 of a loop unbinding and rebinding a sensor while four processes
> opened every /dev/v4l-subdev*. syzbot hit the second dereference on the
> same line by unbinding vimc, and so does a test in QEMU with KASAN that
> opens vimc's sub-device nodes while vimc is unbound and rebound; with
> this patch the same test shows no oops, KASAN report or warning.
>
> Reported-by: syzbot+74de6401dbdd377b5746@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=74de6401dbdd377b5746
> Fixes: 61f5db549dde ("[media] v4l: Make v4l2_subdev inherit from media_entity")
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
> Signed-off-by: Nicola Fiorillo <nicfio@gmail.com>
> ---
> drivers/media/v4l2-core/v4l2-subdev.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
> index a07d77e58..c56ca328f 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -96,6 +96,7 @@ static int subdev_open(struct file *file)
> {
> struct video_device *vdev = video_devdata(file);
> struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
> + struct media_device *mdev = vdev->v4l2_dev->mdev;
> struct v4l2_subdev_fh *subdev_fh;
> int ret;
>
> @@ -112,10 +113,17 @@ static int subdev_open(struct file *file)
> v4l2_fh_init(&subdev_fh->vfh, vdev);
> v4l2_fh_add(&subdev_fh->vfh, file);
>
> - if (sd->v4l2_dev->mdev && sd->entity.graph_obj.mdev->dev) {
> + if (mdev && mdev->dev) {
> + struct device_driver *drv = READ_ONCE(mdev->dev->driver);
> struct module *owner;
>
> - owner = sd->entity.graph_obj.mdev->dev->driver->owner;
> + /* The media device's driver has been unbound meanwhile. */
> + if (!drv) {
> + ret = -ENODEV;
> + goto err;
> + }
> +
> + owner = drv->owner;
All of this is a hack that may reduce a race window but it doesn't fix
the problem.
> if (!try_module_get(owner)) {
> ret = -EBUSY;
> goto err;
--
Regards,
Laurent Pinchart
next prev parent reply other threads:[~2026-10-08 5:48 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-08 4:25 [PATCH v3 0/2] media: v4l2-subdev: Fix NULL dereferences racing with unbind Nicola Fiorillo
2026-10-08 4:25 ` [PATCH v3 1/2] media: v4l2-subdev: Fix NULL pointer dereference in subdev_open() Nicola Fiorillo
2026-10-08 5:48 ` Laurent Pinchart [this message]
2026-10-08 7:06 ` Nicola Fiorillo
2026-10-08 4:26 ` [PATCH v3 2/2] media: v4l2-subdev: Fix NULL pointer dereference in the EXT_CTRLS ioctls Nicola Fiorillo
2026-10-08 10:44 ` Sakari Ailus
2026-10-08 13:55 ` Nicola Fiorillo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261008054842.GB683793@killaraus.ideasonboard.com \
--to=laurent.pinchart@ideasonboard.com \
--cc=hverkuil@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=ngocthang2710.1999@gmail.com \
--cc=nicfio@gmail.com \
--cc=sakari.ailus@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®