| From 2f38a7916c942d680cbb62985f51b0d2e2570365 Mon Sep 17 00:00:00 2001 |
| From: Akinobu Mita <akinobu.mita@gmail.com> |
| Date: Sat, 20 Oct 2018 10:26:23 -0400 |
| Subject: media: video-i2c: avoid accessing released memory area when removing |
| driver |
| |
| [ Upstream commit c764da98a600a4b068d25c77164f092f159cecec ] |
| |
| The video device release() callback for video-i2c driver frees the whole |
| struct video_i2c_data. If there is no user left for the video device |
| when video_unregister_device() is called, the release callback is executed. |
| |
| However, in video_i2c_remove() some fields (v4l2_dev, lock, and queue_lock) |
| in struct video_i2c_data are still accessed after video_unregister_device() |
| is called. |
| |
| This fixes the use after free by moving the code from video_i2c_remove() |
| to the release() callback. |
| |
| Fixes: 5cebaac60974 ("media: video-i2c: add video-i2c driver") |
| |
| Reviewed-by: Matt Ranostay <matt.ranostay@konsulko.com> |
| Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> |
| Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com> |
| Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/media/i2c/video-i2c.c | 11 ++++++----- |
| 1 file changed, 6 insertions(+), 5 deletions(-) |
| |
| diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c |
| index 06d29d8f6be8..f27d294dcbef 100644 |
| --- a/drivers/media/i2c/video-i2c.c |
| +++ b/drivers/media/i2c/video-i2c.c |
| @@ -510,7 +510,12 @@ static const struct v4l2_ioctl_ops video_i2c_ioctl_ops = { |
| |
| static void video_i2c_release(struct video_device *vdev) |
| { |
| - kfree(video_get_drvdata(vdev)); |
| + struct video_i2c_data *data = video_get_drvdata(vdev); |
| + |
| + v4l2_device_unregister(&data->v4l2_dev); |
| + mutex_destroy(&data->lock); |
| + mutex_destroy(&data->queue_lock); |
| + kfree(data); |
| } |
| |
| static int video_i2c_probe(struct i2c_client *client, |
| @@ -608,10 +613,6 @@ static int video_i2c_remove(struct i2c_client *client) |
| struct video_i2c_data *data = i2c_get_clientdata(client); |
| |
| video_unregister_device(&data->vdev); |
| - v4l2_device_unregister(&data->v4l2_dev); |
| - |
| - mutex_destroy(&data->lock); |
| - mutex_destroy(&data->queue_lock); |
| |
| return 0; |
| } |
| -- |
| 2.19.1 |
| |