summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiu Ying <victor.liu@nxp.com>2018-11-28 16:32:05 +0800
committerBryan O'Donoghue <bryan.odonoghue@linaro.org>2019-05-01 17:43:28 +0100
commit045f717b4d27566246e6db29322679972321b2bc (patch)
treeef52c5a3928767009d1db6f417b7271921c9bbf0
parent0c29cc356a65cca11e1bc33cad5934d1bd01a738 (diff)
MLK-16302-2 drm/imx: dpu: crtc: Cleanup crtc in ->unbind() if necessary
When the master imx-drm-core binding fails, component_bind_all() in imx-drm-core ->bind() callback will unbind all bound components first and then call drm_mode_config_cleanup(). Since the crtc as a member(base) of dpu_crtc is freed after the dpu crtc ->unbind() callback, drm_mode_config_cleanup() would accidentally access the freed crtc again. To fix this issue, we should cleanup the crtc, i.e., remove the crtc from the global crtc list, in the ->unbind() callback, so that drm_mode_config_cleanup() won't find the crtc again in the list. However, we have to make sure the crtc exists before the cleanup in the ->unbind() callback, because imx-drm-core ->unbind() calls drm_mode_config_cleanup() first and then unbinds all components via component_unbind_all(). There is a probe deferral caused by the LDB component(later probed GPIO resource) on some platforms(e.g., i.MX8QXP MEK), which causes multiple times to try binding and triggers the issue described above. This patch may fix the issue reported by KASAN: [ 3.217996] BUG: KASAN: use-after-free in drm_mode_config_cleanup+0x220/0x448 [ 3.225149] Read of size 8 at addr ffff80000ad719b0 by task swapper/0/1 [ 3.231769] [ 3.233279] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.14.78-05529-ge53ea0dba88e-dirty #43 [ 3.241642] Hardware name: Freescale i.MX8QXP MEK (DT) [ 3.246793] Call trace: [ 3.249270] [<ffff20000808e7d0>] dump_backtrace+0x0/0x390 [ 3.254690] [<ffff20000808eb74>] show_stack+0x14/0x20 [ 3.259769] [<ffff20000968a108>] dump_stack+0xf8/0x158 [ 3.264932] [<ffff20000830db10>] print_address_description+0x60/0x270 [ 3.271396] [<ffff20000830dff0>] kasan_report+0x210/0x2f0 [ 3.276818] [<ffff20000830c6f4>] __asan_load8+0x84/0xa8 [ 3.282065] [<ffff200008ad4380>] drm_mode_config_cleanup+0x220/0x448 [ 3.288447] [<ffff200008afa7b4>] imx_drm_bind+0x2b4/0x358 [ 3.293863] [<ffff200008b2024c>] try_to_bring_up_master+0x20c/0x278 [ 3.300148] [<ffff200008b20438>] component_add+0x180/0x300 [ 3.305653] [<ffff200008b0b530>] dpu_bliteng_probe+0x30/0x48 [ 3.311339] [<ffff200008b2e13c>] platform_drv_probe+0x74/0x108 [ 3.317198] [<ffff200008b2b3c8>] driver_probe_device+0x3a0/0x4a8 [ 3.323226] [<ffff200008b2b5a0>] __driver_attach+0xd0/0xd8 [ 3.328735] [<ffff200008b27e78>] bus_for_each_dev+0xc0/0x140 [ 3.334419] [<ffff200008b2a618>] driver_attach+0x30/0x40 [ 3.339749] [<ffff200008b29d48>] bus_add_driver+0x2a8/0x320 [ 3.345344] [<ffff200008b2c54c>] driver_register+0xb4/0x190 [ 3.350941] [<ffff200008b2e054>] __platform_driver_register+0x7c/0x88 [ 3.357410] [<ffff20000a228118>] dpu_bliteng_driver_init+0x1c/0x24 [ 3.363613] [<ffff200008084540>] do_one_initcall+0xe0/0x260 [ 3.369211] [<ffff20000a1c10f0>] kernel_init_freeable+0x230/0x2d8 [ 3.375330] [<ffff2000096aa4a8>] kernel_init+0x10/0x118 [ 3.380574] [<ffff2000080863c8>] ret_from_fork+0x10/0x18 [ 3.385894] [ 3.387393] Allocated by task 1: [ 3.390642] kasan_kmalloc+0xd0/0x180 [ 3.394322] kasan_slab_alloc+0x14/0x20 [ 3.398174] __kmalloc_node_track_caller+0x1ec/0x278 [ 3.403157] devm_kmalloc+0x8c/0x128 [ 3.406753] dpu_crtc_bind+0x38/0xbe0 [ 3.410434] component_bind_all+0x254/0x438 [ 3.414638] imx_drm_bind+0x1b0/0x358 [ 3.418314] try_to_bring_up_master+0x20c/0x278 [ 3.422857] component_add+0x180/0x300 [ 3.426622] dpu_bliteng_probe+0x30/0x48 [ 3.430559] platform_drv_probe+0x74/0x108 [ 3.434676] driver_probe_device+0x3a0/0x4a8 [ 3.438966] __driver_attach+0xd0/0xd8 [ 3.442730] bus_for_each_dev+0xc0/0x140 [ 3.446663] driver_attach+0x30/0x40 [ 3.450251] bus_add_driver+0x2a8/0x320 [ 3.454103] driver_register+0xb4/0x190 [ 3.457960] __platform_driver_register+0x7c/0x88 [ 3.462687] dpu_bliteng_driver_init+0x1c/0x24 [ 3.467147] do_one_initcall+0xe0/0x260 [ 3.470997] kernel_init_freeable+0x230/0x2d8 [ 3.475366] kernel_init+0x10/0x118 [ 3.478867] ret_from_fork+0x10/0x18 [ 3.482447] [ 3.483941] Freed by task 1: [ 3.486837] kasan_slab_free+0x88/0x198 [ 3.490691] kfree+0x70/0x210 [ 3.493672] release_nodes+0x538/0x5c0 [ 3.497432] devres_release_group+0x164/0x200 [ 3.501801] component_unbind.isra.4+0x98/0xb8 [ 3.506257] component_bind_all+0x3c8/0x438 [ 3.510456] imx_drm_bind+0x1b0/0x358 [ 3.514131] try_to_bring_up_master+0x20c/0x278 [ 3.518671] component_add+0x180/0x300 [ 3.522434] dpu_bliteng_probe+0x30/0x48 [ 3.526375] platform_drv_probe+0x74/0x108 [ 3.530490] driver_probe_device+0x3a0/0x4a8 [ 3.534781] __driver_attach+0xd0/0xd8 [ 3.538551] bus_for_each_dev+0xc0/0x140 [ 3.542488] driver_attach+0x30/0x40 [ 3.546083] bus_add_driver+0x2a8/0x320 [ 3.549941] driver_register+0xb4/0x190 [ 3.553793] __platform_driver_register+0x7c/0x88 [ 3.558519] dpu_bliteng_driver_init+0x1c/0x24 [ 3.562979] do_one_initcall+0xe0/0x260 [ 3.566827] kernel_init_freeable+0x230/0x2d8 [ 3.571199] kernel_init+0x10/0x118 [ 3.574698] ret_from_fork+0x10/0x18 [ 3.578277] [ 3.579783] The buggy address belongs to the object at ffff80000ad71980 [ 3.579783] which belongs to the cache kmalloc-2048 of size 2048 [ 3.592501] The buggy address is located 48 bytes inside of [ 3.592501] 2048-byte region [ffff80000ad71980, ffff80000ad72180) [ 3.604258] The buggy address belongs to the page: [ 3.609072] page:ffff7e00002b5c00 count:1 mapcount:0 mapping: (null) index:0x0 compound_mapcount: 0 [ 3.618926] flags: 0xfffc00000008100(slab|head) [ 3.623484] raw: 0fffc00000008100 0000000000000000 0000000000000000 00000001800f000f [ 3.631252] raw: dead000000000100 dead000000000200 ffff800010703400 0000000000000000 [ 3.639007] page dumped because: kasan: bad access detected [ 3.644590] [ 3.646086] Memory state around the buggy address: [ 3.650898] ffff80000ad71880: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 3.658134] ffff80000ad71900: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 3.665370] >ffff80000ad71980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 3.672599] ^ [ 3.677402] ffff80000ad71a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 3.684641] ffff80000ad71a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb Signed-off-by: Liu Ying <victor.liu@nxp.com> (cherry picked from commit 5fc482dbf423fff005214db5ac4ac2dcd5cae028)
-rw-r--r--drivers/gpu/drm/imx/dpu/dpu-crtc.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/gpu/drm/imx/dpu/dpu-crtc.c b/drivers/gpu/drm/imx/dpu/dpu-crtc.c
index 1bc701b0879f..cde5007f2450 100644
--- a/drivers/gpu/drm/imx/dpu/dpu-crtc.c
+++ b/drivers/gpu/drm/imx/dpu/dpu-crtc.c
@@ -1099,6 +1099,10 @@ static void dpu_crtc_unbind(struct device *dev, struct device *master,
struct dpu_crtc *dpu_crtc = dev_get_drvdata(dev);
dpu_crtc_put_resources(dpu_crtc);
+
+ /* make sure the crtc exists, and then cleanup */
+ if (dpu_crtc->base.dev)
+ drm_crtc_cleanup(&dpu_crtc->base);
}
static const struct component_ops dpu_crtc_ops = {