github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/syz-usbgen/usb_ids.patch (about) 1 From a5c949b813199bc14e264e1440358e95b96954c9 Mon Sep 17 00:00:00 2001 2 From: Pavel Skripkin <paskripkin@gmail.com> 3 Date: Tue, 7 Sep 2021 22:55:33 +0300 4 Subject: [PATCH] usb: dump usb device ids on hid enumeration 5 6 Signed-off-by: Andrey Konovalov <andreyknvl@google.com> 7 Signed-off-by: Pavel Skripkin <paskripkin@gmail.com> 8 --- 9 drivers/hid/hid-core.c | 105 +++++++++++++++++++++++++++++++++++++++++ 10 1 file changed, 105 insertions(+) 11 12 diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c 13 index 7db332139f7d..e1231e2b1610 100644 14 --- a/drivers/hid/hid-core.c 15 +++ b/drivers/hid/hid-core.c 16 @@ -27,6 +27,8 @@ 17 #include <linux/vmalloc.h> 18 #include <linux/sched.h> 19 #include <linux/semaphore.h> 20 +#include <linux/usb.h> 21 +#include "../usb/core/usb.h" 22 23 #include <linux/hid.h> 24 #include <linux/hiddev.h> 25 @@ -2192,11 +2194,114 @@ static void hid_free_dynids(struct hid_driver *hdrv) 26 spin_unlock(&hdrv->dyn_lock); 27 } 28 29 +static void hid_device_id_dump_one(const struct hid_device_id *id) 30 +{ 31 + char buffer[128]; 32 + int size = (char *)&id->product + sizeof(id->product) - (char *)id; 33 + 34 + if (id->bus != HID_BUS_ANY && id->bus != BUS_USB) 35 + return; 36 + 37 + bin2hex((char *)&buffer[0], (const char *)id, size); 38 + buffer[size * 2] = 0; 39 + pr_err("HIDID: %s\n", &buffer[0]); 40 +} 41 + 42 +static void hid_device_id_dump_static(struct hid_driver *hdrv) 43 +{ 44 + const struct hid_device_id *id = hdrv->id_table; 45 + 46 + for (; id->bus; id++) 47 + hid_device_id_dump_one(id); 48 +} 49 + 50 +static void hid_device_id_dump_dynamic(struct hid_driver *hdrv) 51 +{ 52 + struct hid_dynid *dynid; 53 + 54 + spin_lock(&hdrv->dyn_lock); 55 + list_for_each_entry(dynid, &hdrv->dyn_list, list) 56 + hid_device_id_dump_one(&dynid->id); 57 + spin_unlock(&hdrv->dyn_lock); 58 +} 59 + 60 +static int hid_device_id_dump_driver(struct device_driver *drv, void *data) 61 +{ 62 + struct hid_driver *hdrv = to_hid_driver(drv); 63 + 64 + hid_device_id_dump_static(hdrv); 65 + hid_device_id_dump_dynamic(hdrv); 66 + 67 + return 0; 68 +} 69 + 70 +static void usb_device_id_dump_one(const struct usb_device_id *id) 71 +{ 72 + char buffer[128]; 73 + int size = (char *)&id->bInterfaceNumber + sizeof(id->bInterfaceNumber) 74 + - (char *)id; 75 + 76 + bin2hex((char *)&buffer[0], (const char *)id, size); 77 + buffer[size * 2] = 0; 78 + pr_err("USBID: %s\n", &buffer[0]); 79 +} 80 + 81 +static void usb_device_id_dump_static(struct usb_driver *drv) 82 +{ 83 + const struct usb_device_id *id = drv->id_table; 84 + 85 + if (id == NULL) 86 + return; 87 + 88 + for (; id->idVendor || id->idProduct || id->bDeviceClass || 89 + id->bInterfaceClass || id->driver_info; id++) 90 + usb_device_id_dump_one(id); 91 +} 92 + 93 +static void usb_device_id_dump_dynamic(struct usb_driver *drv) 94 +{ 95 + struct usb_dynid *dynid; 96 + 97 + spin_lock(&drv->dynids.lock); 98 + list_for_each_entry(dynid, &drv->dynids.list, node) 99 + usb_device_id_dump_one(&dynid->id); 100 + spin_unlock(&drv->dynids.lock); 101 +} 102 + 103 +static int usb_device_id_dump_driver(struct device_driver *drv, void *data) 104 +{ 105 + struct usb_driver *usb_drv; 106 + 107 + if (is_usb_device_driver(drv)) 108 + return 0; 109 + usb_drv = to_usb_driver(drv); 110 + 111 + usb_device_id_dump_static(usb_drv); 112 + usb_device_id_dump_dynamic(usb_drv); 113 + 114 + return 0; 115 +} 116 + 117 +static int usb_ids_dumped; 118 + 119 +struct bus_type hid_bus_type; 120 + 121 +static void usb_device_id_dump_all(void) 122 +{ 123 + if (usb_ids_dumped) 124 + return; 125 + usb_ids_dumped = 1; 126 + bus_for_each_drv(&usb_bus_type, NULL, NULL, usb_device_id_dump_driver); 127 + bus_for_each_drv(&hid_bus_type, NULL, NULL, hid_device_id_dump_driver); 128 +} 129 + 130 const struct hid_device_id *hid_match_device(struct hid_device *hdev, 131 struct hid_driver *hdrv) 132 { 133 struct hid_dynid *dynid; 134 135 + usb_device_id_dump_all(); 136 + 137 spin_lock(&hdrv->dyn_lock); 138 list_for_each_entry(dynid, &hdrv->dyn_list, list) { 139 if (hid_match_one_id(hdev, &dynid->id)) { 140 -- 141 2.33.0 142