Commit 7287904c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-2023011801' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID fixes from Jiri Kosina:

 - fixes for potential empty list handling in HID core (Pietro Borrello)

 - fix for NULL pointer dereference in betop driver that could be
   triggered by malicious device (Pietro Borrello)

 - fixes for handling calibration data preventing division by zero in
   Playstation driver (Roderick Colenbrander)

 - fix for memory leak on error path in amd-sfh driver (Basavaraj
   Natikar)

 - other few assorted small fixes and device ID-specific handling

* tag 'for-linus-2023011801' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: betop: check shape of output reports
  HID: playstation: sanity check DualSense calibration data.
  HID: playstation: sanity check DualShock4 calibration data.
  HID: uclogic: Add support for XP-PEN Deco 01 V2
  HID: revert CHERRY_MOUSE_000C quirk
  HID: check empty report_list in bigben_probe()
  HID: check empty report_list in hid_validate_values()
  HID: amd_sfh: Fix warning unwind goto
  HID: intel_ish-hid: Add check for ishtp_dma_tx_map
parents 7026172b 3782c0d6
...@@ -282,7 +282,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) ...@@ -282,7 +282,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
} }
rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]); rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]);
if (rc) if (rc)
return rc; goto cleanup;
mp2_ops->start(privdata, info); mp2_ops->start(privdata, info);
status = amd_sfh_wait_for_response status = amd_sfh_wait_for_response
(privdata, cl_data->sensor_idx[i], SENSOR_ENABLED); (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED);
......
...@@ -160,7 +160,7 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) ...@@ -160,7 +160,7 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
} }
rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]); rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]);
if (rc) if (rc)
return rc; goto cleanup;
writel(0, privdata->mmio + AMD_P2C_MSG(0)); writel(0, privdata->mmio + AMD_P2C_MSG(0));
mp2_ops->start(privdata, info); mp2_ops->start(privdata, info);
......
...@@ -60,7 +60,6 @@ static int betopff_init(struct hid_device *hid) ...@@ -60,7 +60,6 @@ static int betopff_init(struct hid_device *hid)
struct list_head *report_list = struct list_head *report_list =
&hid->report_enum[HID_OUTPUT_REPORT].report_list; &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct input_dev *dev; struct input_dev *dev;
int field_count = 0;
int error; int error;
int i, j; int i, j;
...@@ -86,19 +85,21 @@ static int betopff_init(struct hid_device *hid) ...@@ -86,19 +85,21 @@ static int betopff_init(struct hid_device *hid)
* ----------------------------------------- * -----------------------------------------
* Do init them with default value. * Do init them with default value.
*/ */
if (report->maxfield < 4) {
hid_err(hid, "not enough fields in the report: %d\n",
report->maxfield);
return -ENODEV;
}
for (i = 0; i < report->maxfield; i++) { for (i = 0; i < report->maxfield; i++) {
if (report->field[i]->report_count < 1) {
hid_err(hid, "no values in the field\n");
return -ENODEV;
}
for (j = 0; j < report->field[i]->report_count; j++) { for (j = 0; j < report->field[i]->report_count; j++) {
report->field[i]->value[j] = 0x00; report->field[i]->value[j] = 0x00;
field_count++;
} }
} }
if (field_count < 4) {
hid_err(hid, "not enough fields in the report: %d\n",
field_count);
return -ENODEV;
}
betopff = kzalloc(sizeof(*betopff), GFP_KERNEL); betopff = kzalloc(sizeof(*betopff), GFP_KERNEL);
if (!betopff) if (!betopff)
return -ENOMEM; return -ENOMEM;
......
...@@ -344,6 +344,11 @@ static int bigben_probe(struct hid_device *hid, ...@@ -344,6 +344,11 @@ static int bigben_probe(struct hid_device *hid,
} }
report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
if (list_empty(report_list)) {
hid_err(hid, "no output report found\n");
error = -ENODEV;
goto error_hw_stop;
}
bigben->report = list_entry(report_list->next, bigben->report = list_entry(report_list->next,
struct hid_report, list); struct hid_report, list);
......
...@@ -993,8 +993,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid, ...@@ -993,8 +993,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid,
* Validating on id 0 means we should examine the first * Validating on id 0 means we should examine the first
* report in the list. * report in the list.
*/ */
report = list_entry( report = list_first_entry_or_null(
hid->report_enum[type].report_list.next, &hid->report_enum[type].report_list,
struct hid_report, list); struct hid_report, list);
} else { } else {
report = hid->report_enum[type].report_id_hash[id]; report = hid->report_enum[type].report_id_hash[id];
......
...@@ -274,7 +274,6 @@ ...@@ -274,7 +274,6 @@
#define USB_DEVICE_ID_CH_AXIS_295 0x001c #define USB_DEVICE_ID_CH_AXIS_295 0x001c
#define USB_VENDOR_ID_CHERRY 0x046a #define USB_VENDOR_ID_CHERRY 0x046a
#define USB_DEVICE_ID_CHERRY_MOUSE_000C 0x000c
#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
#define USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR 0x0027 #define USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR 0x0027
...@@ -1295,6 +1294,7 @@ ...@@ -1295,6 +1294,7 @@
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540 0x0075 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540 0x0075
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640 0x0094 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640 0x0094
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2 0x0905
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L 0x0935 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L 0x0935
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S 0x0909 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S 0x0909
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078
......
...@@ -944,6 +944,7 @@ ATTRIBUTE_GROUPS(ps_device); ...@@ -944,6 +944,7 @@ ATTRIBUTE_GROUPS(ps_device);
static int dualsense_get_calibration_data(struct dualsense *ds) static int dualsense_get_calibration_data(struct dualsense *ds)
{ {
struct hid_device *hdev = ds->base.hdev;
short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus; short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus;
short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus; short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus;
short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus; short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus;
...@@ -954,6 +955,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds) ...@@ -954,6 +955,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
int speed_2x; int speed_2x;
int range_2g; int range_2g;
int ret = 0; int ret = 0;
int i;
uint8_t *buf; uint8_t *buf;
buf = kzalloc(DS_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL); buf = kzalloc(DS_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL);
...@@ -1005,6 +1007,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds) ...@@ -1005,6 +1007,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
ds->gyro_calib_data[2].sens_numer = speed_2x*DS_GYRO_RES_PER_DEG_S; ds->gyro_calib_data[2].sens_numer = speed_2x*DS_GYRO_RES_PER_DEG_S;
ds->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus; ds->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus;
/*
* Sanity check gyro calibration data. This is needed to prevent crashes
* during report handling of virtual, clone or broken devices not implementing
* calibration data properly.
*/
for (i = 0; i < ARRAY_SIZE(ds->gyro_calib_data); i++) {
if (ds->gyro_calib_data[i].sens_denom == 0) {
hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
ds->gyro_calib_data[i].abs_code);
ds->gyro_calib_data[i].bias = 0;
ds->gyro_calib_data[i].sens_numer = DS_GYRO_RANGE;
ds->gyro_calib_data[i].sens_denom = S16_MAX;
}
}
/* /*
* Set accelerometer calibration and normalization parameters. * Set accelerometer calibration and normalization parameters.
* Data values will be normalized to 1/DS_ACC_RES_PER_G g. * Data values will be normalized to 1/DS_ACC_RES_PER_G g.
...@@ -1027,6 +1044,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds) ...@@ -1027,6 +1044,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
ds->accel_calib_data[2].sens_numer = 2*DS_ACC_RES_PER_G; ds->accel_calib_data[2].sens_numer = 2*DS_ACC_RES_PER_G;
ds->accel_calib_data[2].sens_denom = range_2g; ds->accel_calib_data[2].sens_denom = range_2g;
/*
* Sanity check accelerometer calibration data. This is needed to prevent crashes
* during report handling of virtual, clone or broken devices not implementing calibration
* data properly.
*/
for (i = 0; i < ARRAY_SIZE(ds->accel_calib_data); i++) {
if (ds->accel_calib_data[i].sens_denom == 0) {
hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
ds->accel_calib_data[i].abs_code);
ds->accel_calib_data[i].bias = 0;
ds->accel_calib_data[i].sens_numer = DS_ACC_RANGE;
ds->accel_calib_data[i].sens_denom = S16_MAX;
}
}
err_free: err_free:
kfree(buf); kfree(buf);
return ret; return ret;
...@@ -1737,6 +1769,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4) ...@@ -1737,6 +1769,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
int speed_2x; int speed_2x;
int range_2g; int range_2g;
int ret = 0; int ret = 0;
int i;
uint8_t *buf; uint8_t *buf;
if (ds4->base.hdev->bus == BUS_USB) { if (ds4->base.hdev->bus == BUS_USB) {
...@@ -1830,6 +1863,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4) ...@@ -1830,6 +1863,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
ds4->gyro_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S; ds4->gyro_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
ds4->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus; ds4->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus;
/*
* Sanity check gyro calibration data. This is needed to prevent crashes
* during report handling of virtual, clone or broken devices not implementing
* calibration data properly.
*/
for (i = 0; i < ARRAY_SIZE(ds4->gyro_calib_data); i++) {
if (ds4->gyro_calib_data[i].sens_denom == 0) {
hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
ds4->gyro_calib_data[i].abs_code);
ds4->gyro_calib_data[i].bias = 0;
ds4->gyro_calib_data[i].sens_numer = DS4_GYRO_RANGE;
ds4->gyro_calib_data[i].sens_denom = S16_MAX;
}
}
/* /*
* Set accelerometer calibration and normalization parameters. * Set accelerometer calibration and normalization parameters.
* Data values will be normalized to 1/DS4_ACC_RES_PER_G g. * Data values will be normalized to 1/DS4_ACC_RES_PER_G g.
...@@ -1852,6 +1900,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4) ...@@ -1852,6 +1900,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G; ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G;
ds4->accel_calib_data[2].sens_denom = range_2g; ds4->accel_calib_data[2].sens_denom = range_2g;
/*
* Sanity check accelerometer calibration data. This is needed to prevent crashes
* during report handling of virtual, clone or broken devices not implementing calibration
* data properly.
*/
for (i = 0; i < ARRAY_SIZE(ds4->accel_calib_data); i++) {
if (ds4->accel_calib_data[i].sens_denom == 0) {
hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
ds4->accel_calib_data[i].abs_code);
ds4->accel_calib_data[i].bias = 0;
ds4->accel_calib_data[i].sens_numer = DS4_ACC_RANGE;
ds4->accel_calib_data[i].sens_denom = S16_MAX;
}
}
err_free: err_free:
kfree(buf); kfree(buf);
return ret; return ret;
......
...@@ -54,7 +54,6 @@ static const struct hid_device_id hid_quirks[] = { ...@@ -54,7 +54,6 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_MOUSE_000C), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB), HID_QUIRK_NO_INIT_REPORTS },
......
...@@ -525,6 +525,8 @@ static const struct hid_device_id uclogic_devices[] = { ...@@ -525,6 +525,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640) }, USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) }, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) }, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
......
...@@ -1655,6 +1655,8 @@ int uclogic_params_init(struct uclogic_params *params, ...@@ -1655,6 +1655,8 @@ int uclogic_params_init(struct uclogic_params *params,
break; break;
case VID_PID(USB_VENDOR_ID_UGEE, case VID_PID(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_PARBLO_A610_PRO): USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
case VID_PID(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2):
case VID_PID(USB_VENDOR_ID_UGEE, case VID_PID(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L): USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
case VID_PID(USB_VENDOR_ID_UGEE, case VID_PID(USB_VENDOR_ID_UGEE,
......
...@@ -104,6 +104,11 @@ void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev, ...@@ -104,6 +104,11 @@ void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev,
int required_slots = (size / DMA_SLOT_SIZE) int required_slots = (size / DMA_SLOT_SIZE)
+ 1 * (size % DMA_SLOT_SIZE != 0); + 1 * (size % DMA_SLOT_SIZE != 0);
if (!dev->ishtp_dma_tx_map) {
dev_err(dev->devc, "Fail to allocate Tx map\n");
return NULL;
}
spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags); spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
for (i = 0; i <= (dev->ishtp_dma_num_slots - required_slots); i++) { for (i = 0; i <= (dev->ishtp_dma_num_slots - required_slots); i++) {
free = 1; free = 1;
...@@ -150,6 +155,11 @@ void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev, ...@@ -150,6 +155,11 @@ void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev,
return; return;
} }
if (!dev->ishtp_dma_tx_map) {
dev_err(dev->devc, "Fail to allocate Tx map\n");
return;
}
i = (msg_addr - dev->ishtp_host_dma_tx_buf) / DMA_SLOT_SIZE; i = (msg_addr - dev->ishtp_host_dma_tx_buf) / DMA_SLOT_SIZE;
spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags); spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
for (j = 0; j < acked_slots; j++) { for (j = 0; j < acked_slots; j++) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment