Skip to content

Commit 74cb485

Browse files
Roderick ColenbranderJiri Kosina
authored andcommitted
HID: playstation: sanity check DualShock4 calibration data.
Some DualShock4 devices report invalid calibration data resulting in kernel oopses due to division by zero during report handling. The devices affected generally appear to be clone devices, which don't implement all reports properly and don't populate proper calibration data. The issue may have been seen on an official device with erased calibration reports. This patch prevents the crashes by essentially disabling calibration when invalid values are detected. Signed-off-by: Roderick Colenbrander <[email protected]> Tested-by: Alain Carlucci <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent febb2c0 commit 74cb485

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

drivers/hid/hid-playstation.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
17371737
int speed_2x;
17381738
int range_2g;
17391739
int ret = 0;
1740+
int i;
17401741
uint8_t *buf;
17411742

17421743
if (ds4->base.hdev->bus == BUS_USB) {
@@ -1830,6 +1831,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
18301831
ds4->gyro_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
18311832
ds4->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus;
18321833

1834+
/*
1835+
* Sanity check gyro calibration data. This is needed to prevent crashes
1836+
* during report handling of virtual, clone or broken devices not implementing
1837+
* calibration data properly.
1838+
*/
1839+
for (i = 0; i < ARRAY_SIZE(ds4->gyro_calib_data); i++) {
1840+
if (ds4->gyro_calib_data[i].sens_denom == 0) {
1841+
hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
1842+
ds4->gyro_calib_data[i].abs_code);
1843+
ds4->gyro_calib_data[i].bias = 0;
1844+
ds4->gyro_calib_data[i].sens_numer = DS4_GYRO_RANGE;
1845+
ds4->gyro_calib_data[i].sens_denom = S16_MAX;
1846+
}
1847+
}
1848+
18331849
/*
18341850
* Set accelerometer calibration and normalization parameters.
18351851
* Data values will be normalized to 1/DS4_ACC_RES_PER_G g.
@@ -1852,6 +1868,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
18521868
ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G;
18531869
ds4->accel_calib_data[2].sens_denom = range_2g;
18541870

1871+
/*
1872+
* Sanity check accelerometer calibration data. This is needed to prevent crashes
1873+
* during report handling of virtual, clone or broken devices not implementing calibration
1874+
* data properly.
1875+
*/
1876+
for (i = 0; i < ARRAY_SIZE(ds4->accel_calib_data); i++) {
1877+
if (ds4->accel_calib_data[i].sens_denom == 0) {
1878+
hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
1879+
ds4->accel_calib_data[i].abs_code);
1880+
ds4->accel_calib_data[i].bias = 0;
1881+
ds4->accel_calib_data[i].sens_numer = DS4_ACC_RANGE;
1882+
ds4->accel_calib_data[i].sens_denom = S16_MAX;
1883+
}
1884+
}
1885+
18551886
err_free:
18561887
kfree(buf);
18571888
return ret;

0 commit comments

Comments
 (0)