--- /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;
--- /dev/null
+From 26444eb71465c9934d9d418ef69c43f61185329b Mon Sep 17 00:00:00 2001
+From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
+Date: Thu, 23 Jul 2026 16:16:31 +0100
+Subject: mm/vmalloc: acquire init_mm lock on huge vmap to avoid ptdump UAF
+
+From: Lorenzo Stoakes (ARM) <ljs@kernel.org>
+
+commit 26444eb71465c9934d9d418ef69c43f61185329b upstream.
+
+Patch series "mm: fix UAF caused by race between ptdump and vmap pgtable
+freeing", v6.
+
+Kernel page table walkers fall into two broad categories - those ranges
+where no exclusion is required via walk_kernel_page_table_range_lockless()
+and those where exclusion is required via walk_kernel_page_table_range()
+or walk_page_range_debug().
+
+The former category is used only by arm64 arch code operating on ranges it
+both wholly owns and does not concurrently write.
+
+The latter category consists of kernel page table walkers operating on
+ranges that are wholly owned (but which need exclusion against concurrent
+writers).
+
+The lock used for exclusion is the mmap lock, and for kernel ranges this
+is the mmap lock on init_mm.
+
+ptdump is a special case being both the only user of
+walk_page_range_debug(), and the only case in which it walks ranges it
+does not own.
+
+This presents a problem, as page tables may be freed under ptdump. And
+indeed there is a use-after-free bug in the kernel as a result, which this
+series addresses.
+
+vmap promotes page tables to huge leaf entries where possible, freeing the
+lower page table when it does. It does this with no meaningful locks held
+against concurrent ptdump walks.
+
+As a result, use-after-free can currently occur. This series addresses
+the issue by having the vmap huge promotion logic acquire the mmap read
+lock while both setting the huge page table entry and freeing the prior
+leaf page table.
+
+The ptdump code already acquires the mmap write lock, so by doing so we
+ensure that the ptdump walker only ever observes either the huge page
+table entry or the existing page table entry, and nothing is freed
+underneath it.
+
+A mitigation for this issue was already applied for arm64 in commit
+fa93b45fd397 ("arm64: Enable vmalloc-huge with ptdump"), which this series
+has to deal with carefully.
+
+This mitigation resolves the issue by acquiring the mmap read lock on
+init_mm on vmap page table free if a ptdump is in progress.
+
+However the fix in this series would cause a deadlock if we were to simply
+apply it for arm64 without also reverting the change.
+
+This is because vmap may acquire the read lock before ptdump attempts to
+acquire the write lock, which then gets queued, and rwsem starvation rules
+mean that the (unacknowledged) nested mmap read lock in the arm64 code
+would also block, meaning the original read lock is never released and
+thus deadlock.
+
+This series works around this by #ifndef CONFIG_ARM64'ing the mmap read
+lock in vmap logic, then partially reverting commit fa93b45fd397 ("arm64:
+Enable vmalloc-huge with ptdump"), keeping the enablement of huge vmap
+support, and removing the ifdeffery with the partial revert patch.
+
+There are related issues that are also addressed in this series:
+
+* x86 page attribute logic, specifically Change Page Attributes (CPA),
+ implements a feature whereby huge ranges can be collapsed into huge leaf
+ entries. This can similarly cause a UAF when done in parallel with a
+ ptdump walk, so similarly acquire the init_mm mmap lock to avoid this.
+
+* The CPA logic allows concurrent page table manipulation and CPA
+ collapse, meaning the former risks accessing a page table the latter
+ frees. Fix this by acquiring mmap write lock on init_mm across the
+ whole CPA collapse operation and read lock on the page table
+ manipulation.
+
+* x86 and arm64 permit walks of non-kernel mm's (both allowing efi mm
+ walks, and in x86's case arbitrary mm's), so we ensure kernel mappings
+ remain stable by locking the init_mm as well as the mm being walked.
+
+The ordering of patches is established for both strict dependencies (the
+arm64 partial revert in particular has to be done after the vmap changes)
+and logical ones (the non-kernel mm fix only makes sense once the vmap/CPA
+fixes are in place).
+
+
+This patch (of 3):
+
+Currently there is a nasty race between ptdump and vmap when attempting to
+map a huge P4D, PUD or PMD entry:
+
+* ptdump walks kernel page table ranges it doesn't own.
+
+* When vmap maps ranges it tries to promotes existing ones to huge page
+ tables in vmap_try_huge_[p4d,pud,pmd]() at P4D, PUD and PMD level,
+ freeing the lower page table in [p4d,pud,pmd]_free_[pud,pmd,pte]_page()
+ when it succeeds.
+
+Both of these things can happen at the same time and as a result ptdump
+can access a freed page table, resulting in a use-after-free and memory
+corruption.
+
+This is possible because while ptdump_walk_pgd() holds both the mem
+hotplug lock and the mmap write lock before invoking
+walk_page_range_debug(), vmap takes no relevant locks at all.
+
+Fix this by holding the mmap read lock in vmap_try_huge_*() when freeing
+page tables.
+
+The read lock is sufficient: ptdump is the only walker that must be
+excluded and it holds the mmap write lock. Other holders of the read lock
+may run concurrently, but each exclusively owns the range it operates on
+and cannot reach the page tables freed here.
+
+We also hold the lock while assigning the huge page table entry, which
+means page table walkers observe only the huge or non-huge page table
+entry.
+
+We use a trylock to prevent ptdump from blocking vmap making forward
+progress. This is fine because it's an optimisation in any case, and thus
+the vmap can safely proceed regardless.
+
+All other kernel page table walkers that touch vmalloc ranges either
+exclusively own the memory walked or acquire the mmap lock, so this
+correctly excludes those walkers.
+
+One wrinkle here is commit fa93b45fd397 ("arm64: Enable vmalloc-huge with
+ptdump"), which addresses the issue for arm64 only by explicitly acquiring
+the mmap read lock on kernel page table freeing should a concurrent ptdump
+be in progress.
+
+This is problematic as vmap may acquire the mmap read lock prior to ptdump
+attempting to acquire an mmap write lock, leading to a deadlock when the
+mmap read lock is slept upon on page table freeing due to rwsem
+anti-starvation.
+
+We work around this by predicating the mmap lock being taken on
+!CONFIG_ARM64 for the time being.
+
+With this patch applied, a follow up will partially revert commit
+fa93b45fd397 ("arm64: Enable vmalloc-huge with ptdump") and at that stage
+remove the arm64 ifdeffery.
+
+We also update walk_page_range_debug() to assert the mmap write lock
+unconditionally and update the comment here to reflect this change.
+
+The issue has existed as long as ptdump was available and vmap freed page
+tables when promoting to a huge leaf entry, that is, since commit
+b6bdb7517c3d ("mm/vmalloc: add interfaces to free unmapped page table")
+for huge ioremap, and commit 121e6f3258fe ("mm/vmalloc: hugepage vmalloc
+mappings") for huge vmalloc.
+
+Since the former is the earlier of the two we choose that for our Fixes
+tag.
+
+We also define a guard class for mmap_read_trylock() so we can use
+cleanup.h to make the scope handling cleaner in the implementation.
+
+This patch is based on work by David Carlier (linked), with gratitude!
+
+Link: https://lore.kernel.org/20260723-series-vmap-race-fix-v6-0-8cc77dcc0018@kernel.org
+Link: https://lore.kernel.org/20260723-series-vmap-race-fix-v6-1-8cc77dcc0018@kernel.org
+Fixes: b6bdb7517c3d ("mm/vmalloc: add interfaces to free unmapped page table")
+Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
+Reported-by: syzbot+fd95a72470f5a44e464c@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/6a287988.39669fcc.33b062.00a0.GAE@google.com/T/
+Link: https://lore.kernel.org/linux-mm/20260706203128.162335-1-devnexen@gmail.com/
+Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Reviewed-by: Dev Jain <dev.jain@arm.com>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Reviewed-by: Kiryl Shutsemau <kas@kernel.org>
+Cc: <stable@vger.kernel.org>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: "Borah, Chaitanya Kumar" <chaitanya.kumar.borah@intel.com>
+Cc: "Borislav Petkov (AMD)" <bp@alien8.de>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Liam R. Howlett <liam@infradead.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Ryan Roberts <ryan.roberts@arm.com>
+Cc: Shakeel Butt <shakeel.butt@linux.dev>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Toshi Kani <toshi.kani@hpe.com>
+Cc: "Uladzislau Rezki (Sony)" <urezki@gmail.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Will Deacon <will@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/mmap_lock.h | 1
+ mm/pagewalk.c | 22 +++++++++++---------
+ mm/vmalloc.c | 49 +++++++++++++++++++++++++++++++++++++---------
+ 3 files changed, 53 insertions(+), 19 deletions(-)
+
+--- a/include/linux/mmap_lock.h
++++ b/include/linux/mmap_lock.h
+@@ -397,6 +397,7 @@ static inline void mmap_read_unlock(stru
+
+ DEFINE_GUARD(mmap_read_lock, struct mm_struct *,
+ mmap_read_lock(_T), mmap_read_unlock(_T))
++DEFINE_GUARD_COND(mmap_read_lock, _try, mmap_read_trylock(_T))
+
+ static inline void mmap_read_unlock_non_owner(struct mm_struct *mm)
+ {
+--- a/mm/pagewalk.c
++++ b/mm/pagewalk.c
+@@ -678,6 +678,8 @@ int walk_kernel_page_table_range_lockles
+ * will also not lock the PTEs for the pte_entry() callback.
+ *
+ * This is for debugging purposes ONLY.
++ *
++ * The mmap write lock must be held.
+ */
+ int walk_page_range_debug(struct mm_struct *mm, unsigned long start,
+ unsigned long end, const struct mm_walk_ops *ops,
+@@ -691,6 +693,16 @@ int walk_page_range_debug(struct mm_stru
+ .no_vma = true
+ };
+
++ /*
++ * When walking userland page tables, an mmap write lock must be held to
++ * account for munmap() downgrading to an mmap read lock when tearing
++ * down page tables.
++ *
++ * When walking kernel page tables, an mmap write lock must also be held
++ * to account for page table freeing on vmap huge page mapping.
++ */
++ mmap_assert_write_locked(mm);
++
+ /* For convenience, we allow traversal of kernel mappings. */
+ if (mm == &init_mm)
+ return walk_kernel_page_table_range(start, end, ops,
+@@ -700,16 +712,6 @@ int walk_page_range_debug(struct mm_stru
+ if (!check_ops_valid(ops))
+ return -EINVAL;
+
+- /*
+- * The mmap lock protects the page walker from changes to the page
+- * tables during the walk. However a read lock is insufficient to
+- * protect those areas which don't have a VMA as munmap() detaches
+- * the VMAs before downgrading to a read lock and actually tearing
+- * down PTEs/page tables. In which case, the mmap write lock should
+- * be held.
+- */
+- mmap_assert_write_locked(mm);
+-
+ return walk_pgd_range(start, end, &walk);
+ }
+
+--- a/mm/vmalloc.c
++++ b/mm/vmalloc.c
+@@ -43,6 +43,7 @@
+ #include <asm/tlbflush.h>
+ #include <asm/shmparam.h>
+ #include <linux/page_owner.h>
++#include <linux/cleanup.h>
+
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/vmalloc.h>
+@@ -155,10 +156,24 @@ static int vmap_try_huge_pmd(pmd_t *pmd,
+ if (!IS_ALIGNED(phys_addr, PMD_SIZE))
+ return 0;
+
+- if (pmd_present(*pmd) && !pmd_free_pte_page(pmd, addr))
+- return 0;
++ if (!pmd_present(*pmd))
++ return pmd_set_huge(pmd, phys_addr, prot);
+
+- return pmd_set_huge(pmd, phys_addr, prot);
++ /*
++ * Acquire the mmap read lock to exclude ptdump, which walks
++ * kernel page tables it does not own under the mmap write lock.
++ *
++ * Concurrent read lock holders are safe: each exclusively owns
++ * the range it operates on and cannot reach this page table.
++ */
++#ifndef CONFIG_ARM64
++ scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm)
++#endif
++ {
++ if (!pmd_free_pte_page(pmd, addr))
++ return 0;
++ return pmd_set_huge(pmd, phys_addr, prot);
++ }
+ }
+
+ static int vmap_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
+@@ -205,10 +220,18 @@ static int vmap_try_huge_pud(pud_t *pud,
+ if (!IS_ALIGNED(phys_addr, PUD_SIZE))
+ return 0;
+
+- if (pud_present(*pud) && !pud_free_pmd_page(pud, addr))
+- return 0;
++ if (!pud_present(*pud))
++ return pud_set_huge(pud, phys_addr, prot);
+
+- return pud_set_huge(pud, phys_addr, prot);
++ /* See comment in vmap_try_huge_pmd(). */
++#ifndef CONFIG_ARM64
++ scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm)
++#endif
++ {
++ if (!pud_free_pmd_page(pud, addr))
++ return 0;
++ return pud_set_huge(pud, phys_addr, prot);
++ }
+ }
+
+ static int vmap_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end,
+@@ -256,10 +279,18 @@ static int vmap_try_huge_p4d(p4d_t *p4d,
+ if (!IS_ALIGNED(phys_addr, P4D_SIZE))
+ return 0;
+
+- if (p4d_present(*p4d) && !p4d_free_pud_page(p4d, addr))
+- return 0;
++ if (!p4d_present(*p4d))
++ return p4d_set_huge(p4d, phys_addr, prot);
+
+- return p4d_set_huge(p4d, phys_addr, prot);
++ /* See comment in vmap_try_huge_pmd(). */
++#ifndef CONFIG_ARM64
++ scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm)
++#endif
++ {
++ if (!p4d_free_pud_page(p4d, addr))
++ return 0;
++ return p4d_set_huge(p4d, phys_addr, prot);
++ }
+ }
+
+ static int vmap_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end,