From: Arnd Bergmann arnd@arndb.de
commit f729a1b0f8df7091cea3729fc0e414f5326e1163 upstream.
Going through all uses of timeval, I noticed that we screwed up input_event in the previous attempts to fix it:
The time fields now match between kernel and user space, but all following fields are in the wrong place.
Add the required padding that is implied by the glibc timeval definition to fix the layout, and use a struct initializer to avoid leaking kernel stack data.
Fixes: 141e5dcaa735 ("Input: input_event - fix the CONFIG_SPARC64 mixup") Fixes: 2e746942ebac ("Input: input_event - provide override for sparc64") Signed-off-by: Arnd Bergmann arnd@arndb.de Link: https://lore.kernel.org/r/20191213204936.3643476-2-arnd@arndb.de Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/input/evdev.c | 14 +++++++------- drivers/input/misc/uinput.c | 14 +++++++++----- include/uapi/linux/input.h | 1 + 3 files changed, 17 insertions(+), 12 deletions(-)
--- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -224,13 +224,13 @@ static void __pass_event(struct evdev_cl */ client->tail = (client->head - 2) & (client->bufsize - 1);
- client->buffer[client->tail].input_event_sec = - event->input_event_sec; - client->buffer[client->tail].input_event_usec = - event->input_event_usec; - client->buffer[client->tail].type = EV_SYN; - client->buffer[client->tail].code = SYN_DROPPED; - client->buffer[client->tail].value = 0; + client->buffer[client->tail] = (struct input_event) { + .input_event_sec = event->input_event_sec, + .input_event_usec = event->input_event_usec, + .type = EV_SYN, + .code = SYN_DROPPED, + .value = 0, + };
client->packet_head = client->tail; } --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -74,12 +74,16 @@ static int uinput_dev_event(struct input struct uinput_device *udev = input_get_drvdata(dev); struct timespec64 ts;
- udev->buff[udev->head].type = type; - udev->buff[udev->head].code = code; - udev->buff[udev->head].value = value; ktime_get_ts64(&ts); - udev->buff[udev->head].input_event_sec = ts.tv_sec; - udev->buff[udev->head].input_event_usec = ts.tv_nsec / NSEC_PER_USEC; + + udev->buff[udev->head] = (struct input_event) { + .input_event_sec = ts.tv_sec, + .input_event_usec = ts.tv_nsec / NSEC_PER_USEC, + .type = type, + .code = code, + .value = value, + }; + udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
wake_up_interruptible(&udev->waitq); --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -34,6 +34,7 @@ struct input_event { __kernel_ulong_t __sec; #if defined(__sparc__) && defined(__arch64__) unsigned int __usec; + unsigned int __pad; #else __kernel_ulong_t __usec; #endif