Re: [syzbot] [mm?] [ext4?] WARNING in __folio_set_anon

From: Lance Yang

Date: Thu Sep 24 2026 - 05:30:01 EST




On 2026/9/24 16:52, Lorenzo Stoakes (ARM) wrote:
On Thu, Sep 24, 2026 at 09:50:02AM +0200, David Hildenbrand (Arm) wrote:
On 9/24/26 09:43, David Hildenbrand (Arm) wrote:
On 9/24/26 08:54, Lance Yang wrote:

On Wed, Sep 23, 2026 at 10:00:37PM -0700, syzbot wrote:
Hello,

syzbot found the following issue on:

HEAD commit: 38872197cae2 Merge branch 'for-next/fixes' into for-kernelci
git tree: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci
console output: https://syzkaller.appspot.com/x/log.txt?x=17a44d25580000
kernel config: https://syzkaller.appspot.com/x/.config?x=56ed23170c168d4c
dashboard link: https://syzkaller.appspot.com/bug?extid=c181d3198e98f8aef8b9
compiler: Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
userspace arch: arm64
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=16a36515580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=16dcf4c9580000

Looking at the repro, emm ... the repro maps an O_RDONLY /dev/zero fd with

Does this trigger upstream or only after Lorenzo's rework (not upstream yet IIRC)

It'd trigger with my make MAP_PRIVATE-/dev/zero true anon stuff too yes.


46827ac1ab221 mm/vma: make MAP_PRIVATE-mapped /dev/zero mappings truly anonymous
db7438ea23180 mm/vma: only permit MAP_PRIVATE /dev/zero to be mapped anonymous
54e8e096ea86b mm: implement file_is_dev_zero() to uniquely identify /dev/zero
fb24843cfd9eb mm: move drivers/char/mem.c to mm/char-mem.c

I assume it triggers upstream. Does it also trigger with lorenzo's changes?

MAP_SHARED | PROT_READ. do_mmap() clears VM_SHARED and VM_MAYWRITE, so

Clearing VM_MAYWRITE for a private mapping is odd. Can you point me at the code
that clears both things?

I assume we still have the file pointer, and as the file is read-only we remove
VM_MAYWRITE. But why are we removing MAP_SHARED? (where?)

Looking at the code, it's the

if (!(file->f_mode & FMODE_WRITE))
vma_flags_clear(&vma_flags, VMA_MAYWRITE_BIT, VMA_SHARED_BIT);

So we end up with VMA_MAYSHARE_BIT but without VMA_MAYWRITE_BIT and without
VMA_SHARED_BIT.

So it's by definition not a COW mapping. But it's marked anonymous and confuses
the system :)

This is definitely a bug. And I added these asserts specifically to find
bugs like this with anon mappings:

VM_WARN_ON_ONCE(!vma_is_cow_mapping(vma)); <-- fires
if (vma_is_anonymous(vma))
VM_WARN_ON_ONCE(pgoff != linear_page_index(vma, address)); <-- would have fired

It's because mmap_zero_prepare() keys off VMA_SHARED_BIT when it should be
keying off the terribly-named VMA_MAYSHARE_BIT.

(VMA_MAYSHARE_BIT actually tells you if the mapping was mapped shared _in
the first place_ specifically because of this clearing of VMA_SHARED_BIT,
VMA_MAYWRITE_BIT.)

Cool! Using VMA_MAYSHARE_BIT instead of VMA_SHARED_BIT in mmap_zero_prepare()
should do the trick.


So it turns out forever a readonly /dev/zero shared mapping has quietly been
converted to yet another variant of a 'special' anonymous mapping that we
weren't even aware of.

And it's got an incorrect pgoff (but not anon pgoff now) as a result,
similar to the usual MAP_PRIVATE-/dev/zero case.

So the solution is simple, check for VMA_MAYSHARE_BIT in
mmap_zero_prepare(). The Fixes: will be in the sands of time.

I'll send a fix out.

Thanks, Lorenzo!


--
Cheers,

David

--
Cheers, Lorenzo