From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f173.google.com (mail-pl1-f173.google.com [209.85.214.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0212923D28C for ; Sat, 15 Aug 2026 14:34:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.173 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786804485; cv=none; b=cXBTG29rQUxDwMc5APd9A2go3y2rO1OE8RMdbnJtEHRNaEVUhxcBSHcX+nfz4FGwCsV/Rca8Dw5TEoCRqeGFF6emX9ZPnPPUp2ZjQ2SrCZYURkak9VKhGk14g973t4XZEO/aOoadG2w5nfF9Os1U7pEdZNl1lgXRoh2WknALvBk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786804485; c=relaxed/simple; bh=8AAYfkIw/WPcobF9fvgpeSR3p+vRUhuIMV5BpImoUFc=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=q/DoTXRtFE1MJp8Th6tv3rdQ7DFj1/yevudl8M6141j59t77CqOK1OUkExXHHKqmW1gfT90qiSCzJ/weuCc+5/tWdnHK5oMyXkExnu2y1XOZw2G7FeMSH5aCa2ierTbsnAJ7jSDNz0lDo/yBnnWRmvACR3wv450WHgfXPIBnQww= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=VDbofz1U; arc=none smtp.client-ip=209.85.214.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VDbofz1U" Received: by mail-pl1-f173.google.com with SMTP id d9443c01a7336-2d02b4c3601so22756665ad.3 for ; Sat, 15 Aug 2026 07:34:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786804483; x=1787409283; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=mB13gFyb5oo+TFN7lavVIm84ZMLZ6Hndr2bjKO1MQL0=; b=VDbofz1UxV6ZZ8KnubVK0NWK/pWOiO588KQUehIdJhaj/xLx9pN1xRNTMBQ6zv1qtB 7Rw1sbpJ6lIy/2TEGMzI6oTR1t+G0Ks/m2g30BtvMocYi9UGekt42UyPdQ7MpE2R/Y3x lx5MtuIFA7vlJHZCYi/R08vlIsCRNQuVb/eiFbTBzqCKkWJftc0s8wOL8pydXuyVmYmR XvQsaZw8MN/NyTIOuT/gvoKpaTUI2tgBH7joCMs38FwjTddJI5Q49radDEfxSwCfp3F9 kloYUBA6pD9dmBe3Ct3LKvSBeyQaiF5GT12veVTNZfHASYaU8iQcFEeqMLBFaKo167Da GnTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786804483; x=1787409283; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=mB13gFyb5oo+TFN7lavVIm84ZMLZ6Hndr2bjKO1MQL0=; b=flV0GmaWxyFtV3I4jY0u+cM8l6M+atqPvhuKzuHTxLl/mEl6EObvn5RbRQ+7cnoAIQ xQXg8lN8OWug6x/dduDU5yYyjiYxRFV9r80YjnKbam9mFpQ3PDl7sMjy+ok1hegocGua 04PtrJkVB8OP/rcopfiuxnQ7/mmxqWf8PRzt5cyyLCGQAwm/fZCMA43mnLCwEfM6s0HS m073bG7fsIiEcynU03eAYjc8VqZh5hzOYrAOC6gYfou2RDzVrbOXxWPnW+aJUTHmdf2Y mFj8xNSps86ivQHMEejQQyNzBIcu0mgX+4wm9PFTFFFgJEwlSRNrJzE/NGHy1aa/tYJm SfZg== X-Forwarded-Encrypted: i=1; AHgh+RoneBO6sZNN4oMdGe76yaz4HupdgFo7faNiszwY9rW4BdcowlGGZmifAum2SLdPp55+DlNjeJxrNa5k9wc=@vger.kernel.org X-Gm-Message-State: AOJu0YylDDB7cwKXjJOfXf8SJos92FbfU8cn/R7v86zFbuOfBrPxYeRU BJcmmbxDA+vS/LwXuXSzCJ6ACJprqofjppk7mZLzW1aQC4eS5ngfkwwR X-Gm-Gg: AR+sD10AaiG/+FccIJnQa+RXY7qUgMhhWbu8uHhRnI0vEGcKW7bAvquBoqCwPkgCkZ5 7r2a18HoopcpvKZ4ZqBHMW/Xw4Nocf3tY5N9cz7eJxy9ZyPbRDTuVv39nWXh6jGM8HN0vwMb4hZ +5J3N1R7y33nNpaJ4+GRURz+dM58JEnVd1dKRIg3Uc484/Hjhjau843KQK6PDUQo0i7pdU73p2y 1bwAH/7upoZrfW4HOSFMZYrMuMTmllhmuhoRzZIEUiydrxibxyWr2iIGxiSkyiklqGknM4jSz2f QLbIMnXJdFTthN4xFCivvYNZAGc/VF66pWuoIvAWmHVJqez71UA3Da5qAvq4CSPI75bYfEOttlh 7d12vEZuDvJBlUE3Jw4XjL9+RePehHrbgzHWEb4p9FIho+7bbT/e3TMSqqYh+LxprUorwbGv3hD AHstgyr6M/l46RJoJ2KB4QsoFVee/PvP64M953DxzxjCMRTZbsqbBsx2kRk6VdwwItVmE1uKQBX zp1SplTjBZvANleLSU7AecEBsBq1DZ6roP+ffMp8fMuN7x91lxfvA== X-Received: by 2002:a17:90b:3147:b0:38d:f5bb:e0f4 with SMTP id 98e67ed59e1d1-3933b6f1c52mr13670076a91.1.1786804483369; Sat, 15 Aug 2026 07:34:43 -0700 (PDT) Received: from deepanshu-Legion-Pro-5-16AFR10.. ([2405:201:682f:383f:23b8:ec2e:1238:f3ad]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-1413889d914sm20498490c88.13.2026.08.15.07.34.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 15 Aug 2026 07:34:42 -0700 (PDT) From: Deepanshu Kartikey To: valentina.manea.m@gmail.com, shuah@kernel.org, i@zenithal.me, gregkh@linuxfoundation.org Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Deepanshu Kartikey , syzbot+8753715f05759f1a10de@syzkaller.appspotmail.com Subject: [PATCH] usbip: vhci_hcd: move sysfs attribute setup into probe/remove Date: Sat, 15 Aug 2026 20:04:27 +0530 Message-ID: <20260815143427.19066-1-kartikey406@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The vhci sysfs attribute group is created in vhci_start() and removed in vhci_stop(), guarded by usb_hcd_is_primary_hcd(). Since vhci_start() and vhci_stop() run from usb_add_hcd()/usb_remove_hcd(), which are each called twice, the attach attribute is live while only one of the two hcds exists: it is created during the first usb_add_hcd() before vhci_hcd_ss is set, and it survives the first usb_put_hcd() during removal. A concurrent write to attach can therefore reach a NULL or freed vhci_hcd_ss. Create the group at the end of vhci_hcd_probe(), after both hcds are added, and remove it at the start of vhci_hcd_remove(), before either reference is dropped. sysfs_remove_group() drains in-flight store callbacks, so no writer can be inside attach_store() once it returns. Reported-by: syzbot+8753715f05759f1a10de@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=8753715f05759f1a10de Tested-by: syzbot+8753715f05759f1a10de@syzkaller.appspotmail.com Signed-off-by: Deepanshu Kartikey --- drivers/usb/usbip/vhci_hcd.c | 66 ++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index 39e8faf4c18c..90f166f3ae96 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -1199,7 +1199,6 @@ static int vhci_start(struct usb_hcd *hcd) { struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd); int id, rhport; - int err; usbip_dbg_vhci_hc("enter vhci_start\n"); @@ -1230,40 +1229,17 @@ static int vhci_start(struct usb_hcd *hcd) return -EINVAL; } - /* vhci_hcd is now ready to be controlled through sysfs */ - if (id == 0 && usb_hcd_is_primary_hcd(hcd)) { - err = vhci_init_attr_group(); - if (err) { - dev_err(hcd_dev(hcd), "init attr group failed, err = %d\n", err); - return err; - } - err = sysfs_create_group(&hcd_dev(hcd)->kobj, &vhci_attr_group); - if (err) { - dev_err(hcd_dev(hcd), "create sysfs files failed, err = %d\n", err); - vhci_finish_attr_group(); - return err; - } - dev_info(hcd_dev(hcd), "created sysfs %s\n", hcd_name(hcd)); - } - return 0; } static void vhci_stop(struct usb_hcd *hcd) { struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd); - int id, rhport; + int rhport; usbip_dbg_vhci_hc("stop VHCI controller\n"); - /* 1. remove the userland interface of vhci_hcd */ - id = hcd_name_to_id(hcd_name(hcd)); - if (id == 0 && usb_hcd_is_primary_hcd(hcd)) { - sysfs_remove_group(&hcd_dev(hcd)->kobj, &vhci_attr_group); - vhci_finish_attr_group(); - } - - /* 2. shutdown all the ports of vhci_hcd */ + /* shutdown all the ports of vhci_hcd */ for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) { struct vhci_device *vdev = &vhci_hcd->vdev[rhport]; @@ -1405,8 +1381,25 @@ static int vhci_hcd_probe(struct platform_device *pdev) } usbip_dbg_vhci_hc("bye\n"); + + if (pdev->id == 0) { + ret = vhci_init_attr_group(); + if (ret) { + dev_err_probe(&pdev->dev, ret, "init attr group failed\n"); + goto remove_usb3_hcd; + } + ret = sysfs_create_group(&pdev->dev.kobj, &vhci_attr_group); + if (ret) { + dev_err_probe(&pdev->dev, ret, "create sysfs files failed\n"); + vhci_finish_attr_group(); + goto remove_usb3_hcd; + } + } + return 0; +remove_usb3_hcd: + usb_remove_hcd(hcd_ss); put_usb3_hcd: usb_put_hcd(hcd_ss); remove_usb2_hcd: @@ -1421,17 +1414,30 @@ static int vhci_hcd_probe(struct platform_device *pdev) static void vhci_hcd_remove(struct platform_device *pdev) { struct vhci *vhci = *((void **)dev_get_platdata(&pdev->dev)); + struct usb_hcd *hcd_hs = vhci_hcd_to_hcd(vhci->vhci_hcd_hs); + struct usb_hcd *hcd_ss = vhci_hcd_to_hcd(vhci->vhci_hcd_ss); + + /* + * Remove the userland interface before dropping the hcd references. + * sysfs_remove_group() waits for in-flight attach_store()/detach_store() + * callers to return and rejects new ones, so neither hcd can be reached + * from sysfs by the time it is freed below. + */ + if (pdev->id == 0) { + sysfs_remove_group(&pdev->dev.kobj, &vhci_attr_group); + vhci_finish_attr_group(); + } /* * Disconnects the root hub, * then reverses the effects of usb_add_hcd(), * invoking the HCD's stop() methods. */ - usb_remove_hcd(vhci_hcd_to_hcd(vhci->vhci_hcd_ss)); - usb_put_hcd(vhci_hcd_to_hcd(vhci->vhci_hcd_ss)); + usb_remove_hcd(hcd_ss); + usb_put_hcd(hcd_ss); - usb_remove_hcd(vhci_hcd_to_hcd(vhci->vhci_hcd_hs)); - usb_put_hcd(vhci_hcd_to_hcd(vhci->vhci_hcd_hs)); + usb_remove_hcd(hcd_hs); + usb_put_hcd(hcd_hs); vhci->vhci_hcd_hs = NULL; vhci->vhci_hcd_ss = NULL; -- 2.43.0