[PATCH 0/2] mm: fix UAF caused by race between ptdump and vmap pgtable freeing

Lorenzo Stoakes posted 2 patches 2 weeks, 1 day ago
There is a newer version of this series
arch/arm64/include/asm/ptdump.h |  2 --
arch/arm64/mm/mmu.c             | 43 ++++-------------------------------------
arch/arm64/mm/ptdump.c          | 11 ++---------
include/linux/mmap_lock.h       |  1 +
mm/pagewalk.c                   | 22 +++++++++++----------
mm/vmalloc.c                    | 41 ++++++++++++++++++++++++++++++---------
6 files changed, 51 insertions(+), 69 deletions(-)
[PATCH 0/2] mm: fix UAF caused by race between ptdump and vmap pgtable freeing
Posted by Lorenzo Stoakes 2 weeks, 1 day ago
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
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 leaf 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
a93b45fd397 ("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
a93b45fd397 ("arm64: Enable vmalloc-huge with ptdump"), keeping the
enablement of huge vmap support, and removing the ifdeffery with the
partial revert patch.

Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
---
Lorenzo Stoakes (2):
      mm/vmalloc: acquire init_mm read lock on huge vmap promotion
      Revert "arm64: Enable vmalloc-huge with ptdump"

 arch/arm64/include/asm/ptdump.h |  2 --
 arch/arm64/mm/mmu.c             | 43 ++++-------------------------------------
 arch/arm64/mm/ptdump.c          | 11 ++---------
 include/linux/mmap_lock.h       |  1 +
 mm/pagewalk.c                   | 22 +++++++++++----------
 mm/vmalloc.c                    | 41 ++++++++++++++++++++++++++++++---------
 6 files changed, 51 insertions(+), 69 deletions(-)
---
base-commit: a635d6748234582ea287c5ffeae28b9b23f91c7e
change-id: 20260710-series-vmap-race-fix-2a4cac988938

Cheers,
-- 
Lorenzo Stoakes <ljs@kernel.org>
Re: [PATCH 0/2] mm: fix UAF caused by race between ptdump and vmap pgtable freeing
Posted by Dev Jain 1 week, 6 days ago

On 10/07/26 4:19 pm, Lorenzo Stoakes wrote:
> 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
> 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 leaf 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
> a93b45fd397 ("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
> a93b45fd397 ("arm64: Enable vmalloc-huge with ptdump"), keeping the
> enablement of huge vmap support, and removing the ifdeffery with the
> partial revert patch.
> 
> Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> ---

Will Deacon had pushed back on a similar approach:
https://lore.kernel.org/all/20250530123527.GA30463@willie-the-truck/

Although now when I read back that thread, it feels more so like my
incompetency to convince :) because:

1. I don't think this pmd_free_pte_page() path is a hot path at all

2. We are doing a try lock which is almost guaranteed to succeed,
   so it's not like we are losing out on block mappings

3. Any overhead from the try lock will get dominated by the pgtable
   page free/TLB flush

I guess you did not take the RCU approach because that would put code
into the generic kernel pgtable freeing path.

I liked the RCU approach because I hate the fact that ptdump takes
an mmap_write_lock when it is literally only reading the pgtables.
But your approach is simpler and fixes the problem at the particular spot
and not hammers the fix into a generic path. So overall, ACK.


> Lorenzo Stoakes (2):
>       mm/vmalloc: acquire init_mm read lock on huge vmap promotion
>       Revert "arm64: Enable vmalloc-huge with ptdump"
> 
>  arch/arm64/include/asm/ptdump.h |  2 --
>  arch/arm64/mm/mmu.c             | 43 ++++-------------------------------------
>  arch/arm64/mm/ptdump.c          | 11 ++---------
>  include/linux/mmap_lock.h       |  1 +
>  mm/pagewalk.c                   | 22 +++++++++++----------
>  mm/vmalloc.c                    | 41 ++++++++++++++++++++++++++++++---------
>  6 files changed, 51 insertions(+), 69 deletions(-)
> ---
> base-commit: a635d6748234582ea287c5ffeae28b9b23f91c7e
> change-id: 20260710-series-vmap-race-fix-2a4cac988938
> 
> Cheers,
Re: [PATCH 0/2] mm: fix UAF caused by race between ptdump and vmap pgtable freeing
Posted by Lorenzo Stoakes 1 week, 6 days ago
On Sun, Jul 12, 2026 at 12:50:08PM +0530, Dev Jain wrote:
> Will Deacon had pushed back on a similar approach:
> https://lore.kernel.org/all/20250530123527.GA30463@willie-the-truck/
>
> Although now when I read back that thread, it feels more so like my
> incompetency to convince :) because:

