Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1572779 > unrolled thread

Re: [PATCH v3 20/24] media: imx: Add Camera Interface subdev driver

Started byRussell King - ARM Linux <linux@armlinux.org.uk>
First post2017-02-02 23:40 +0100
Last post2017-02-07 03:00 +0100
Articles 2 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [PATCH v3 20/24] media: imx: Add Camera Interface subdev driver Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-02 23:40 +0100
    Re: [PATCH v3 20/24] media: imx: Add Camera Interface subdev driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-07 03:00 +0100

#1572779 — Re: [PATCH v3 20/24] media: imx: Add Camera Interface subdev driver

FromRussell King - ARM Linux <linux@armlinux.org.uk>
Date2017-02-02 23:40 +0100
SubjectRe: [PATCH v3 20/24] media: imx: Add Camera Interface subdev driver
Message-ID<t6ycP-1zz-27@gated-at.bofh.it>
On Fri, Jan 06, 2017 at 06:11:38PM -0800, Steve Longerbeam wrote:
> +struct camif_priv {
> +	struct device         *dev;
> +	struct video_device    vfd;

You can't do this.

> +static struct video_device camif_videodev = {
> +	.fops		= &camif_fops,
> +	.ioctl_ops	= &camif_ioctl_ops,
> +	.minor		= -1,
> +	.release	= video_device_release,
> +	.vfl_dir	= VFL_DIR_RX,
> +	.tvnorms	= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
> +};

> +static int camif_probe(struct platform_device *pdev)
> +{
> +	struct imx_media_internal_sd_platformdata *pdata;
> +	struct camif_priv *priv;
> +	struct video_device *vfd;
> +	int ret;
> +
> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;

You kmalloc this structure, so this structure has the lifetime of
the driver being bound to the platform device.

> +	vfd = &priv->vfd;
> +	*vfd = camif_videodev;

However, "*vfd" contains a struct device, and you _correctly_ set the
release function for "*vfd" to video_device_release via camif_videodev.

However, if you try to rmmod imx-media, then you end up with a kernel
warning that you're freeing memory containing a held lock, and later
chaos ensues because kmalloc has been corrupted.

The root cause of this is embedding the device structure within the
video_device into the driver's private data.  *Any* structure what so
ever that contains a kref is reference counted, and that includes
struct device, and therefore also includes struct video_device.  What
that means is that its lifetime is _not_ under _your_ control, and
you may not free it except through its release function (which is
video_device_release().)  However, that also tries to kfree (with an
offset of 4) your private data, which results in the warning and the
corrupted kmalloc free lists.

The solution is simple, make "vfd" a pointer in your private data
structure and kmalloc() it separately, letting video_device_release()
kfree() that data when it needs to.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

[toc] | [next] | [standalone]


#1575323

FromSteve Longerbeam <slongerbeam@gmail.com>
Date2017-02-07 03:00 +0100
Message-ID<t83ey-4xN-7@gated-at.bofh.it>
In reply to#1572779
On 02/02/2017 02:35 PM, Russell King - ARM Linux wrote:
> <snip>
> However, "*vfd" contains a struct device, and you _correctly_ set the
> release function for "*vfd" to video_device_release via camif_videodev.
>
> However, if you try to rmmod imx-media, then you end up with a kernel
> warning that you're freeing memory containing a held lock, and later
> chaos ensues because kmalloc has been corrupted.
>
> The root cause of this is embedding the device structure within the
> video_device into the driver's private data.  *Any* structure what so
> ever that contains a kref is reference counted, and that includes
> struct device, and therefore also includes struct video_device.  What
> that means is that its lifetime is _not_ under _your_ control, and
> you may not free it except through its release function (which is
> video_device_release().)  However, that also tries to kfree (with an
> offset of 4) your private data, which results in the warning and the
> corrupted kmalloc free lists.
>
> The solution is simple, make "vfd" a pointer in your private data
> structure and kmalloc() it separately, letting video_device_release()
> kfree() that data when it needs to.

Thanks Russell for tracking this down. I remember doing this
when I was reviewing the code for opportunities to "optimize" :-/,
and carelessly caused this bug by not reviewing how video_device
is freed.

Fixed.

Steve

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web