Commit 91325f31 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'mm-hotfixes-stable-2025-08-12-20-50' of...

Merge tag 'mm-hotfixes-stable-2025-08-12-20-50' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull misc fixes from Andrew Morton:
 "12 hotfixes. 5 are cc:stable and the remainder address post-6.16
  issues or aren't considered necessary for -stable kernels.

  10 of these fixes are for MM"

* tag 'mm-hotfixes-stable-2025-08-12-20-50' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
  proc: proc_maps_open allow proc_mem_open to return NULL
  mm/mremap: avoid expensive folio lookup on mremap folio pte batch
  userfaultfd: fix a crash in UFFDIO_MOVE when PMD is a migration entry
  mm: pass page directly instead of using folio_page
  selftests/proc: fix string literal warning in proc-maps-race.c
  fs/proc/task_mmu: hold PTL in pagemap_hugetlb_range and gather_hugetlb_stats
  mm/smaps: fix race between smaps_hugetlb_range and migration
  mm: fix the race between collapse and PT_RECLAIM under per-vma lock
  mm/kmemleak: avoid soft lockup in __kmemleak_do_cleanup()
  MAINTAINERS: add Masami as a reviewer of hung task detector
  mm/kmemleak: avoid deadlock by moving pr_warn() outside kmemleak_lock
  kasan/test: fix protection against compiler elision
parents 8742b2d8 c0e1b774
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -11438,6 +11438,7 @@ F: drivers/tty/hvc/
HUNG TASK DETECTOR
M:	Andrew Morton <akpm@linux-foundation.org>
R:	Lance Yang <lance.yang@linux.dev>
R:	Masami Hiramatsu <mhiramat@kernel.org>
L:	linux-kernel@vger.kernel.org
S:	Maintained
F:	include/linux/hung_task.h
+18 −6
Original line number Diff line number Diff line
@@ -340,8 +340,8 @@ static int proc_maps_open(struct inode *inode, struct file *file,

	priv->inode = inode;
	priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
	if (IS_ERR_OR_NULL(priv->mm)) {
		int err = priv->mm ? PTR_ERR(priv->mm) : -ESRCH;
	if (IS_ERR(priv->mm)) {
		int err = PTR_ERR(priv->mm);

		seq_release_private(inode, file);
		return err;
@@ -1148,10 +1148,13 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask,
{
	struct mem_size_stats *mss = walk->private;
	struct vm_area_struct *vma = walk->vma;
	pte_t ptent = huge_ptep_get(walk->mm, addr, pte);
	struct folio *folio = NULL;
	bool present = false;
	spinlock_t *ptl;
	pte_t ptent;

	ptl = huge_pte_lock(hstate_vma(vma), walk->mm, pte);
	ptent = huge_ptep_get(walk->mm, addr, pte);
	if (pte_present(ptent)) {
		folio = page_folio(pte_page(ptent));
		present = true;
@@ -1170,6 +1173,7 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask,
		else
			mss->private_hugetlb += huge_page_size(hstate_vma(vma));
	}
	spin_unlock(ptl);
	return 0;
}
#else
@@ -2017,12 +2021,14 @@ static int pagemap_hugetlb_range(pte_t *ptep, unsigned long hmask,
	struct pagemapread *pm = walk->private;
	struct vm_area_struct *vma = walk->vma;
	u64 flags = 0, frame = 0;
	spinlock_t *ptl;
	int err = 0;
	pte_t pte;

	if (vma->vm_flags & VM_SOFTDIRTY)
		flags |= PM_SOFT_DIRTY;

	ptl = huge_pte_lock(hstate_vma(vma), walk->mm, ptep);
	pte = huge_ptep_get(walk->mm, addr, ptep);
	if (pte_present(pte)) {
		struct folio *folio = page_folio(pte_page(pte));
@@ -2050,11 +2056,12 @@ static int pagemap_hugetlb_range(pte_t *ptep, unsigned long hmask,

		err = add_to_pagemap(&pme, pm);
		if (err)
			return err;
			break;
		if (pm->show_pfn && (flags & PM_PRESENT))
			frame++;
	}

	spin_unlock(ptl);
	cond_resched();

	return err;
@@ -3128,17 +3135,22 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr,
static int gather_hugetlb_stats(pte_t *pte, unsigned long hmask,
		unsigned long addr, unsigned long end, struct mm_walk *walk)
{
	pte_t huge_pte = huge_ptep_get(walk->mm, addr, pte);
	pte_t huge_pte;
	struct numa_maps *md;
	struct page *page;
	spinlock_t *ptl;

	ptl = huge_pte_lock(hstate_vma(walk->vma), walk->mm, pte);
	huge_pte = huge_ptep_get(walk->mm, addr, pte);
	if (!pte_present(huge_pte))
		return 0;
		goto out;

	page = pte_page(huge_pte);

	md = walk->private;
	gather_stats(page, md, pte_dirty(huge_pte), 1);
out:
	spin_unlock(ptl);
	return 0;
}

+1 −1
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ static struct {
 * Some tests use these global variables to store return values from function
 * calls that could otherwise be eliminated by the compiler as dead code.
 */
static volatile void *kasan_ptr_result;
static void *volatile kasan_ptr_result;
static volatile int kasan_int_result;

/* Probe for console output: obtains test_status lines of interest. */
+1 −1
Original line number Diff line number Diff line
@@ -1172,11 +1172,11 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
	if (result != SCAN_SUCCEED)
		goto out_up_write;
	/* check if the pmd is still valid */
	vma_start_write(vma);
	result = check_pmd_still_valid(mm, address, pmd);
	if (result != SCAN_SUCCEED)
		goto out_up_write;

	vma_start_write(vma);
	anon_vma_lock_write(vma->anon_vma);

	mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm, address,
+9 −1
Original line number Diff line number Diff line
@@ -470,6 +470,7 @@ static struct kmemleak_object *mem_pool_alloc(gfp_t gfp)
{
	unsigned long flags;
	struct kmemleak_object *object;
	bool warn = false;

	/* try the slab allocator first */
	if (object_cache) {
@@ -488,8 +489,10 @@ static struct kmemleak_object *mem_pool_alloc(gfp_t gfp)
	else if (mem_pool_free_count)
		object = &mem_pool[--mem_pool_free_count];
	else
		pr_warn_once("Memory pool empty, consider increasing CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE\n");
		warn = true;
	raw_spin_unlock_irqrestore(&kmemleak_lock, flags);
	if (warn)
		pr_warn_once("Memory pool empty, consider increasing CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE\n");

	return object;
}
@@ -2181,6 +2184,7 @@ static const struct file_operations kmemleak_fops = {
static void __kmemleak_do_cleanup(void)
{
	struct kmemleak_object *object, *tmp;
	unsigned int cnt = 0;

	/*
	 * Kmemleak has already been disabled, no need for RCU list traversal
@@ -2189,6 +2193,10 @@ static void __kmemleak_do_cleanup(void)
	list_for_each_entry_safe(object, tmp, &object_list, object_list) {
		__remove_object(object);
		__delete_object(object);

		/* Call cond_resched() once per 64 iterations to avoid soft lockup */
		if (!(++cnt & 0x3f))
			cond_resched();
	}
}

Loading