No haha not so, I think more like this stuff is fiddly.

>
> 1. I don't think this pmd_free_pte_page() path is a hot path at all

Right, and we don't actually alter that path anyway

>
> 2. We are doing a try lock which is almost guaranteed to succeed,
>    so it's not like we are losing out on block mappings

Also it's specifically only on when vmap tries to make a mapping huge, and
this path is being inconsistent with a convention that already existed - if
you manipulate kernel page table mappings that can interact with other page
table walkers, you have to take the init_mm mmap lock.

>
> 3. Any overhead from the try lock will get dominated by the pgtable
>    page free/TLB flush

Yup.

>
> I guess you did not take the RCU approach because that would put code
> into the generic kernel pgtable freeing path.

Well a number of reasons:

* firstly yes it makes the code path always RCU only to suit a specific
  debug user as you say :)

* Importantly - we risk genuine RCU stall issues, because the ptdump then
  has to be RCU too over vast ranges.

  To work around that you have to shard the ptdump walk, make an assumption
  all callbacks are RCU-safe, and that the sharding suffices to avoid these
  stalls.

  It's a ton of complexity and assumptions to account for... vmalloc doing
  the wrong thing.

* It is an established precedent that we mmap lock init_mm for kernel page
  table walking as per mm/pagewalk.c. It'd require significant rework there
  and would disallow any future walkers like this if we were to require
  RCU.

* The mmap lock approach is simple, safe, and as you say is only actually
  required in code paths that manipulate page tables and thus are already
  not hotpaths.

* If there's future work to free vmalloc page tables upon vunmap()
  (currently it does not), we have a stable, established basis for doing so
  that again puts the weight of the work on the operation being performed
  rather than anything else.

>
> I liked the RCU approach because I hate the fact that ptdump takes
> an mmap_write_lock when it is literally only reading the pgtables.

Well you have to do that for the userland side, because there could be a
concurrent downgraded mmap read lock during an munmap, and the same goes
for non-VMA kernel ranges too, so it would have to keep doing that
regardless.

> But your approach is simpler and fixes the problem at the particular spot
> and not hammers the fix into a generic path. So overall, ACK.

Thanks!

>
>
> > Lorenzo Stoakes (2):
> >       mm/vmalloc: acquire init_mm read lock on huge vmap promotion
> >       Revert "arm64: Enable vmalloc-huge with ptdump"
> >
> >  arch/arm64/include/asm/ptdump.h |  2 --
> >  arch/arm64/mm/mmu.c             | 43 ++++-------------------------------------
> >  arch/arm64/mm/ptdump.c          | 11 ++---------
> >  include/linux/mmap_lock.h       |  1 +
> >  mm/pagewalk.c                   | 22 +++++++++++----------
> >  mm/vmalloc.c                    | 41 ++++++++++++++++++++++++++++++---------
> >  6 files changed, 51 insertions(+), 69 deletions(-)
> > ---
> > base-commit: a635d6748234582ea287c5ffeae28b9b23f91c7e
> > change-id: 20260710-series-vmap-race-fix-2a4cac988938
> >
> > Cheers,
>

Cheers, Lorenzo
Re: [PATCH 0/2] mm: fix UAF caused by race between ptdump and vmap pgtable freeing
Posted by Will Deacon 1 week, 5 days ago
On Sun, Jul 12, 2026 at 09:46:46AM +0100, Lorenzo Stoakes wrote:
> On Sun, Jul 12, 2026 at 12:50:08PM +0530, Dev Jain wrote:
> > Will Deacon had pushed back on a similar approach:
> > https://lore.kernel.org/all/20250530123527.GA30463@willie-the-truck/
> >
> > Although now when I read back that thread, it feels more so like my
> > incompetency to convince :) because:
> 
> No haha not so, I think more like this stuff is fiddly.

Yup, not disputing that this is hard to get right.

