* [PATCH] Input: evdev - fix information leak in evdev_pass_values()
@ 2026-07-29 18:30 Dmitry Torokhov
0 siblings, 0 replies; only message in thread
From: Dmitry Torokhov @ 2026-07-29 18:30 UTC (permalink / raw)
To: linux-input; +Cc: Kees Cook, linux-kernel
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
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/evdev.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 5764c98b4f1f..114524806293 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -146,11 +146,11 @@ static void __evdev_queue_syn_dropped(struct evdev_client *client)
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;
@@ -212,20 +212,20 @@ static void __pass_event(struct evdev_client *client,
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;
}
@@ -247,6 +247,8 @@ static void evdev_pass_values(struct evdev_client *client,
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;
--
2.55.0.508.g3f0d502094-goog
--
Dmitry
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-07-29 18:30 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29 18:30 [PATCH] Input: evdev - fix information leak in evdev_pass_values() Dmitry Torokhov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox