| From 949c1695a7a452e12b8332aa180f29ce5593d5d3 Mon Sep 17 00:00:00 2001 |
| From: Benoit Parrot <bparrot@ti.com> |
| Date: Fri, 6 Mar 2020 14:08:39 +0100 |
| Subject: [PATCH] media: ti-vpe: cal: fix a kernel oops when unloading module |
| |
| commit 80264809ea0a3fd2ee8251f31a9eb85d2c3fc77e upstream. |
| |
| After the switch to use v4l2_async_notifier_add_subdev() and |
| v4l2_async_notifier_cleanup(), unloading the ti_cal module would cause a |
| kernel oops. |
| |
| This was root cause to the fact that v4l2_async_notifier_cleanup() tries |
| to kfree the asd pointer passed into v4l2_async_notifier_add_subdev(). |
| |
| In our case the asd reference was from a statically allocated struct. |
| So in effect v4l2_async_notifier_cleanup() was trying to free a pointer |
| that was not kalloc. |
| |
| So here we switch to using a kzalloc struct instead of a static one. |
| To achieve this we re-order some of the calls to prevent asd allocation |
| from leaking. |
| |
| Fixes: d079f94c9046 ("media: platform: Switch to v4l2_async_notifier_add_subdev") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Benoit Parrot <bparrot@ti.com> |
| Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com> |
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c |
| index 92947d7df05a..92311461cc59 100644 |
| --- a/drivers/media/platform/ti-vpe/cal.c |
| +++ b/drivers/media/platform/ti-vpe/cal.c |
| @@ -266,8 +266,6 @@ struct cal_ctx { |
| struct v4l2_subdev *sensor; |
| struct v4l2_fwnode_endpoint endpoint; |
| |
| - struct v4l2_async_subdev asd; |
| - |
| struct v4l2_fh fh; |
| struct cal_dev *dev; |
| struct cc_data *cc; |
| @@ -1648,7 +1646,6 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) |
| |
| parent = pdev->dev.of_node; |
| |
| - asd = &ctx->asd; |
| endpoint = &ctx->endpoint; |
| |
| ep_node = NULL; |
| @@ -1695,8 +1692,6 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) |
| ctx_dbg(3, ctx, "can't get remote parent\n"); |
| goto cleanup_exit; |
| } |
| - asd->match_type = V4L2_ASYNC_MATCH_FWNODE; |
| - asd->match.fwnode = of_fwnode_handle(sensor_node); |
| |
| v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), endpoint); |
| |
| @@ -1726,9 +1721,17 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) |
| |
| v4l2_async_notifier_init(&ctx->notifier); |
| |
| + asd = kzalloc(sizeof(*asd), GFP_KERNEL); |
| + if (!asd) |
| + goto cleanup_exit; |
| + |
| + asd->match_type = V4L2_ASYNC_MATCH_FWNODE; |
| + asd->match.fwnode = of_fwnode_handle(sensor_node); |
| + |
| ret = v4l2_async_notifier_add_subdev(&ctx->notifier, asd); |
| if (ret) { |
| ctx_err(ctx, "Error adding asd\n"); |
| + kfree(asd); |
| goto cleanup_exit; |
| } |
| |
| -- |
| 2.7.4 |
| |