aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@gmail.com>2025-08-17 14:53:44 +0000
committerAleksandr Nogikh <nogikh@google.com>2025-08-21 12:29:58 +0000
commit5ec502e031c3ca7cad5ac0aa468469b7b9b85d1d (patch)
tree2904dc7b5bdfa922285d36d577b844a359b47427 /tools
parent32aa395ffd5035ed3d563077ade0202f3d5eb516 (diff)
tools/usbgen: extract driver names
Change the kernel patch and the syz-usbgen tool to split the extracted USB IDs by the driver they belong to. This will allow for a more precise patching of class/driver-specific USB descriptors. Also update USB IDs with Linux kernel 6.16.
Diffstat (limited to 'tools')
-rw-r--r--tools/syz-usbgen/usb_ids.patch30
-rw-r--r--tools/syz-usbgen/usbgen.go83
2 files changed, 74 insertions, 39 deletions
diff --git a/tools/syz-usbgen/usb_ids.patch b/tools/syz-usbgen/usb_ids.patch
index 3d373c509..9699f20b9 100644
--- a/tools/syz-usbgen/usb_ids.patch
+++ b/tools/syz-usbgen/usb_ids.patch
@@ -1,13 +1,13 @@
-commit 0b9540c5b3cb5e34af4cdc1f6828314a041f8d1a
+commit ea2ac1d4c7632717bac2410cfde8a2971aac65af
Author: Andrey Konovalov <andreyknvl@gmail.com>
-Date: Thu Jul 25 00:26:01 2024 +0200
+Date: Sun Aug 17 14:49:51 2025 +0000
- usb: dump usb and hid device ids on hid enumeration
+ usb: dump USB and HID device IDs on HID enumeration
Signed-off-by: Andrey Konovalov <andreyknvl@gmail.com>
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
-index 74efda212c55f..d2f1f9243638e 100644
+index b31b8a2fd..4893fcb4a 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -27,6 +27,8 @@
@@ -19,11 +19,11 @@ index 74efda212c55f..d2f1f9243638e 100644
#include <linux/hid.h>
#include <linux/hiddev.h>
-@@ -2544,11 +2546,112 @@ static void hid_free_dynids(struct hid_driver *hdrv)
+@@ -2632,11 +2634,112 @@ static void hid_free_dynids(struct hid_driver *hdrv)
spin_unlock(&hdrv->dyn_lock);
}
-+static void hid_device_id_dump_one(const struct hid_device_id *id)
++static void hid_device_id_dump_one(const struct hid_device_id *id, const char *driver_name)
+{
+ char buffer[128];
+ int size = (char *)&id->product + sizeof(id->product) - (char *)id;
@@ -33,7 +33,7 @@ index 74efda212c55f..d2f1f9243638e 100644
+
+ bin2hex((char *)&buffer[0], (const char *)id, size);
+ buffer[size * 2] = 0;
-+ pr_err("HIDID: %s\n", &buffer[0]);
++ pr_err("HIDID: %s (%s)\n", &buffer[0], driver_name);
+}
+
+static void hid_device_id_dump_static(struct hid_driver *hdrv)
@@ -41,7 +41,7 @@ index 74efda212c55f..d2f1f9243638e 100644
+ const struct hid_device_id *id = hdrv->id_table;
+
+ for (; id->bus; id++)
-+ hid_device_id_dump_one(id);
++ hid_device_id_dump_one(id, hdrv->name);
+}
+
+static void hid_device_id_dump_dynamic(struct hid_driver *hdrv)
@@ -50,7 +50,7 @@ index 74efda212c55f..d2f1f9243638e 100644
+
+ spin_lock(&hdrv->dyn_lock);
+ list_for_each_entry(dynid, &hdrv->dyn_list, list)
-+ hid_device_id_dump_one(&dynid->id);
++ hid_device_id_dump_one(&dynid->id, hdrv->name);
+ spin_unlock(&hdrv->dyn_lock);
+}
+
@@ -64,7 +64,7 @@ index 74efda212c55f..d2f1f9243638e 100644
+ return 0;
+}
+
-+static void usb_device_id_dump_one(const struct usb_device_id *id)
++static void usb_device_id_dump_one(const struct usb_device_id *id, const char *driver_name)
+{
+ char buffer[128];
+ int size = (char *)&id->bInterfaceNumber + sizeof(id->bInterfaceNumber)
@@ -72,7 +72,7 @@ index 74efda212c55f..d2f1f9243638e 100644
+
+ bin2hex((char *)&buffer[0], (const char *)id, size);
+ buffer[size * 2] = 0;
-+ pr_err("USBID: %s\n", &buffer[0]);
++ pr_err("USBID: %s (%s)\n", &buffer[0], driver_name);
+}
+
+static void usb_device_id_dump_static(struct usb_driver *drv)
@@ -84,17 +84,17 @@ index 74efda212c55f..d2f1f9243638e 100644
+
+ for (; id->idVendor || id->idProduct || id->bDeviceClass ||
+ id->bInterfaceClass || id->driver_info; id++)
-+ usb_device_id_dump_one(id);
++ usb_device_id_dump_one(id, drv->name);
+}
+
+static void usb_device_id_dump_dynamic(struct usb_driver *drv)
+{
+ struct usb_dynid *dynid;
+
-+ spin_lock(&drv->dynids.lock);
++ mutex_lock(&usb_dynids_lock);
+ list_for_each_entry(dynid, &drv->dynids.list, node)
-+ usb_device_id_dump_one(&dynid->id);
-+ spin_unlock(&drv->dynids.lock);
++ usb_device_id_dump_one(&dynid->id, drv->name);
++ mutex_unlock(&usb_dynids_lock);
+}
+
+static int usb_device_id_dump_driver(struct device_driver *drv, void *data)
diff --git a/tools/syz-usbgen/usbgen.go b/tools/syz-usbgen/usbgen.go
index e77ff7a59..5d21216fe 100644
--- a/tools/syz-usbgen/usbgen.go
+++ b/tools/syz-usbgen/usbgen.go
@@ -45,48 +45,83 @@ package linux
}
}
-func extractIds(syslog []byte, prefix string, size int) []string {
- re := fmt.Sprintf("%s: [0-9a-f]{%d}", prefix, size)
+func extractIds(syslog []byte, prefix string, size int) map[string][]string {
+ re := fmt.Sprintf("%s: ([0-9a-f]{%d}) \\((.+)\\)", prefix, size)
r := regexp.MustCompile(re)
- matches := r.FindAll(syslog, -1)
- uniqueMatches := make(map[string]bool)
+ matches := r.FindAllSubmatch(syslog, -1)
+ // Map from matching substring to capture groups.
+ uniqueMatches := make(map[string][][]byte)
for _, match := range matches {
- uniqueMatches[string(match)] = true
+ uniqueMatches[string(match[0])] = match[1:]
}
- sortedMatches := make([]string, 0)
- for match := range uniqueMatches {
- match = match[len(prefix+": "):]
- match = match[:size]
- sortedMatches = append(sortedMatches, match)
+ // Map from driver name to slice of USB IDs.
+ driverIDs := make(map[string][]string, 0)
+ for _, groups := range uniqueMatches {
+ id := string(groups[0])
+ driver := string(groups[1])
+ driverIDs[driver] = append(driverIDs[driver], id)
}
- sort.Strings(sortedMatches)
- return sortedMatches
+ // Keep IDs sorted for consistent output between runs.
+ for driver := range driverIDs {
+ sort.Strings(driverIDs[driver])
+ }
+ return driverIDs
}
-func generateIdsVar(ids []string, name string) []byte {
- output := []byte(fmt.Sprintf("var %s = ", name))
- for i, id := range ids {
- decodedID, err := hex.DecodeString(id)
- if err != nil {
- tool.Failf("failed to decode hex string %v: %v", id, err)
+func generateIdsVar(driverIDs map[string][]string, name string) []byte {
+ // Sort driver names for consistent output between runs.
+ drivers := make([]string, 0, len(driverIDs))
+ for driver := range driverIDs {
+ drivers = append(drivers, driver)
+ }
+ sort.Strings(drivers)
+
+ // Generate a map variable that stores USB IDs for each driver.
+ totalIDs := 0
+ output := []byte(fmt.Sprintf("var %s = map[string]string{\n", name))
+ for _, driver := range drivers {
+ ids := driverIDs[driver]
+ outputDriver := fmt.Sprintf("\t\"%s\": ", driver)
+ output = append(output, []byte(outputDriver)...)
+ for i, id := range ids {
+ decodedID, err := hex.DecodeString(id)
+ if err != nil {
+ tool.Failf("failed to decode hex string %v: %v", id, err)
+ }
+ prefix := "\t\t"
+ suffix := " +"
+ if i == 0 {
+ prefix = ""
+ }
+ if i == len(ids)-1 {
+ suffix = ","
+ }
+ outputID := fmt.Sprintf("%v%#v%v\n", prefix, string(decodedID), suffix)
+ output = append(output, []byte(outputID)...)
}
+ totalIDs += len(ids)
+ }
+ output = append(output, []byte("}\n\n")...)
+
+ // Generate a variable that stores all USB IDs together.
+ output = append(output, []byte(fmt.Sprintf("var %sAll = ", name))...)
+ for i, driver := range drivers {
prefix := "\t"
suffix := " +"
if i == 0 {
prefix = ""
}
- if i == len(ids)-1 {
+ if i == len(drivers)-1 {
suffix = ""
}
- outputID := fmt.Sprintf("%v%#v%v\n", prefix, string(decodedID), suffix)
- output = append(output, []byte(outputID)...)
+ outputDriver := fmt.Sprintf("%v%s[\"%s\"]%v\n", prefix, name, driver, suffix)
+ output = append(output, []byte(outputDriver)...)
}
-
- if len(ids) == 0 {
+ if len(drivers) == 0 {
output = append(output, []byte("\"\"")...)
}
- fmt.Printf("%v %s ids written\n", len(ids), name)
+ fmt.Printf("%v %s ids written\n", totalIDs, name)
return output
}