[PATCH] HID: sony: Fix division by zero

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

Today I connected a partially broken DS4 via USB and got a kernel
panic with a division by zero in the hid-sony driver.

The issue is caused by sens_denom=0 in the sensor calibration data,
which triggers a division by zero when dualshock4_parse_report() is
invoked, the division happens in the mult_frac() macro.

This patch applies a workaround that allows the DS4 to be used even
with a broken sensor: if the denominator sent by the device is zero,
it is replaced with 1 and a warning is emitted.

Signed-off-by: Alain Carlucci <alain.carlucci@xxxxxxxxx>
---
 drivers/hid/hid-sony.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 13125997a..f8b05cb29 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1714,6 +1714,7 @@ static int dualshock4_get_calibration_data(struct sony_sc *sc)
 	short acc_z_plus, acc_z_minus;
 	int speed_2x;
 	int range_2g;
+	int calib_id;
/* For Bluetooth we use a different request, which supports CRC.
 	 * Note: in Bluetooth mode feature report 0x02 also changes the state
@@ -1858,6 +1859,23 @@ static int dualshock4_get_calibration_data(struct sony_sc *sc)
 	sc->ds4_calib_data[5].sens_numer = 2*DS4_ACC_RES_PER_G;
 	sc->ds4_calib_data[5].sens_denom = range_2g;
+ for (calib_id = 0; calib_id < 6; calib_id++) {
+		/* Ensure there are no denominators equal to zero to prevent
+		 * crashes while dividing by that number.
+		 */
+
+		if (sc->ds4_calib_data[calib_id].sens_denom != 0) {
+			/* Denominator OK, skip this */
+			continue;
+		}
+
+		sc->ds4_calib_data[calib_id].sens_denom = 1;
+
+		hid_warn(sc->hdev,
+			 "DualShock 4 USB dongle: invalid calibration for sensor %d\n",
+			 calib_id);
+	}
+
 err_stop:
 	kfree(buf);
 	return ret;
--
2.39.0



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux