From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
To: Ngoc Quy <ngocquy0700@gmail.com>
Cc: akpm@linux-foundation.org, liam@infradead.org,
Vlastimil Babka <vbabka@kernel.org>,
Jann Horn <jannh@google.com>, Pedro Falcato <pfalcato@suse.de>,
Muhammad Usama Anjum <usama.anjum@collabora.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
linux-fsdevel@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH] fs/proc/task_mmu: pin mm_users in do_pagemap_scan()
Date: Mon, 26 Oct 2026 14:37:05 +0000 [thread overview]
Message-ID: <at9jXXDoMLi3X2EF@gremlin> (raw)
In-Reply-To: <20261014095540.3261469-1-ngocquy0700@gmail.com>
On Wed, Oct 14, 2026 at 04:55:40PM +0700, Ngoc Quy wrote:
> The PAGEMAP_SCAN ioctl takes mmap_read_lock() on an mm obtained from
> /proc/<pid>/pagemap without holding a reference to mm_users.
>
> proc_mem_open() deliberately grabs only mm_count, so a consumer that
NIT: just say mmgrab() here. Its comment already explains the
mmget_not_zero() semantics.
> touches the address space has to call mmget_not_zero() first. Every
> other consumer in this file does -- m_start(), do_procmap_query(),
> show_smaps_rollup() and pagemap_read() -- but do_pagemap_scan() does
> not.
>
> Without that reference the target can reach exit_mmap() concurrently,
> and exit_mmap() calls unmap_vmas() while holding mmap_lock only for
> reading, which does not exclude the scanner. For ordinary VMAs this is
> harmless, as free_pgtables() and remove_vma() run afterwards under
> mmap_write_lock. A shared hugetlb VMA is different: __hugetlb_zap_end()
> frees the VMA's hugetlb_vma_lock inside the read-locked phase.
>
> walk_hugetlb_range() can therefore load vma->vm_private_data, have the
> lock freed underneath it, and then down_read() a freed rw_semaphore.
> The load happens before the freeing side clears the pointer, so this is
> a use-after-free and not a NULL dereference. Any unprivileged user can
> reach it with no huge pages configured, as hugetlb_reserve_pages()
> allocates the lock before the VM_NORESERVE early return.
>
> Pin mm_users across the scan, the way the other consumers do. mmput()
> from the exiting task can then no longer reach exit_mmap() while a walk
> is in progress.
>
> Fixes: 52526ca7fdb9 ("fs/proc/task_mmu: implement IOCTL to get and optionally clear info about PTEs")
> Cc: stable@vger.kernel.org
> Assisted-by: Claude:claude-opus-5
This is the old-format tag, but the tag is no longer required, so let's
just drop it.
Instead, write something under the --- about AI usage.
> Signed-off-by: Ngoc Quy <ngocquy0700@gmail.com>
LGTM so:
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> ---
> fs/proc/task_mmu.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> index 5c54aebe2118..8825b01f5e38 100644
> --- a/fs/proc/task_mmu.c
> +++ b/fs/proc/task_mmu.c
> @@ -3231,15 +3231,18 @@ static long do_pagemap_scan(struct mm_struct *mm, unsigned long uarg)
> size_t n_ranges_out = 0;
> int ret;
>
> + if (!mm || !mmget_not_zero(mm))
> + return -ESRCH;
> +
> ret = pagemap_scan_get_args(&p.arg, uarg);
> if (ret)
> - return ret;
> + goto out_mmput;
>
> p.masks_of_interest = p.arg.category_mask | p.arg.category_anyof_mask |
> p.arg.return_mask;
> ret = pagemap_scan_init_bounce_buffer(&p);
> if (ret)
> - return ret;
> + goto out_mmput;
>
> for (walk_start = p.arg.start; walk_start < p.arg.end;
> walk_start = p.arg.walk_end) {
> @@ -3294,6 +3297,8 @@ static long do_pagemap_scan(struct mm_struct *mm, unsigned long uarg)
> ret = -EFAULT;
>
> kfree(p.vec_buf);
> +out_mmput:
> + mmput(mm);
> return ret;
> }
>
>
> base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
> --
> 2.53.0
>
--
Cheers, Lorenzo
prev parent reply other threads:[~2026-10-26 14:37 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-14 9:55 [PATCH] fs/proc/task_mmu: pin mm_users in do_pagemap_scan() Ngoc Quy
2026-10-20 0:46 ` Andrew Morton
2026-10-20 10:00 ` Ngọc Quý
2026-10-25 10:55 ` David Hildenbrand (Arm)
2026-10-26 13:39 ` Lorenzo Stoakes (ARM)
2026-10-25 10:56 ` David Hildenbrand (Arm)
2026-10-26 13:25 ` Pedro Falcato
2026-10-26 14:37 ` Lorenzo Stoakes (ARM) [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=at9jXXDoMLi3X2EF@gremlin \
--to=ljs@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=jannh@google.com \
--cc=liam@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ngocquy0700@gmail.com \
--cc=pfalcato@suse.de \
--cc=stable@vger.kernel.org \
--cc=usama.anjum@collabora.com \
--cc=vbabka@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.