[media] s5p-fimc: Don't allocate fimc-lite video device structure dynamically
authorSylwester Nawrocki <s.nawrocki@samsung.com>
Thu, 26 Jul 2012 10:13:08 +0000 (07:13 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 15 Sep 2012 13:40:10 +0000 (10:40 -0300)
This fixes potential invalid pointer de-reference, when
media_entity_cleanup() is called after video_unregister_device,
and video device structure memory is already freed.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/s5p-fimc/fimc-lite-reg.c
drivers/media/video/s5p-fimc/fimc-lite.c
drivers/media/video/s5p-fimc/fimc-lite.h
drivers/media/video/s5p-fimc/fimc-mdevice.c

index f996e94..09dc71e 100644 (file)
@@ -137,7 +137,7 @@ void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f)
        }
 
        if (i == 0 && src_pixfmt_map[i][0] != pixelcode) {
-               v4l2_err(dev->vfd,
+               v4l2_err(&dev->vfd,
                         "Unsupported pixel code, falling back to %#08x\n",
                         src_pixfmt_map[i][0]);
        }
index c5b57e8..9289008 100644 (file)
@@ -374,7 +374,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
                unsigned long size = fimc->payload[i];
 
                if (vb2_plane_size(vb, i) < size) {
-                       v4l2_err(fimc->vfd,
+                       v4l2_err(&fimc->vfd,
                                 "User buffer too small (%ld < %ld)\n",
                                 vb2_plane_size(vb, i), size);
                        return -EINVAL;
@@ -467,7 +467,7 @@ static int fimc_lite_open(struct file *file)
 
        if (++fimc->ref_count == 1 && fimc->out_path == FIMC_IO_DMA) {
                ret = fimc_pipeline_initialize(&fimc->pipeline,
-                                              &fimc->vfd->entity, true);
+                                              &fimc->vfd.entity, true);
                if (ret < 0) {
                        pm_runtime_put_sync(&fimc->pdev->dev);
                        fimc->ref_count--;
@@ -1215,18 +1215,14 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
 {
        struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
        struct vb2_queue *q = &fimc->vb_queue;
-       struct video_device *vfd;
+       struct video_device *vfd = &fimc->vfd;
        int ret;
 
+       memset(vfd, 0, sizeof(*vfd));
+
        fimc->fmt = &fimc_lite_formats[0];
        fimc->out_path = FIMC_IO_DMA;
 
-       vfd = video_device_alloc();
-       if (!vfd) {
-               v4l2_err(sd->v4l2_dev, "Failed to allocate video device\n");
-               return -ENOMEM;
-       }
-
        snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture",
                 fimc->index);
 
@@ -1234,9 +1230,8 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
        vfd->ioctl_ops = &fimc_lite_ioctl_ops;
        vfd->v4l2_dev = sd->v4l2_dev;
        vfd->minor = -1;
-       vfd->release = video_device_release;
+       vfd->release = video_device_release_empty;
        vfd->lock = &fimc->lock;
-       fimc->vfd = vfd;
        fimc->ref_count = 0;
        fimc->reqbufs_count = 0;
 
@@ -1255,24 +1250,20 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
 
        fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
        ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
-       if (ret)
-               goto err;
+       if (ret < 0)
+               return ret;
 
        video_set_drvdata(vfd, fimc);
 
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
-       if (ret)
-               goto err_vd;
+       if (ret < 0) {
+               media_entity_cleanup(&vfd->entity);
+               return ret;
+       }
 
        v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n",
                  vfd->name, video_device_node_name(vfd));
        return 0;
-
- err_vd:
-       media_entity_cleanup(&vfd->entity);
- err:
-       video_device_release(vfd);
-       return ret;
 }
 
 static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd)
@@ -1282,10 +1273,9 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd)
        if (fimc == NULL)
                return;
 
-       if (fimc->vfd) {
-               video_unregister_device(fimc->vfd);
-               media_entity_cleanup(&fimc->vfd->entity);
-               fimc->vfd = NULL;
+       if (video_is_registered(&fimc->vfd)) {
+               video_unregister_device(&fimc->vfd);
+               media_entity_cleanup(&fimc->vfd.entity);
        }
 }
 
@@ -1515,7 +1505,7 @@ static int fimc_lite_resume(struct device *dev)
                return 0;
 
        INIT_LIST_HEAD(&fimc->active_buf_q);
-       fimc_pipeline_initialize(&fimc->pipeline, &fimc->vfd->entity, false);
+       fimc_pipeline_initialize(&fimc->pipeline, &fimc->vfd.entity, false);
        fimc_lite_hw_init(fimc);
        clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
 
index 44424ee..9944dd3 100644 (file)
@@ -132,7 +132,7 @@ struct fimc_lite {
        struct platform_device  *pdev;
        struct flite_variant    *variant;
        struct v4l2_device      *v4l2_dev;
-       struct video_device     *vfd;
+       struct video_device     vfd;
        struct v4l2_fh          fh;
        struct vb2_alloc_ctx    *alloc_ctx;
        struct v4l2_subdev      subdev;
index e65bb28..0dd26b6 100644 (file)
@@ -591,7 +591,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
                if (fimc == NULL)
                        continue;
                source = &fimc->subdev.entity;
-               sink = &fimc->vfd->entity;
+               sink = &fimc->vfd.entity;
                /* FIMC-LITE's subdev and video node */
                ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
                                               sink, 0, flags);