--- /dev/null
+From 90f305f2c7a30257c683e13f4bf7c798eea992a0 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Wed, 29 Jul 2026 11:30:45 -0700
+Subject: Input: evdev - fix information leak in evdev_pass_values()
+
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+commit 90f305f2c7a30257c683e13f4bf7c798eea992a0 upstream.
+
+In evdev_pass_values(), the input_event structure is allocated on the
+kernel stack and populated field-by-field. However, it is never fully
+initialized. On architectures where struct input_event contains explicit
+or implicit padding (such as the 32-bit __pad field on SPARC64), these
+padding bytes are left uninitialized.
+
+When this event structure is subsequently passed to the client buffer
+and later copied to userspace, the uninitialized padding bytes leak
+kernel stack memory, potentially exposing sensitive information.
+
+Similar issues exist in __evdev_queue_syn_dropped and __pass_event.
+
+Fix this by explicitly zeroing the entire event structure with memset()
+before populating its fields. This ensures all padding bytes are cleared
+before the data crosses the security boundary.
+
+Reported-by: sashiko-bot@kernel.org
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/ampGGKo4UMKru6f5@google.com
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/evdev.c | 22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+--- a/drivers/input/evdev.c
++++ b/drivers/input/evdev.c
+@@ -149,11 +149,11 @@ static void __evdev_queue_syn_dropped(st
+ struct timespec64 ts = ktime_to_timespec64(ev_time[client->clk_type]);
+ struct input_event ev;
+
++ memset(&ev, 0, sizeof(ev));
+ ev.input_event_sec = ts.tv_sec;
+ ev.input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
+ ev.type = EV_SYN;
+ ev.code = SYN_DROPPED;
+- ev.value = 0;
+
+ client->buffer[client->head++] = ev;
+ client->head &= client->bufsize - 1;
+@@ -221,20 +221,20 @@ static void __pass_event(struct evdev_cl
+ client->head &= client->bufsize - 1;
+
+ if (unlikely(client->head == client->tail)) {
++ struct input_event ev;
++
++ memset(&ev, 0, sizeof(ev));
++ ev.input_event_sec = event->input_event_sec;
++ ev.input_event_usec = event->input_event_usec;
++ ev.type = EV_SYN;
++ ev.code = SYN_DROPPED;
++
+ /*
+ * This effectively "drops" all unconsumed events, leaving
+ * EV_SYN/SYN_DROPPED plus the newest event in the queue.
+ */
+ client->tail = (client->head - 2) & (client->bufsize - 1);
+-
+- 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->buffer[client->tail] = ev;
+ client->packet_head = client->tail;
+ }
+
+@@ -256,6 +256,8 @@ static void evdev_pass_values(struct evd
+ if (client->revoked)
+ return;
+
++ memset(&event, 0, sizeof(event));
++
+ ts = ktime_to_timespec64(ev_time[client->clk_type]);
+ event.input_event_sec = ts.tv_sec;
+ event.input_event_usec = ts.tv_nsec / NSEC_PER_USEC;