drm/bridge: synopsys: dw-hdmi: destroy connector and encoder

connector and encoder should be removed when bind failed, otherwise will
lead to system panic when enable SLUB and SLUB_DEBUG:

[    1.071801] rockchip-drm display-subsystem: failed to bind ff960000.dsi (ops dw_mipi_dsi_ops): -517
[    1.073943] Unable to handle kernel paging request at virtual address 006b6b6b6b6b6b73
……
[    1.442300] pc : drm_mode_config_cleanup+0x4c/0x2f8
[    1.447179] lr : rockchip_drm_bind+0x610/0x1c38

after enable KASAN, we can see the UAF error:

[    3.862556] BUG: KASAN: use-after-free in rockchip_drm_bind+0x474/0x2b58
[    3.862611] Read of size 4 at addr ffffffc00a21f55c by task swapper/0/1
[    3.862691] CPU: 4 PID: 1 Comm: swapper/0 Not tainted 4.19.101 #1820
[    3.862737] Hardware name: Rockchip rk3368 808 evb board (DT)
[    3.862782] Call trace:
[    3.862853]  dump_backtrace+0x0/0x240
[    3.862905]  show_stack+0x14/0x20
[    3.863146]  kasan_report+0xc/0x18
[    3.863265]  rockchip_drm_bind+0x474/0x2b58
……
[    3.864314] Allocated by task 1:
[    3.864376]  __kasan_kmalloc.isra.0+0x100/0x1b8
[    3.864435]  kasan_slab_alloc+0x14/0x20
[    3.864493]  __kmalloc_track_caller+0x154/0x368
[    3.864550]  devm_kmalloc+0x30/0xb0
[    3.864611]  dw_hdmi_rockchip_bind+0xcc/0xa28
[    3.864668]  component_bind_all+0x1d8/0x450
[    3.864728]  rockchip_drm_bind+0x450/0x2b58
……
[    3.865787] Freed by task 1:
[    3.865851]  __kasan_slab_free+0x118/0x220
[    3.865897]  kasan_slab_free+0x10/0x18
[    3.865952]  kfree+0x7c/0x308
[    3.866012]  release_nodes+0x248/0x4a0
[    3.866070]  devres_release_group+0xd4/0x148
[    3.866127]  component_unbind.isra.7+0x98/0xc8
[    3.866183]  component_bind_all+0x3b0/0x450
[    3.866247]  rockchip_drm_bind+0x450/0x2b58

Change-Id: I6378bf34d8b953fb770badfafdd3fe44628505f7
Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
Sandy Huang
2020-03-25 20:03:54 +08:00
committed by Tao Huang
parent d4258036e8
commit 689b1973fb

View File

@@ -4439,6 +4439,8 @@ void dw_hdmi_remove(struct dw_hdmi *hdmi)
hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
dw_hdmi_destroy_properties(hdmi);
hdmi->connector.funcs->destroy(&hdmi->connector);
hdmi->bridge.encoder->funcs->destroy(hdmi->bridge.encoder);
clk_disable_unprepare(hdmi->iahb_clk);
clk_disable_unprepare(hdmi->isfr_clk);