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

scsi: ufs: fix potential bug which ends in system hang

In function __ufshcd_query_descriptor(), in the event of an error
happening, we directly goto out_unlock and forget to invaliate
hba->dev_cmd.query.descriptor pointer. This results in this pointer still
valid in ufshcd_copy_query_response() for other query requests which go
through ufshcd_exec_raw_upiu_cmd(). This will cause __memcpy() crash and
system hangs. Log as shown below:

Unable to handle kernel paging request at virtual address
ffff000012233c40
Mem abort info:
ESR = 0x96000047
Exception class = DABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
Data abort info:
ISV = 0, ISS = 0x00000047
CM = 0, WnR = 1
swapper pgtable: 4k pages, 48-bit VAs, pgdp = 0000000028cc735c
[ffff000012233c40] pgd=00000000bffff003, pud=00000000bfffe003,
pmd=00000000ba8b8003, pte=0000000000000000
Internal error: Oops: 96000047 [#2] PREEMPT SMP
...
Call trace:
__memcpy+0x74/0x180
ufshcd_issue_devman_upiu_cmd+0x250/0x3c0
ufshcd_exec_raw_upiu_cmd+0xfc/0x1a8
ufs_bsg_request+0x178/0x3b0
bsg_queue_rq+0xc0/0x118
blk_mq_dispatch_rq_list+0xb0/0x538
blk_mq_sched_dispatch_requests+0x18c/0x1d8
__blk_mq_run_hw_queue+0xb4/0x118
blk_mq_run_work_fn+0x28/0x38
process_one_work+0x1ec/0x470
worker_thread+0x48/0x458
kthread+0x130/0x138
ret_from_fork+0x10/0x1c
Code: 540000ab a8c12027 a88120c7 a8c12027 (a88120c7)
---[ end trace 793e1eb5dff69f2d ]---
note: kworker/0:2H[2054] exited with preempt_count 1

This patch is to move "descriptor = NULL" down to below the label
"out_unlock".

Fixes: d44a5f98bb49b2(ufs: query descriptor API)
Link: https://lore.kernel.org/r/20191112223436.27449-3-huobean@gmail.com
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Bean Huo <beanhuo@micron.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Bean Huo and committed by
Martin K. Petersen
cfcbae38 3d4881d1

+1 -1
+1 -1
drivers/scsi/ufs/ufshcd.c
··· 2989 2989 goto out_unlock; 2990 2990 } 2991 2991 2992 - hba->dev_cmd.query.descriptor = NULL; 2993 2992 *buf_len = be16_to_cpu(response->upiu_res.length); 2994 2993 2995 2994 out_unlock: 2995 + hba->dev_cmd.query.descriptor = NULL; 2996 2996 mutex_unlock(&hba->dev_cmd.lock); 2997 2997 out: 2998 2998 ufshcd_release(hba);