From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-m155101.qiye.163.com (mail-m155101.qiye.163.com [101.71.155.101]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 748243BD63C for ; Tue, 28 Jul 2026 06:56:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=101.71.155.101 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785221763; cv=none; b=Gf2AtRByYLPf/CNNpz7XD5GI3+zMNXHX668gsR3HkwG4I4BNlNXgaLcWZO3rtVXevzWb+iXgPxruB5P6nOCX8FeKLeZcBwCVspaC2CEDnnPEy9ek5mcpG4YFTY8gUJ26Rp48DrzUjP2KPgQBNfv233y6OBQCi5ZOqDHlREAkxV4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785221763; c=relaxed/simple; bh=2naNoMivn0vRG3jWZKdZZIkm1PtkeAjGQbmEwRoLppk=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=O8oNYC18sh0E5tSLobqrdPDWLH+au7vUn4hMREmxv6Tu4BI2ErySc8j5TVv3PlhvtocVM7RpW/KmOWDMq0gY0dmaSKLkSbil/Bt3npQEUucs8XFl8a+KkycAXz7GFOKF/3xnh2nvGBsmz4t7tEiP0LFYY7Xc8hHQP6NpT39YdEs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=seu.edu.cn; spf=pass smtp.mailfrom=seu.edu.cn; dkim=pass (1024-bit key) header.d=seu.edu.cn header.i=@seu.edu.cn header.b=CrtKUFE4; arc=none smtp.client-ip=101.71.155.101 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=seu.edu.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=seu.edu.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=seu.edu.cn header.i=@seu.edu.cn header.b="CrtKUFE4" Received: from LAPTOP-99KJFSET (unknown [222.191.246.242]) by smtp.qiye.163.com (Hmail) with ESMTP id 47d3f7936; Tue, 28 Jul 2026 14:55:58 +0800 (GMT+08:00) From: Hongyan Xu To: John Stultz , Arnd Bergmann , Greg Kroah-Hartman Cc: linux-kernel@vger.kernel.org, jianhao.xu@seu.edu.cn, getshell@seu.edu.cn Subject: [PATCH] misc: hisi_hikey_usb: cancel role switch work on remove Date: Tue, 28 Jul 2026 14:55:58 +0800 Message-ID: <20260728065558.1532-1-getshell@seu.edu.cn> X-Mailer: git-send-email 2.50.1.windows.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-HM-Tid: 0a9fa7823c3c03a1kunm5dcca8cde42d6 X-HM-MType: 10 X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFITzdXWRgWCB1ZQUpXWS1ZQUlXWQ8JGhUIEh9ZQVkZGBoYVk1KGR1IHU5CTxgaS1YeHw 5VEwETFhoSFyQUDg9ZV1kYEgtZQVlJSUlVSkJKVUlPTVVJT0lZV1kWGg8SFR0UWUFZT0tIVUpLSU hOQ0NVSktLVUtZBg++ DKIM-Signature: a=rsa-sha256; b=CrtKUFE4U7UTP5JbcYwnzsqIVYSkMvNDxVyXN/OIvGlw4ZrBX4J4qy0oGkpMv+Rr+RfZoMJ932Iclk7dZkK3zu/613whei1/vnZse5bjRY2GG9YaMn1FEABNqzV/SZh2PNUHUJmzsB0q5tHJtC7+R7mlOev/31fBDiZ1Nwm9azQ=; s=default; c=relaxed/relaxed; d=seu.edu.cn; v=1; bh=GeHhDN2fSblgtkCuARRcSljm/H5tdQbmdyAoCCA01SQ=; h=date:mime-version:subject:message-id:from; The hub role switch set callback schedules private work that dereferences both driver data and the downstream role switch. Unregistering the hub switch does not drain work already queued, and a callback that fetched driver data before unregister can queue more work during removal. Mark the instance as removing under its mutex and serialize removal with role switch set callbacks by setting the role to USB_ROLE_NONE. The callback clears the switch driver data when it observes removal and no longer queues work. Unregister the switch, cancel the work, and only then drop the downstream role switch reference. This issue was found by a static analysis tool. Signed-off-by: Hongyan Xu --- drivers/misc/hisi_hikey_usb.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c index 2165ec3..9db6429 100644 --- a/drivers/misc/hisi_hikey_usb.c +++ b/drivers/misc/hisi_hikey_usb.c @@ -45,6 +45,7 @@ struct hisi_hikey_usb { struct mutex lock; struct work_struct work; + bool removing; struct notifier_block nb; }; @@ -130,17 +131,23 @@ static void relay_set_role_switch(struct work_struct *work) static int hub_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role role) { struct hisi_hikey_usb *hisi_hikey_usb = usb_role_switch_get_drvdata(sw); + int ret = 0; - if (!hisi_hikey_usb || !hisi_hikey_usb->dev_role_sw) - return -EINVAL; + if (!hisi_hikey_usb) + return -ENODEV; mutex_lock(&hisi_hikey_usb->lock); - hisi_hikey_usb->role = role; + if (hisi_hikey_usb->removing || !hisi_hikey_usb->dev_role_sw) { + if (hisi_hikey_usb->removing) + usb_role_switch_set_drvdata(sw, NULL); + ret = -ENODEV; + } else { + hisi_hikey_usb->role = role; + schedule_work(&hisi_hikey_usb->work); + } mutex_unlock(&hisi_hikey_usb->lock); - schedule_work(&hisi_hikey_usb->work); - - return 0; + return ret; } static int hisi_hikey_usb_of_role_switch(struct platform_device *pdev, @@ -244,7 +251,15 @@ static int hisi_hikey_usb_remove(struct platform_device *pdev) struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev); if (hisi_hikey_usb->hub_role_sw) { + mutex_lock(&hisi_hikey_usb->lock); + hisi_hikey_usb->removing = true; + mutex_unlock(&hisi_hikey_usb->lock); + + /* Serialize with set callbacks and clear their private data. */ + usb_role_switch_set_role(hisi_hikey_usb->hub_role_sw, + USB_ROLE_NONE); usb_role_switch_unregister(hisi_hikey_usb->hub_role_sw); + cancel_work_sync(&hisi_hikey_usb->work); if (hisi_hikey_usb->dev_role_sw) usb_role_switch_put(hisi_hikey_usb->dev_role_sw); -- 2.50.1.windows.1