[PATCH] Input: joydev - avoid an undefined shift in the legacy 0x read
From: Guanglei Zhu
Date: Tue Nov 03 2026 - 04:10:11 EST
The legacy 0.x read path shifts the axis values by the calibration
constants that JS_SET_CAL installs:
data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x;
data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y;
JS_CORR is copied straight from userspace as three s32 values and
never validated, so the shift count can be negative or wider than
the type, which is undefined behavior: the shift compiles to
whatever the architecture does with an out-of-range count, and the
compiler is free to assume it cannot happen.
Clamp the shift count to the width of the shifted value.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Guanglei Zhu <zhugl3@xxxxxxxxxxxx>
---
drivers/input/joydev.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 32459fd8a7c1..4740099599bf 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -353,8 +353,8 @@ static ssize_t joydev_0x_read(struct joydev_client *client,
for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++)
data.buttons |=
test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0;
- data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x;
- data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y;
+ data.x = (joydev->abs[0] / 256 + 128) >> clamp(joydev->glue.JS_CORR.x, 0, 31);
+ data.y = (joydev->abs[1] / 256 + 128) >> clamp(joydev->glue.JS_CORR.y, 0, 31);
/*
* Reset reader's event queue
--
2.50.1