mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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

  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®