[PATCH v3 6/8] HID: wacom: cleanup usage of 'driver_data'
"Pawel Zalewski (The Capable Hub)" <[email protected]>
| Newsgroups | org.kernel.vger.linux-input,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260727-mod-devicetable-hid_device_id-v3-6-980896ca283e@thegoodpenguin.co.uk> |
This module is using the 'hid_device_id::driver_data' field as a valid pointer to dereference. The hid subsystem allows for injecting 'new_id' device via the command line. It follows that it is more convenient to have 'driver_data' to be an integer to allow the userspace to select a valid pointer via an index. Lets enable this and store an index to the table of pointers 'wacom_features_table' instead, the access to this table is bounded and checked at runtime via the 'wacom_features_table_index' enum to avoid OOB dereferencing of objects. The implementation relies heavily on the preprocessor - but given the large amount of required entries (162) this is justified, more robust and more resilient to user error than manual input. Signed-off-by: Pawel Zalewski (The Capable Hub) <[email protected]> --- drivers/hid/wacom.h | 177 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/hid/wacom_sys.c | 22 ++++-- drivers/hid/wacom_wac.c | 25 +++++-- 3 files changed, 214 insertions(+), 10 deletions(-) diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 1deacb4568cb..115d0eb23277 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -228,6 +228,182 @@ static inline u32 wacom_rescale(u32 value, u32 in_max, u32 out_max) extern const struct hid_device_id wacom_ids[]; +/* This table lists all unique product IDs that are matched with + * a corresponging wacom_features_##prod struct. So any new product + * should be added to this table. + */ +#define HID_WACOM_PRODUCT_TABLE() \ + table_entry(0x00) \ + table_entry(0x03) \ + table_entry(0x10) \ + table_entry(0x11) \ + table_entry(0x12) \ + table_entry(0x13) \ + table_entry(0x14) \ + table_entry(0x15) \ + table_entry(0x16) \ + table_entry(0x17) \ + table_entry(0x18) \ + table_entry(0x19) \ + table_entry(0x20) \ + table_entry(0x21) \ + table_entry(0x22) \ + table_entry(0x23) \ + table_entry(0x24) \ + table_entry(0x26) \ + table_entry(0x27) \ + table_entry(0x28) \ + table_entry(0x29) \ + table_entry(0x2A) \ + table_entry(0x30) \ + table_entry(0x31) \ + table_entry(0x32) \ + table_entry(0x33) \ + table_entry(0x34) \ + table_entry(0x35) \ + table_entry(0x37) \ + table_entry(0x38) \ + table_entry(0x39) \ + table_entry(0x3F) \ + table_entry(0x41) \ + table_entry(0x42) \ + table_entry(0x43) \ + table_entry(0x44) \ + table_entry(0x45) \ + table_entry(0x47) \ + table_entry(0x57) \ + table_entry(0x59) \ + table_entry(0x5B) \ + table_entry(0x5D) \ + table_entry(0x5E) \ + table_entry(0x60) \ + table_entry(0x61) \ + table_entry(0x62) \ + table_entry(0x63) \ + table_entry(0x64) \ + table_entry(0x65) \ + table_entry(0x69) \ + table_entry(0x6A) \ + table_entry(0x6B) \ + table_entry(0x81) \ + table_entry(0x84) \ + table_entry(0x90) \ + table_entry(0x93) \ + table_entry(0x94) \ + table_entry(0x97) \ + table_entry(0x9A) \ + table_entry(0x9F) \ + table_entry(0xB0) \ + table_entry(0xB1) \ + table_entry(0xB2) \ + table_entry(0xB3) \ + table_entry(0xB4) \ + table_entry(0xB5) \ + table_entry(0xB7) \ + table_entry(0xB8) \ + table_entry(0xB9) \ + table_entry(0xBA) \ + table_entry(0xBB) \ + table_entry(0xBC) \ + table_entry(0xBD) \ + table_entry(0xC0) \ + table_entry(0xC2) \ + table_entry(0xC4) \ + table_entry(0xC5) \ + table_entry(0xC6) \ + table_entry(0xC7) \ + table_entry(0xCC) \ + table_entry(0xCE) \ + table_entry(0xD0) \ + table_entry(0xD1) \ + table_entry(0xD2) \ + table_entry(0xD3) \ + table_entry(0xD4) \ + table_entry(0xD5) \ + table_entry(0xD6) \ + table_entry(0xD7) \ + table_entry(0xD8) \ + table_entry(0xDA) \ + table_entry(0xDB) \ + table_entry(0xDD) \ + table_entry(0xDE) \ + table_entry(0xDF) \ + table_entry(0xE2) \ + table_entry(0xE3) \ + table_entry(0xE5) \ + table_entry(0xE6) \ + table_entry(0xEC) \ + table_entry(0xED) \ + table_entry(0xEF) \ + table_entry(0xF0) \ + table_entry(0xF4) \ + table_entry(0xF6) \ + table_entry(0xF8) \ + table_entry(0xFA) \ + table_entry(0xFB) \ + table_entry(0x100) \ + table_entry(0x101) \ + table_entry(0x10D) \ + table_entry(0x10E) \ + table_entry(0x10F) \ + table_entry(0x116) \ + table_entry(0x12C) \ + table_entry(0x300) \ + table_entry(0x301) \ + table_entry(0x302) \ + table_entry(0x303) \ + table_entry(0x304) \ + table_entry(0x307) \ + table_entry(0x309) \ + table_entry(0x30A) \ + table_entry(0x30C) \ + table_entry(0x30E) \ + table_entry(0x314) \ + table_entry(0x315) \ + table_entry(0x317) \ + table_entry(0x318) \ + table_entry(0x319) \ + table_entry(0x323) \ + table_entry(0x325) \ + table_entry(0x326) \ + table_entry(0x32A) \ + table_entry(0x32B) \ + table_entry(0x32C) \ + table_entry(0x32F) \ + table_entry(0x331) \ + table_entry(0x333) \ + table_entry(0x335) \ + table_entry(0x336) \ + table_entry(0x33B) \ + table_entry(0x33C) \ + table_entry(0x33D) \ + table_entry(0x33E) \ + table_entry(0x343) \ + table_entry(0x360) \ + table_entry(0x361) \ + table_entry(0x377) \ + table_entry(0x379) \ + table_entry(0x37A) \ + table_entry(0x37B) \ + table_entry(0x393) \ + table_entry(0x3c6) \ + table_entry(0x3c8) \ + table_entry(0x3dd) \ + table_entry(0x4001) \ + table_entry(0x4004) \ + table_entry(0x5000) \ + table_entry(0x5002) \ + table_entry(0x6004) \ + table_entry(HID_ANY_ID) \ + +enum wacom_features_table_index { +#define table_entry(product) \ + WACOM_FEATURE_TABLE_##product, + HID_WACOM_PRODUCT_TABLE() + NUM_OF_WACOM_FEATURES_IN_TABLE +#undef table_entry +}; + void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); void wacom_setup_device_quirks(struct wacom *wacom); int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, @@ -249,4 +425,5 @@ struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur); int wacom_equivalent_usage(int usage); int wacom_initialize_leds(struct wacom *wacom); void wacom_idleprox_timeout(struct timer_list *list); +const struct wacom_features *get_wacom_features(enum wacom_features_table_index index); #endif diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 0eafa483b7f7..834519751a5c 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -2559,8 +2559,13 @@ static void wacom_wireless_work(struct work_struct *work) } /* Stylus interface */ - wacom_wac1->features = - *((struct wacom_features *)id->driver_data); + const struct wacom_features *features = get_wacom_features(id->driver_data); + + if (!features) { + hid_err(wacom->hdev, "could not get wacom features.\n"); + return; + } + wacom_wac1->features = *features; wacom_wac1->pid = wacom_wac->pid; hid_hw_stop(hdev1); @@ -2572,8 +2577,7 @@ static void wacom_wireless_work(struct work_struct *work) if (wacom_wac1->features.touch_max || (wacom_wac1->features.type >= INTUOSHT && wacom_wac1->features.type <= BAMBOO_PT)) { - wacom_wac2->features = - *((struct wacom_features *)id->driver_data); + wacom_wac2->features = *features; wacom_wac2->pid = wacom_wac->pid; hid_hw_stop(hdev2); error = wacom_parse_and_register(wacom2, true); @@ -2843,7 +2847,15 @@ static int wacom_probe(struct hid_device *hdev, wacom->hdev = hdev; wacom_wac = &wacom->wacom_wac; - wacom_wac->features = *((struct wacom_features *)id->driver_data); + + const struct wacom_features *id_features = get_wacom_features(id->driver_data); + + if (!id_features) { + hid_err(wacom->hdev, "could not get wacom id_features.\n"); + return -EINVAL; + } + wacom_wac->features = *id_features; + features = &wacom_wac->features; if (features->check_for_hid_type && features->hid_type != hdev->type) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index da1f0ea85625..d0a864d52509 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -4945,25 +4945,40 @@ static const struct wacom_features wacom_features_HID_ANY_ID = static const struct wacom_features wacom_features_0x94 = { "Wacom Bootloader", .type = BOOTLOADER }; +static const struct wacom_features *wacom_features_table[] = { +#define table_entry(product) \ + [WACOM_FEATURE_TABLE_##product] = &wacom_features_##product, + HID_WACOM_PRODUCT_TABLE() +#undef table_entry +}; + +const struct wacom_features *get_wacom_features(enum wacom_features_table_index index) +{ + if (index >= NUM_OF_WACOM_FEATURES_IN_TABLE) + return NULL; + + return wacom_features_table[index]; +} + #define USB_DEVICE_WACOM(prod) \ HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ - .driver_data = (kernel_ulong_t)&wacom_features_##prod + .driver_data = WACOM_FEATURE_TABLE_##prod #define BT_DEVICE_WACOM(prod) \ HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ - .driver_data = (kernel_ulong_t)&wacom_features_##prod + .driver_data = WACOM_FEATURE_TABLE_##prod #define I2C_DEVICE_WACOM(prod) \ HID_DEVICE(BUS_I2C, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ - .driver_data = (kernel_ulong_t)&wacom_features_##prod + .driver_data = WACOM_FEATURE_TABLE_##prod #define PCI_DEVICE_WACOM(prod) \ HID_DEVICE(BUS_PCI, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ - .driver_data = (kernel_ulong_t)&wacom_features_##prod + .driver_data = WACOM_FEATURE_TABLE_##prod #define USB_DEVICE_LENOVO(prod) \ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \ - .driver_data = (kernel_ulong_t)&wacom_features_##prod + .driver_data = WACOM_FEATURE_TABLE_##prod const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x00) }, -- 2.43.0