From bd14f96e5e7eca3dfd7a8203e3ba8dfe0b5573db Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Fri, 15 Dec 2023 10:10:03 +0800 Subject: [PATCH] soc: rockchip: rockchip_system_monitor: Fix list_del corruption when del video info list_del corruption, ffffffc028662d18->next is LIST_POISON1 (dead000000000100) ------------[ cut here ]------------ kernel BUG at lib/list_debug.c:47! Internal error: Oops - BUG: 0 [#1] PREEMPT SMP Modules linked in: 8822es(O) sprdbt_tty Process CtrlThread (pid: 3697, stack limit = 0x0000000060d302a5) CPU: 1 PID: 3697 Comm: CtrlThread Tainted: G O 4.19.232 #96 Hardware name: Rockchip RK3528 DEMO4 DDR4 V10 Board (DT) pstate: 40400005 (nZcv daif +PAN -UAO) pc : __list_del_entry_valid+0x64/0xb0 lr : __list_del_entry_valid+0x64/0xb0 sp : ffffff800fd1bc70 x29: ffffff800fd1bc70 x28: ffffffc05c468000 x27: 0000000000000000 x26: 0000000000000000 x25: 0000000046000000 x24: 0000000000000011 x23: ffffff800fd1be60 x22: ffffff80098188a0 x21: ffffff8009818000 x20: ffffffc0462af700 x19: ffffffc028662d00 x18: ffffffffffffffff x17: 0000000000000000 x16: 0000000000000000 x15: ffffff800934a980 x14: 4f53494f505f5453 x13: 494c207369207478 x12: 656e3e2d38316432 x11: 3636383230636666 x10: 66666666202c6e6f x9 : 6974707572726f63 x8 : 3030303030303030 x7 : 0000000000000058 x6 : ffffffc07f74aa18 x5 : ffffffc07f74aa18 x4 : 0000000000000000 x3 : ffffffc07f753908 x2 : ac674fb1e4701200 x1 : 0000000000000000 x0 : 000000000000004e Call trace: __list_del_entry_valid+0x64/0xb0 rockchip_update_system_status+0x168/0x250 status_store+0x1c/0x38 kobj_attr_store+0x14/0x28 sysfs_kf_write+0x48/0x58 kernfs_fop_write+0xf4/0x220 __vfs_write+0x34/0x158 vfs_write+0xb0/0x1d0 ksys_write+0x64/0xe0 __arm64_sys_write+0x14/0x20 el0_svc_common.constprop.0+0x64/0x178 el0_svc_compat_handler+0x18/0x20 el0_svc_compat+0x8/0x34 Signed-off-by: Finley Xiao Change-Id: I42e9c42d7e65c742226f82b9367466b2ed86550d --- .../soc/rockchip/rockchip_system_monitor.c | 53 +++++++------------ 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/drivers/soc/rockchip/rockchip_system_monitor.c b/drivers/soc/rockchip/rockchip_system_monitor.c index 527764e235c7..51844a9c8025 100644 --- a/drivers/soc/rockchip/rockchip_system_monitor.c +++ b/drivers/soc/rockchip/rockchip_system_monitor.c @@ -246,34 +246,6 @@ static struct video_info *rockchip_parse_video_info(const char *buf) return video_info; } -static struct video_info *rockchip_find_video_info(const char *buf) -{ - struct video_info *info, *video_info; - - video_info = rockchip_parse_video_info(buf); - - if (!video_info) - return NULL; - - mutex_lock(&video_info_mutex); - list_for_each_entry(info, &video_info_list, node) { - if (info->width == video_info->width && - info->height == video_info->height && - info->ishevc == video_info->ishevc && - info->videoFramerate == video_info->videoFramerate && - info->streamBitrate == video_info->streamBitrate) { - mutex_unlock(&video_info_mutex); - kfree(video_info); - return info; - } - } - - mutex_unlock(&video_info_mutex); - kfree(video_info); - - return NULL; -} - static void rockchip_add_video_info(struct video_info *video_info) { if (video_info) { @@ -285,12 +257,25 @@ static void rockchip_add_video_info(struct video_info *video_info) static void rockchip_del_video_info(struct video_info *video_info) { - if (video_info) { - mutex_lock(&video_info_mutex); - list_del(&video_info->node); - mutex_unlock(&video_info_mutex); - kfree(video_info); + struct video_info *info, *tmp; + + if (!video_info) + return; + + mutex_lock(&video_info_mutex); + list_for_each_entry_safe(info, tmp, &video_info_list, node) { + if (info->width == video_info->width && + info->height == video_info->height && + info->ishevc == video_info->ishevc && + info->videoFramerate == video_info->videoFramerate && + info->streamBitrate == video_info->streamBitrate) { + list_del(&info->node); + kfree(info); + break; + } } + kfree(video_info); + mutex_unlock(&video_info_mutex); } static void rockchip_update_video_info(void) @@ -338,7 +323,7 @@ void rockchip_update_system_status(const char *buf) switch (buf[0]) { case '0': /* clear video flag */ - video_info = rockchip_find_video_info(buf); + video_info = rockchip_parse_video_info(buf); if (video_info) { rockchip_del_video_info(video_info); rockchip_update_video_info();