lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250928014631.2832243-2-yicongsrfy@163.com>
Date: Sun, 28 Sep 2025 09:46:31 +0800
From: yicongsrfy@....com
To: oliver@...kum.org,
	andrew+netdev@...n.ch,
	davem@...emloft.net,
	edumazet@...gle.com,
	kuba@...nel.org
Cc: marcan@...can.st,
	pabeni@...hat.com,
	linux-usb@...r.kernel.org,
	netdev@...r.kernel.org,
	yicong@...inos.cn
Subject: [PATCH 2/2] net: usb: support quirks in usbnet

From: Yi Cong <yicong@...inos.cn>

Some vendors' USB network interface controllers (NICs) may be compatible
with multiple drivers.

I consulted with relevant vendors. Taking the AX88179 chip as an example,
NICs based on this chip may be used across various OS—for instance,
cdc_ncm is used on macOS, while ax88179_178a.ko is the intended driver
on Linux (despite a previous patch having disabled it).
Therefore, the firmware must support multiple protocols.

Currently, both cdc_ncm and ax88179_178a coexist in the Linux kernel.
Supporting both drivers simultaneously leads to the following issues:

1. Inconsistent driver loading order during reboot stress testing:
   The order in which drivers are loaded can vary across reboots,
   potentially resulting in the unintended driver being loaded. For
   example:
[    4.239893] cdc_ncm 2-1:2.0: MAC-Address: c8:a3:62:ef:99:8e
[    4.239897] cdc_ncm 2-1:2.0: setting rx_max = 16384
[    4.240149] cdc_ncm 2-1:2.0: setting tx_max = 16384
[    4.240583] cdc_ncm 2-1:2.0 usb0: register 'cdc_ncm' at usb-
xxxxx:00-1, CDC NCM, c8:a3:62:ef:99:8e
[    4.240627] usbcore: registered new interface driver cdc_ncm
[    4.240908] usbcore: registered new interface driver ax88179_178a

In this case, network connectivity functions, but the cdc_ncm driver is
loaded instead of the expected ax88179_178a.

2. Similar issues during cable plug/unplug testing:
   The same race condition can occur when reconnecting the USB device:
[   79.879922] usb 4-1: new SuperSpeed USB device number 3 using xhci_hcd
[   79.905168] usb 4-1: New USB device found, idVendor=0b95, idProduct=
1790, bcdDevice= 2.00
[   79.905185] usb 4-1: New USB device strings: Mfr=1, Product=2,
SerialNumber=3
[   79.905191] usb 4-1: Product: AX88179B
[   79.905198] usb 4-1: Manufacturer: ASIX
[   79.905201] usb 4-1: SerialNumber: 00EF998E
[   79.915215] ax88179_probe, bConfigurationValue:2
[   79.952638] cdc_ncm 4-1:2.0: MAC-Address: c8:a3:62:ef:99:8e
[   79.952654] cdc_ncm 4-1:2.0: setting rx_max = 16384
[   79.952919] cdc_ncm 4-1:2.0: setting tx_max = 16384
[   79.953598] cdc_ncm 4-1:2.0 eth0: register 'cdc_ncm' at usb-0000:04:
00.2-1, CDC NCM (NO ZLP), c8:a3:62:ef:99:8e
[   79.954029] cdc_ncm 4-1:2.0 eth0: unregister 'cdc_ncm' usb-0000:04:
00.2-1, CDC NCM (NO ZLP)

At this point, the network becomes unusable.

To resolve these issues, introduce a *quirks* mechanism into the usbnet
module. By adding chip-specific identification within the generic usbnet
framework, we can skip the usbnet probe process for devices that require a
dedicated driver.

Signed-off-by: Yi Cong <yicong@...inos.cn>
---
 drivers/net/usb/cdc_ncm.c       |  2 +-
 drivers/net/usb/usbnet.c        | 14 +++++++++++
 drivers/net/usb/usbnet_quirks.h | 42 +++++++++++++++++++++++++++++++++
 include/linux/usb/usbnet.h      |  2 ++
 4 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/usb/usbnet_quirks.h

diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 5d123df0a866..6fa03e5bd054 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -2117,7 +2117,7 @@ MODULE_DEVICE_TABLE(usb, cdc_devs);
 static struct usb_driver cdc_ncm_driver = {
 	.name = "cdc_ncm",
 	.id_table = cdc_devs,
-	.probe = usbnet_probe,
+	.probe = usbnet_probe_quirks,
 	.disconnect = usbnet_disconnect,
 	.suspend = usbnet_suspend,
 	.resume = usbnet_resume,
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 511c4154cf74..51ba466057f9 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -31,6 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/pm_runtime.h>
 
+#include "usbnet_quirks.h"
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -1697,6 +1698,19 @@ static const struct device_type wwan_type = {
 	.name	= "wwan",
 };
 
+int usbnet_probe_quirks(struct usb_interface *udev,
+			const struct usb_device_id *prod)
+{
+	/* Should it be ignored? */
+	if (unlikely(usbnet_ignore(udev))) {
+		dev_dbg(&udev->dev, "usbnet ignore this device!\n");
+		return -ENODEV;
+	}
+
+	return usbnet_probe(udev, prod);
+}
+EXPORT_SYMBOL_GPL(usbnet_probe_quirks);
+
 int
 usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 {
diff --git a/drivers/net/usb/usbnet_quirks.h b/drivers/net/usb/usbnet_quirks.h
new file mode 100644
index 000000000000..85c29237f2b2
--- /dev/null
+++ b/drivers/net/usb/usbnet_quirks.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Operations on the network namespace
+ */
+
+#ifndef __USB_NET_IGNORE_H__
+#define __USB_NET_IGNORE_H__
+
+#include <linux/usb.h>
+
+/* usbnet_ignore_list:
+ * Chip info which already support int vendor specific driver,
+ * and then should be ignored in generic usbnet
+ */
+static const struct usb_device_id usbnet_ignore_list[] = {
+	/* Chips already support in ax88179_178a.c */
+	{ USB_DEVICE(0x0b95, 0x1790) },
+	{ USB_DEVICE(0x0b95, 0x178a) },
+	{ USB_DEVICE(0x04b4, 0x3610) },
+	{ USB_DEVICE(0x2001, 0x4a00) },
+	{ USB_DEVICE(0x0df6, 0x0072) },
+	{ USB_DEVICE(0x04e8, 0xa100) },
+	{ USB_DEVICE(0x17ef, 0x304b) },
+	{ USB_DEVICE(0x050d, 0x0128) },
+	{ USB_DEVICE(0x0930, 0x0a13) },
+	{ USB_DEVICE(0x0711, 0x0179) },
+	{ USB_DEVICE(0x07c9, 0x000e) },
+	{ USB_DEVICE(0x07c9, 0x000f) },
+	{ USB_DEVICE(0x07c9, 0x0010) },
+	/* End of support in ax88179_178a.c */
+
+	{ } /*END*/
+};
+
+static inline bool usbnet_ignore(struct usb_interface *intf)
+{
+	const struct usb_device_id *match = usb_match_id(intf,
+							 usbnet_ignore_list);
+
+	return match == NULL ? false : true;
+}
+#endif
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index a2d54122823d..de198fcaf76d 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -188,6 +188,8 @@ struct driver_info {
  * much everything except custom framing and chip-specific stuff.
  */
 extern int usbnet_probe(struct usb_interface *, const struct usb_device_id *);
+extern int usbnet_probe_quirks(struct usb_interface *udev,
+			       const struct usb_device_id *prod);
 extern int usbnet_suspend(struct usb_interface *, pm_message_t);
 extern int usbnet_resume(struct usb_interface *);
 extern void usbnet_disconnect(struct usb_interface *);
-- 
2.25.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