From ae4ced56fecedac4bda79b82babe928120663ae0 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Mon, 24 Mar 2025 18:13:56 +0800 Subject: [PATCH] media: rockchip: vpss: prevent NULL dereference in ofl_open Add NULL check for ofl->hw before accessing dev_lock mutex to avoid kernel panic caused by translation fault at virtual address 0x27d8. The crash occurs when opening V4L2 device if the hardware structure (ofl->hw) is not properly initialized. This adds defensive checks to: 1. Validate ofl and ofl->hw pointers before mutex operations 2. Return -ENODEV if hw structure is unavailable 3. Prevent use-after-unlock in error paths Fixes system stability issues with v4l_id process (PID 229) when handling uninitialized hardware states. Detail issues can repo as below: [ 6.811649] Unable to handle kernel paging request at virtual address 00000000000027d8 [ 6.812363] Mem abort info: [ 6.812621] ESR = 0x0000000096000005 [ 6.812958] EC = 0x25: DABT (current EL), IL = 32 bits [ 6.813438] SET = 0, FnV = 0 [ 6.813718] EA = 0, S1PTW = 0 [ 6.813999] FSC = 0x05: level 1 translation fault [ 6.814429] Data abort info: [ 6.814685] ISV = 0, ISS = 0x00000005 [ 6.815021] CM = 0, WnR = 0 [ 6.815360] user pgtable: 4k pages, 39-bit VAs, pgdp=0000000043594000 [ 6.815941] [00000000000027d8] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000 [ 6.816746] Internal error: Oops: 0000000096000005 [#1] SMP [ 6.817245] Modules linked in: [ 6.817530] CPU: 0 PID: 229 Comm: v4l_id Tainted: G W 6.1.118 #16 [ 6.818193] Hardware name: Rockchip RV1126B EVB1 V10 Board (DT) [ 6.818715] pstate: 00000005 (nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 6.819332] pc : mutex_unlock+0xc/0x40 [ 6.819686] lr : ofl_open+0x5c/0xc8 [ 6.820010] sp : ffffffc009673ad0 [ 6.820312] x29: ffffffc009673ad0 x28: ffffff8001f65400 x27: 0000000000000000 [ 6.820956] x26: 0000000000000004 x25: 0000000000000000 x24: ffffffc008cae360 [ 6.821598] x23: ffffff800290e200 x22: 00000000000027d8 x21: ffffff8002030108 [ 6.822233] x20: ffffff800290e200 x19: 0000000000000000 x18: 0000000000000000 [ 6.822865] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 [ 6.823508] x14: ffffff8001820025 x13: 0000000000000007 x12: ffffff8001425480 [ 6.824155] x11: 0000000000000002 x10: 00000007305dcf59 x9 : 0000000000000000 [ 6.824787] x8 : ffffff80020328b8 x7 : 0000000000000000 x6 : 000000000000056c [ 6.825430] x5 : ffffffc008c23fb0 x4 : 0000000000000000 x3 : 0000000000000000 [ 6.826072] x2 : 0000000000000000 x1 : ffffff8001f65400 x0 : 00000000000027d8 [ 6.826715] Call trace: [ 6.826940] mutex_unlock+0xc/0x40 [ 6.827254] v4l2_open+0x98/0xec [ 6.827550] chrdev_open+0x158/0x164 [ 6.827875] do_dentry_open+0x2d4/0x350 [ 6.828231] vfs_open+0x28/0x30 [ 6.828520] path_openat+0x760/0x870 [ 6.828854] do_filp_open+0x38/0x88 Change-Id: I48b2e39f2e9a79efee7e63348e9dfc02889a02a1 Signed-off-by: Caesar Wang --- .../platform/rockchip/vpss/vpss_offline_v20.c | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c b/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c index fb00305e0a13..dbfbe05feddc 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c +++ b/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c @@ -2548,6 +2548,11 @@ static int ofl_open(struct file *file) struct rkvpss_offline_dev *ofl = video_drvdata(file); int ret; + if (!ofl || !ofl->hw) { + ret = -ENODEV; + goto end; + } + ret = v4l2_fh_open(file); if (ret) goto end; @@ -2555,13 +2560,18 @@ static int ofl_open(struct file *file) mutex_lock(&ofl->hw->dev_lock); ret = pm_runtime_get_sync(ofl->hw->dev); mutex_unlock(&ofl->hw->dev_lock); - if (ret < 0) + + if (ret < 0) { v4l2_fh_release(file); - else - ret = rkvpss_ofl_add_file_id(ofl, (void *)file); + goto end; + } + + ret = rkvpss_ofl_add_file_id(ofl, (void *)file); end: - v4l2_dbg(1, rkvpss_debug, &ofl->v4l2_dev, - "%s file:%p ret:%d\n", __func__, file, ret); + if (ofl) { + v4l2_dbg(1, rkvpss_debug, &ofl->v4l2_dev, + "%s file:%p ret:%d\n", __func__, file, ret); + } return (ret > 0) ? 0 : ret; }