[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <99a5ca7c-006a-443f-909b-d6375164412e@lucifer.local>
Date: Fri, 2 Jan 2026 17:46:28 +0000
From: Lorenzo Stoakes <lorenzo.stoakes@...cle.com>
To: Harry Yoo <harry.yoo@...cle.com>
Cc: "David Hildenbrand (Red Hat)" <david@...nel.org>,
Jeongjun Park <aha310510@...il.com>, Liam.Howlett@...cle.com,
akpm@...ux-foundation.org, jannh@...gle.com,
linux-kernel@...r.kernel.org, linux-mm@...ck.org, riel@...riel.com,
syzbot+b165fc2e11771c66d8ba@...kaller.appspotmail.com,
syzkaller-bugs@...glegroups.com, vbabka@...e.cz
Subject: Re: [syzbot] [mm?] WARNING in folio_remove_rmap_ptes
OK I now have a sane repro. It doesn't require a race, not even MAP_PRIVATE
file-backed VMAs, it just requires the problematic merge to occur.
This triggers both for KASAN (doesn't even need iteration) and with sufficient
iterations (to avoid re-use of anon_vma I guess?) triggers Jann's assert.
If you're using a >=6.17 kernel in your host I recommend you don't run this
locally but rather in a VM :P
Requires CONFIG_DEBUG_VM or CONFIG_KASAN to be visible.
Will follow up with proper patch. Not sure a test makes sense as we can't really
assert anything sane here, will perhaps include in commit message instead.
Cheers, Lorenzo
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#define RESERVED_PGS (100)
#define VMA_A_PGS (10)
#define VMA_B_PGS (10)
#define NUM_ITERS (1000)
static void trigger_bug(void)
{
unsigned long page_size = sysconf(_SC_PAGE_SIZE);
char *reserved, *ptr_a, *ptr_b;
/*
* The goal here is to achieve:
*
* mremap() with MREMAP_DONTUNMAP such that A and B merge:
*
* |-------------------------|
* | |
* | |-----------| |---------|
* v | unfaulted | | faulted |
* |-----------| |---------|
* B A
*
* Then unmap VMA A to trigger the bug.
*/
/* Reserve a region of memory to operate in. */
reserved = mmap(NULL, RESERVED_PGS * page_size, PROT_NONE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (reserved == MAP_FAILED) {
perror("mmap reserved");
exit(EXIT_FAILURE);
}
/* Map VMA A into place. */
ptr_a = mmap(&reserved[page_size], VMA_A_PGS * page_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
if (ptr_a == MAP_FAILED) {
perror("mmap VMA A");
exit(EXIT_FAILURE);
}
/* Fault it in. */
ptr_a[0] = 'x';
/*
* Now move it out of the way so we can place VMA B in position,
* unfaulted.
*/
ptr_a = mremap(ptr_a, VMA_A_PGS * page_size, VMA_A_PGS * page_size,
MREMAP_FIXED | MREMAP_MAYMOVE, &reserved[50 * page_size]);
if (ptr_a == MAP_FAILED) {
perror("mremap VMA A out of the way");
exit(EXIT_FAILURE);
}
/* Map VMA B into place. */
ptr_b = mmap(&reserved[page_size + VMA_A_PGS * page_size], VMA_B_PGS * page_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
if (ptr_b == MAP_FAILED) {
perror("mmap VMA B");
exit(EXIT_FAILURE);
}
/* Now move VMA A into position with MREMAP_DONTUNMAP to trigger the bug. */
ptr_a = mremap(ptr_a, VMA_A_PGS * page_size, VMA_A_PGS * page_size,
MREMAP_FIXED | MREMAP_MAYMOVE | MREMAP_DONTUNMAP,
&reserved[page_size]);
if (ptr_a == MAP_FAILED) {
perror("mremap VMA A with MREMAP_DONTUNMAP");
exit(EXIT_FAILURE);
}
/* Finally, unmap VMA A which should trigger the bug. */
munmap(ptr_a, VMA_A_PGS * page_size);
/* Cleanup in case bug didn't trigger sufficiently visibly... */
munmap(reserved, RESERVED_PGS * page_size);
}
int main(void)
{
int i;
for (i = 0; i < NUM_ITERS; i++)
trigger_bug();
return EXIT_SUCCESS;
}
Powered by blists - more mailing lists