Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: ti-vpe: cal: fix a kernel oops when unloading module

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>

authored by

Benoit Parrot and committed by
Mauro Carvalho Chehab
80264809 e6599adf

+8 -5
+8 -5
drivers/media/platform/ti-vpe/cal.c
··· 372 372 struct v4l2_subdev *sensor; 373 373 struct v4l2_fwnode_endpoint endpoint; 374 374 375 - struct v4l2_async_subdev asd; 376 - 377 375 struct v4l2_fh fh; 378 376 struct cal_dev *dev; 379 377 struct cc_data *cc; ··· 2030 2032 2031 2033 parent = pdev->dev.of_node; 2032 2034 2033 - asd = &ctx->asd; 2034 2035 endpoint = &ctx->endpoint; 2035 2036 2036 2037 ep_node = NULL; ··· 2076 2079 ctx_dbg(3, ctx, "can't get remote parent\n"); 2077 2080 goto cleanup_exit; 2078 2081 } 2079 - asd->match_type = V4L2_ASYNC_MATCH_FWNODE; 2080 - asd->match.fwnode = of_fwnode_handle(sensor_node); 2081 2082 2082 2083 v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), endpoint); 2083 2084 ··· 2105 2110 2106 2111 v4l2_async_notifier_init(&ctx->notifier); 2107 2112 2113 + asd = kzalloc(sizeof(*asd), GFP_KERNEL); 2114 + if (!asd) 2115 + goto cleanup_exit; 2116 + 2117 + asd->match_type = V4L2_ASYNC_MATCH_FWNODE; 2118 + asd->match.fwnode = of_fwnode_handle(sensor_node); 2119 + 2108 2120 ret = v4l2_async_notifier_add_subdev(&ctx->notifier, asd); 2109 2121 if (ret) { 2110 2122 ctx_err(ctx, "Error adding asd\n"); 2123 + kfree(asd); 2111 2124 goto cleanup_exit; 2112 2125 } 2113 2126