Re: [PATCH] Input: joydev - avoid an undefined shift in the legacy 0x read

From: Dmitry Torokhov

Date: Tue Nov 03 2026 - 14:15:10 EST


Hi Guanglei,

On Tue, Nov 03, 2026 at 04:41:28PM +0800, Guanglei Zhu wrote:
> 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

Why do all these need to be in stable?

> 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

Thanks.

--
Dmitry