Re: [PATCH RFC v3] media: em28xx: Fix race condition between open and init function

2021-04-16 Thread Shuah Khan

On 4/16/21 1:33 PM, Igor Torrente wrote:



On 4/15/21 2:25 PM, Shuah Khan wrote:

On 4/15/21 8:07 AM, Igor Matheus Andrade Torrente wrote:

Fixes a race condition - for lack of a more precise term - between
em28xx_v4l2_open and em28xx_v4l2_init, by detaching the v4l2_dev,
media_pad and vdev structs from the em28xx_v4l2, and managing the
lifetime of those objects more dynamicaly.

The race happens when a thread[1] - containing the em28xx_v4l2_init()
code - calls the v4l2_mc_create_media_graph(), and it return a error,
if a thread[2] - running v4l2_open() - pass the verification point
and reaches the em28xx_v4l2_open() before the thread[1] finishes
the deregistration of v4l2 subsystem, the thread[1] will free all
resources before the em28xx_v4l2_open() can process their things,
because the em28xx_v4l2_init() has the dev->lock. And all this lead
the thread[2] to cause a user-after-free.

Reported-by: kernel test robot 
Reported-and-tested-by: 
syzbot+b2391895514ed9ef4...@syzkaller.appspotmail.com

Signed-off-by: Igor Matheus Andrade Torrente 
---

V2: Add v4l2_i2c_new_subdev null check
 Deal with v4l2 subdevs dependencies

V3: Fix link error when compiled as a module

---
  drivers/media/usb/em28xx/em28xx-camera.c |   4 +-
  drivers/media/usb/em28xx/em28xx-video.c  | 300 +++
  drivers/media/usb/em28xx/em28xx.h    |   6 +-
  3 files changed, 209 insertions(+), 101 deletions(-)



The changes looks good to me. Have you tried building as a modules and
running modprobes and rmmods? You can do that without a device.



I tried and everything worked fine.



Thank you.

Reviewed-by: Shuah Khan 

thanks,
-- Shuah



Re: [PATCH RFC v3] media: em28xx: Fix race condition between open and init function

2021-04-16 Thread Igor Torrente




On 4/15/21 2:25 PM, Shuah Khan wrote:

On 4/15/21 8:07 AM, Igor Matheus Andrade Torrente wrote:

Fixes a race condition - for lack of a more precise term - between
em28xx_v4l2_open and em28xx_v4l2_init, by detaching the v4l2_dev,
media_pad and vdev structs from the em28xx_v4l2, and managing the
lifetime of those objects more dynamicaly.

The race happens when a thread[1] - containing the em28xx_v4l2_init()
code - calls the v4l2_mc_create_media_graph(), and it return a error,
if a thread[2] - running v4l2_open() - pass the verification point
and reaches the em28xx_v4l2_open() before the thread[1] finishes
the deregistration of v4l2 subsystem, the thread[1] will free all
resources before the em28xx_v4l2_open() can process their things,
because the em28xx_v4l2_init() has the dev->lock. And all this lead
the thread[2] to cause a user-after-free.

Reported-by: kernel test robot 
Reported-and-tested-by: 
syzbot+b2391895514ed9ef4...@syzkaller.appspotmail.com

Signed-off-by: Igor Matheus Andrade Torrente 
---

V2: Add v4l2_i2c_new_subdev null check
 Deal with v4l2 subdevs dependencies

V3: Fix link error when compiled as a module

---
  drivers/media/usb/em28xx/em28xx-camera.c |   4 +-
  drivers/media/usb/em28xx/em28xx-video.c  | 300 +++
  drivers/media/usb/em28xx/em28xx.h    |   6 +-
  3 files changed, 209 insertions(+), 101 deletions(-)



The changes looks good to me. Have you tried building as a modules and
running modprobes and rmmods? You can do that without a device.



I tried and everything worked fine.


thanks,
-- Shuah



Thanks,
---
Igor Matheus Andrade Torrente


Re: [PATCH RFC v3] media: em28xx: Fix race condition between open and init function

2021-04-15 Thread Shuah Khan

On 4/15/21 8:07 AM, Igor Matheus Andrade Torrente wrote:

Fixes a race condition - for lack of a more precise term - between
em28xx_v4l2_open and em28xx_v4l2_init, by detaching the v4l2_dev,
media_pad and vdev structs from the em28xx_v4l2, and managing the
lifetime of those objects more dynamicaly.

The race happens when a thread[1] - containing the em28xx_v4l2_init()
code - calls the v4l2_mc_create_media_graph(), and it return a error,
if a thread[2] - running v4l2_open() - pass the verification point
and reaches the em28xx_v4l2_open() before the thread[1] finishes
the deregistration of v4l2 subsystem, the thread[1] will free all
resources before the em28xx_v4l2_open() can process their things,
because the em28xx_v4l2_init() has the dev->lock. And all this lead
the thread[2] to cause a user-after-free.

Reported-by: kernel test robot 
Reported-and-tested-by: syzbot+b2391895514ed9ef4...@syzkaller.appspotmail.com
Signed-off-by: Igor Matheus Andrade Torrente 
---

V2: Add v4l2_i2c_new_subdev null check
 Deal with v4l2 subdevs dependencies

V3: Fix link error when compiled as a module

---
  drivers/media/usb/em28xx/em28xx-camera.c |   4 +-
  drivers/media/usb/em28xx/em28xx-video.c  | 300 +++
  drivers/media/usb/em28xx/em28xx.h|   6 +-
  3 files changed, 209 insertions(+), 101 deletions(-)