Conceptually, adding locking purely to deal with a vanishingly rare,
debug reader does turn my head but I'm _far_ less concerned about it if
it's done in the core code, as is the case here. x86 needs it and we're
recently running into related locking issues with the set_memory_*()
APIs if we want to collapse the page-table on arm64 [1]. If the overhead
is flagged as an issue, we can see if it's worth generalising the static
key trick that the second patch reverts but I definitely wouldn't start
from that position.

Will

[1] https://lore.kernel.org/linux-arm-kernel/799181c3-a1a1-4de7-bc6a-576d3282efb0@arm.com/
Re: [PATCH 0/2] mm: fix UAF caused by race between ptdump and vmap pgtable freeing
Posted by Mike Rapoport 1 week, 5 days ago
On Mon, Jul 13, 2026 at 12:37:46PM +0100, Will Deacon wrote:
> On Sun, Jul 12, 2026 at 09:46:46AM +0100, Lorenzo Stoakes wrote:
> > On Sun, Jul 12, 2026 at 12:50:08PM +0530, Dev Jain wrote:
> > > Will Deacon had pushed back on a similar approach:
> > > https://lore.kernel.org/all/20250530123527.GA30463@willie-the-truck/
> > >
> > > Although now when I read back that thread, it feels more so like my
> > > incompetency to convince :) because:
> > 
> > No haha not so, I think more like this stuff is fiddly.
> 
> Yup, not disputing that this is hard to get right.
> 
> Conceptually, adding locking purely to deal with a vanishingly rare,
> debug reader does turn my head but I'm _far_ less concerned about it if
> it's done in the core code, as is the case here. x86 needs it and we're
> recently running into related locking issues with the set_memory_*()
> APIs if we want to collapse the page-table on arm64 [1]. If the overhead
> is flagged as an issue, we can see if it's worth generalising the static
> key trick that the second patch reverts but I definitely wouldn't start
> from that position.

I'd say it's worth generalizing the set_memory APIs ;-)

Since it's de-facto machinery for manipulation of the kernel page tables it
makes sense to have a common code for page table walks with hooks to
architectures for checking/setting/clearing protection bits.

Coincidentally, I'm working on a POC that lifts x86's CPA into mm/ with
the intention to later use it on other architectures.

> Will
> 
> [1] https://lore.kernel.org/linux-arm-kernel/799181c3-a1a1-4de7-bc6a-576d3282efb0@arm.com/

-- 
Sincerely yours,
Mike.
Re: [PATCH 0/2] mm: fix UAF caused by race between ptdump and vmap pgtable freeing
Posted by Lorenzo Stoakes (ARM) 1 week, 5 days ago
+cc Kiryl as ref'd below.

On Mon, Jul 13, 2026 at 05:08:19PM +0300, Mike Rapoport wrote:
> On Mon, Jul 13, 2026 at 12:37:46PM +0100, Will Deacon wrote:
> > On Sun, Jul 12, 2026 at 09:46:46AM +0100, Lorenzo Stoakes wrote:
> > > On Sun, Jul 12, 2026 at 12:50:08PM +0530, Dev Jain wrote:
> > > > Will Deacon had pushed back on a similar approach:
> > > > https://lore.kernel.org/all/20250530123527.GA30463@willie-the-truck/
> > > >
> > > > Although now when I read back that thread, it feels more so like my
> > > > incompetency to convince :) because:
> > >
> > > No haha not so, I think more like this stuff is fiddly.
> >
> > Yup, not disputing that this is hard to get right.
> >
> > Conceptually, adding locking purely to deal with a vanishingly rare,
> > debug reader does turn my head but I'm _far_ less concerned about it if
> > it's done in the core code, as is the case here. x86 needs it and we're
> > recently running into related locking issues with the set_memory_*()
> > APIs if we want to collapse the page-table on arm64 [1]. If the overhead
> > is flagged as an issue, we can see if it's worth generalising the static
> > key trick that the second patch reverts but I definitely wouldn't start
> > from that position.

Yeah I think my solution is not exactly pretty but it's the best fix as a hotfix
thing _right now_.

As Kiryl points out the nicer long-term solution would be RCU freeing, but I
think that's the wrong solution for a _fix_ right now, rather something to look
at as a larger structural change in the future.

>
> I'd say it's worth generalizing the set_memory APIs ;-)
>
> Since it's de-facto machinery for manipulation of the kernel page tables it
> makes sense to have a common code for page table walks with hooks to
> architectures for checking/setting/clearing protection bits.
>
> Coincidentally, I'm working on a POC that lifts x86's CPA into mm/ with
> the intention to later use it on other architectures.

Lovely :)

There's another issue with CPA too (planned to raise this separately already but
been super busy/distracted lately :) - it doesn't actually mark its page tables
as kernel page tables so we actually have a gap if an IOMMU happens to map that.

I am planning to send a patch for that anyway but it's indicative of this
needing to be shared code, and lifting stuff up to be shared is good in general
:)

>
> > Will
> >
> > [1] https://lore.kernel.org/linux-arm-kernel/799181c3-a1a1-4de7-bc6a-576d3282efb0@arm.com/
>
> --
> Sincerely yours,
> Mike.

Cheers, Lorenzo
Re: [PATCH 0/2] mm: fix UAF caused by race between ptdump and vmap pgtable freeing
Posted by Dev Jain 1 week, 6 days ago

On 12/07/26 2:16 pm, Lorenzo Stoakes wrote:
> On Sun, Jul 12, 2026 at 12:50:08PM +0530, Dev Jain wrote:
>> Will Deacon had pushed back on a similar approach:
>> https://lore.kernel.org/all/20250530123527.GA30463@willie-the-truck/
>>
>> Although now when I read back that thread, it feels more so like my
>> incompetency to convince :) because:
> 
> No haha not so, I think more like this stuff is fiddly.
> 
>>
>> 1. I don't think this pmd_free_pte_page() path is a hot path at all
> 
> Right, and we don't actually alter that path anyway
> 
>>
>> 2. We are doing a try lock which is almost guaranteed to succeed,
>>    so it's not like we are losing out on block mappings
> 
> Also it's specifically only on when vmap tries to make a mapping huge, and
> this path is being inconsistent with a convention that already existed - if
> you manipulate kernel page table mappings that can interact with other page
> table walkers, you have to take the init_mm mmap lock.
> 
>>
>> 3. Any overhead from the try lock will get dominated by the pgtable
>>    page free/TLB flush
> 
> Yup.
> 
>>
>> I guess you did not take the RCU approach because that would put code
>> into the generic kernel pgtable freeing path.
> 
> Well a number of reasons:
> 
> * firstly yes it makes the code path always RCU only to suit a specific
>   debug user as you say :)
> 
> * Importantly - we risk genuine RCU stall issues, because the ptdump then
>   has to be RCU too over vast ranges.
> 
>   To work around that you have to shard the ptdump walk, make an assumption
>   all callbacks are RCU-safe, and that the sharding suffices to avoid these
>   stalls.
> 
>   It's a ton of complexity and assumptions to account for... vmalloc doing
>   the wrong thing.
> 
> * It is an established precedent that we mmap lock init_mm for kernel page
>   table walking as per mm/pagewalk.c. It'd require significant rework there
>   and would disallow any future walkers like this if we were to require
>   RCU.
> 
> * The mmap lock approach is simple, safe, and as you say is only actually
>   required in code paths that manipulate page tables and thus are already
>   not hotpaths.
> 
> * If there's future work to free vmalloc page tables upon vunmap()
>   (currently it does not), we have a stable, established basis for doing so
>   that again puts the weight of the work on the operation being performed
>   rather than anything else.
> 
>>
>> I liked the RCU approach because I hate the fact that ptdump takes
>> an mmap_write_lock when it is literally only reading the pgtables.
> 
> Well you have to do that for the userland side, because there could be a
> concurrent downgraded mmap read lock during an munmap, and the same goes
> for non-VMA kernel ranges too, so it would have to keep doing that
> regardless.

Oh right, I didn't know x86 was using ptdump for user tables too.


