Skip to content

Commit 6eb04ca

Browse files
guilhermepiccoliJiri Kosina
authored and
Jiri Kosina
committed
HID: nintendo: Prevent divide-by-zero on code
It was reported [0] that adding a generic joycon to the system caused a kernel crash on Steam Deck, with the below panic spew: divide error: 0000 [#1] PREEMPT SMP NOPTI [...] Hardware name: Valve Jupiter/Jupiter, BIOS F7A0119 10/24/2023 RIP: 0010:nintendo_hid_event+0x340/0xcc1 [hid_nintendo] [...] Call Trace: [...] ? exc_divide_error+0x38/0x50 ? nintendo_hid_event+0x340/0xcc1 [hid_nintendo] ? asm_exc_divide_error+0x1a/0x20 ? nintendo_hid_event+0x307/0xcc1 [hid_nintendo] hid_input_report+0x143/0x160 hidp_session_run+0x1ce/0x700 [hidp] Since it's a divide-by-0 error, by tracking the code for potential denominator issues, we've spotted 2 places in which this could happen; so let's guard against the possibility and log in the kernel if the condition happens. This is specially useful since some data that fills some denominators are read from the joycon HW in some cases, increasing the potential for flaws. [0] ValveSoftware/SteamOS#1070 Signed-off-by: Guilherme G. Piccoli <[email protected]> Tested-by: Sam Lantinga <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 0b7dd38 commit 6eb04ca

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

drivers/hid/hid-nintendo.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -927,14 +927,27 @@ static int joycon_request_calibration(struct joycon_ctlr *ctlr)
927927
*/
928928
static void joycon_calc_imu_cal_divisors(struct joycon_ctlr *ctlr)
929929
{
930-
int i;
930+
int i, divz = 0;
931931

932932
for (i = 0; i < 3; i++) {
933933
ctlr->imu_cal_accel_divisor[i] = ctlr->accel_cal.scale[i] -
934934
ctlr->accel_cal.offset[i];
935935
ctlr->imu_cal_gyro_divisor[i] = ctlr->gyro_cal.scale[i] -
936936
ctlr->gyro_cal.offset[i];
937+
938+
if (ctlr->imu_cal_accel_divisor[i] == 0) {
939+
ctlr->imu_cal_accel_divisor[i] = 1;
940+
divz++;
941+
}
942+
943+
if (ctlr->imu_cal_gyro_divisor[i] == 0) {
944+
ctlr->imu_cal_gyro_divisor[i] = 1;
945+
divz++;
946+
}
937947
}
948+
949+
if (divz)
950+
hid_warn(ctlr->hdev, "inaccurate IMU divisors (%d)\n", divz);
938951
}
939952

940953
static const s16 DFLT_ACCEL_OFFSET /*= 0*/;
@@ -1163,16 +1176,16 @@ static void joycon_parse_imu_report(struct joycon_ctlr *ctlr,
11631176
JC_IMU_SAMPLES_PER_DELTA_AVG) {
11641177
ctlr->imu_avg_delta_ms = ctlr->imu_delta_samples_sum /
11651178
ctlr->imu_delta_samples_count;
1166-
/* don't ever want divide by zero shenanigans */
1167-
if (ctlr->imu_avg_delta_ms == 0) {
1168-
ctlr->imu_avg_delta_ms = 1;
1169-
hid_warn(ctlr->hdev,
1170-
"calculated avg imu delta of 0\n");
1171-
}
11721179
ctlr->imu_delta_samples_count = 0;
11731180
ctlr->imu_delta_samples_sum = 0;
11741181
}
11751182

1183+
/* don't ever want divide by zero shenanigans */
1184+
if (ctlr->imu_avg_delta_ms == 0) {
1185+
ctlr->imu_avg_delta_ms = 1;
1186+
hid_warn(ctlr->hdev, "calculated avg imu delta of 0\n");
1187+
}
1188+
11761189
/* useful for debugging IMU sample rate */
11771190
hid_dbg(ctlr->hdev,
11781191
"imu_report: ms=%u last_ms=%u delta=%u avg_delta=%u\n",

0 commit comments

Comments
 (0)