The changes looks good to me. Have you tried building as a modules and
running modprobes and rmmods? You can do that without a device.

thanks,
-- Shuah




[PATCH RFC v3] media: em28xx: Fix race condition between open and init function

2021-04-15 Thread Igor Matheus Andrade Torrente
Fixes a race condition - for lack of a more precise term - between
em28xx_v4l2_open and em28xx_v4l2_init, by detaching the v4l2_dev,
media_pad and vdev structs from the em28xx_v4l2, and managing the
lifetime of those objects more dynamicaly.

The race happens when a thread[1] - containing the em28xx_v4l2_init()
code - calls the v4l2_mc_create_media_graph(), and it return a error,
if a thread[2] - running v4l2_open() - pass the verification point
and reaches the em28xx_v4l2_open() before the thread[1] finishes
the deregistration of v4l2 subsystem, the thread[1] will free all
resources before the em28xx_v4l2_open() can process their things,
because the em28xx_v4l2_init() has the dev->lock. And all this lead
the thread[2] to cause a user-after-free.

Reported-by: kernel test robot 
Reported-and-tested-by: syzbot+b2391895514ed9ef4...@syzkaller.appspotmail.com
Signed-off-by: Igor Matheus Andrade Torrente 
---

V2: Add v4l2_i2c_new_subdev null check
Deal with v4l2 subdevs dependencies

V3: Fix link error when compiled as a module

---
 drivers/media/usb/em28xx/em28xx-camera.c |   4 +-
 drivers/media/usb/em28xx/em28xx-video.c  | 300 +++
 drivers/media/usb/em28xx/em28xx.h|   6 +-
 3 files changed, 209 insertions(+), 101 deletions(-)

diff --git a/drivers/media/usb/em28xx/em28xx-camera.c 
b/drivers/media/usb/em28xx/em28xx-camera.c
index d1e66b503f4d..436c5a8cbbb6 100644
--- a/drivers/media/usb/em28xx/em28xx-camera.c
+++ b/drivers/media/usb/em28xx/em28xx-camera.c
@@ -340,7 +340,7 @@ int em28xx_init_camera(struct em28xx *dev)
v4l2->sensor_xtal = 430;
pdata.xtal = v4l2->sensor_xtal;
if (NULL ==
-   v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
+   v4l2_i2c_new_subdev_board(v4l2->v4l2_dev, adap,
  &mt9v011_info, NULL))
return -ENODEV;
v4l2->vinmode = EM28XX_VINMODE_RGB8_GRBG;
@@ -394,7 +394,7 @@ int em28xx_init_camera(struct em28xx *dev)
v4l2->sensor_yres = 480;
 
subdev =
-v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
+v4l2_i2c_new_subdev_board(v4l2->v4l2_dev, adap,
   &ov2640_info, NULL);
if (!subdev)
return -ENODEV;
diff --git a/drivers/media/usb/em28xx/em28xx-video.c 
b/drivers/media/usb/em28xx/em28xx-video.c
index 6b84c3413e83..85dfd80fddfb 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -184,7 +184,7 @@ static int em28xx_vbi_supported(struct em28xx *dev)
  */
 static void em28xx_wake_i2c(struct em28xx *dev)
 {
-   struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
+   struct v4l2_device *v4l2_dev = dev->v4l2->v4l2_dev;
 
v4l2_device_call_all(v4l2_dev, 0, core,  reset, 0);
v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
@@ -974,9 +974,17 @@ static void em28xx_v4l2_create_entities(struct em28xx *dev)
struct em28xx_v4l2 *v4l2 = dev->v4l2;
int ret, i;
 
+   v4l2->video_pad = kzalloc(sizeof(*v4l2->video_pad), GFP_KERNEL);
+   if (!v4l2->video_pad) {
+   dev_err(&dev->intf->dev,
+   "failed to allocate video pad memory!\n");
+   v4l2->vdev->entity.num_pads = 0;
+   return;
+   }
+
/* Initialize Video, VBI and Radio pads */
-   v4l2->video_pad.flags = MEDIA_PAD_FL_SINK;
-   ret = media_entity_pads_init(&v4l2->vdev.entity, 1, &v4l2->video_pad);
+   v4l2->video_pad->flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(&v4l2->vdev->entity, 1, v4l2->video_pad);
if (ret < 0)
dev_err(&dev->intf->dev,
"failed to initialize video media entity!\n");
@@ -1132,11 +1140,11 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, 
unsigned int count)
f.type = V4L2_TUNER_RADIO;
else
f.type = V4L2_TUNER_ANALOG_TV;
-   v4l2_device_call_all(&v4l2->v4l2_dev,
+   v4l2_device_call_all(v4l2->v4l2_dev,
 0, tuner, s_frequency, &f);
 
/* Enable video stream at TV decoder */
-   v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 1);
+   v4l2_device_call_all(v4l2->v4l2_dev, 0, video, s_stream, 1);
}
 
v4l2->streaming_users++;
@@ -1157,7 +1165,7 @@ static void em28xx_stop_streaming(struct vb2_queue *vq)
 
if (v4l2->streaming_users-- == 1) {
/* Disable video stream at TV decoder */
-   v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0);
+   v4l2_device_call_all(v4l2->v4l2_dev, 0, video, s_stream, 0);
 
/* Last active user, so shutdown all the URBS */
em28xx_uninit_usb_xfer(dev