> 
>> But your approach is simpler and fixes the problem at the particular spot
>> and not hammers the fix into a generic path. So overall, ACK.
> 
> Thanks!
> 
>>
>>
>>> Lorenzo Stoakes (2):
>>>       mm/vmalloc: acquire init_mm read lock on huge vmap promotion
>>>       Revert "arm64: Enable vmalloc-huge with ptdump"
>>>
>>>  arch/arm64/include/asm/ptdump.h |  2 --
>>>  arch/arm64/mm/mmu.c             | 43 ++++-------------------------------------
>>>  arch/arm64/mm/ptdump.c          | 11 ++---------
>>>  include/linux/mmap_lock.h       |  1 +
>>>  mm/pagewalk.c                   | 22 +++++++++++----------
>>>  mm/vmalloc.c                    | 41 ++++++++++++++++++++++++++++++---------
>>>  6 files changed, 51 insertions(+), 69 deletions(-)
>>> ---
>>> base-commit: a635d6748234582ea287c5ffeae28b9b23f91c7e
>>> change-id: 20260710-series-vmap-race-fix-2a4cac988938
>>>
>>> Cheers,
>>
> 
> Cheers, Lorenzo
Re: [PATCH 0/2] mm: fix UAF caused by race between ptdump and vmap pgtable freeing
Posted by David CARLIER 2 weeks, 1 day ago
Hi Lorenzo,

On Fri, 10 Jul 2026 at 11:50, Lorenzo Stoakes <ljs@kernel.org> wrote:
>
> 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
> 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 leaf 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
> a93b45fd397 ("arm64: Enable vmalloc-huge with ptdump"), which this series

seems it should be fa93b45fd397.

Cheers.
> 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
> a93b45fd397 ("arm64: Enable vmalloc-huge with ptdump"), keeping the
> enablement of huge vmap support, and removing the ifdeffery with the
> partial revert patch.
>
> Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> ---
> Lorenzo Stoakes (2):
>       mm/vmalloc: acquire init_mm read lock on huge vmap promotion
>       Revert "arm64: Enable vmalloc-huge with ptdump"
>
>  arch/arm64/include/asm/ptdump.h |  2 --
>  arch/arm64/mm/mmu.c             | 43 ++++-------------------------------------
>  arch/arm64/mm/ptdump.c          | 11 ++---------
>  include/linux/mmap_lock.h       |  1 +
>  mm/pagewalk.c                   | 22 +++++++++++----------
>  mm/vmalloc.c                    | 41 ++++++++++++++++++++++++++++++---------
>  6 files changed, 51 insertions(+), 69 deletions(-)
> ---
> base-commit: a635d6748234582ea287c5ffeae28b9b23f91c7e
> change-id: 20260710-series-vmap-race-fix-2a4cac988938
>
> Cheers,
> --
> Lorenzo Stoakes <ljs@kernel.org>
>
Re: [PATCH 0/2] mm: fix UAF caused by race between ptdump and vmap pgtable freeing
Posted by Lorenzo Stoakes 2 weeks, 1 day ago
On Fri, Jul 10, 2026 at 12:44:20PM +0100, David CARLIER wrote:
> Hi Lorenzo,
>
> On Fri, 10 Jul 2026 at 11:50, Lorenzo Stoakes <ljs@kernel.org> wrote:
> >
> > 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
> > 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 leaf 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
> > a93b45fd397 ("arm64: Enable vmalloc-huge with ptdump"), which this series
>
> seems it should be fa93b45fd397.

Yeah oops, I typo'd that.

Andrew - could you fix that up for me? Thanks!

>
> Cheers.
> > 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
> > a93b45fd397 ("arm64: Enable vmalloc-huge with ptdump"), keeping the
> > enablement of huge vmap support, and removing the ifdeffery with the
> > partial revert patch.
> >
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > ---
> > Lorenzo Stoakes (2):
> >       mm/vmalloc: acquire init_mm read lock on huge vmap promotion
> >       Revert "arm64: Enable vmalloc-huge with ptdump"
> >
> >  arch/arm64/include/asm/ptdump.h |  2 --
> >  arch/arm64/mm/mmu.c             | 43 ++++-------------------------------------
> >  arch/arm64/mm/ptdump.c          | 11 ++---------
> >  include/linux/mmap_lock.h       |  1 +
> >  mm/pagewalk.c                   | 22 +++++++++++----------
> >  mm/vmalloc.c                    | 41 ++++++++++++++++++++++++++++++---------
> >  6 files changed, 51 insertions(+), 69 deletions(-)
> > ---
> > base-commit: a635d6748234582ea287c5ffeae28b9b23f91c7e
> > change-id: 20260710-series-vmap-race-fix-2a4cac988938
> >
> > Cheers,
> > --
> > Lorenzo Stoakes <ljs@kernel.org>
> >