kernel BUG in may_open (4)

Status: moderation: reported on 2026/11/04 20:59
Subsystems: fs
Labels: prio:normal
[Documentation on labels]
Reported-by: syzbot+e2b376decc66855d15eb@syzkaller.appspotmail.com
First crash: 4d02h, last: 4d02h
✨ AI-generated root cause summary:

In fs/namei.c:may_open(), a kernel BUG is triggered at VFS_BUG_ON_INODE(!IS_ANON_FILE(inode), inode) when evaluating inode->i_mode & S_IFMT because the inode (ffff0000c7782b80) has i_mode == 0 and lacks the S_ANON_INODE flag. As recorded by dump_inode(), all probed fields of the inode are zero (i_sb is NULL, i_mode == 0, i_opflags == 0, i_flags == 0, i_state == 0, and i_count == 0). Because every valid VFS inode initialized via inode_init_always_gfp() must have a non-NULL i_sb and i_count == 1, and d_instantiate() validates i_op before attaching an inode to a dentry, the inode could not have been attached in an uninitialized state. Rather, this manifests a use-after-free where a dentry retained a dangling d_inode pointer to an inode that was prematurely freed and subsequently zeroed upon slab reallocation under CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y.

▶ ▼ ✨ Full AI root cause analysis
Based on kernel commit 7a19f0cc94ad:

Technical Root Cause Analysis

1. Failure Manifestation and Crash Site

The crash occurs at fs/namei.c:4295 in may_open():

static int may_open(struct mnt_idmap *idmap, const struct path *path,
		    int acc_mode, int flag)
{
	struct dentry *dentry = path->dentry;
	struct inode *inode = dentry->d_inode;
	int error;

	if (!inode)
		return -ENOENT;

	switch (inode->i_mode & S_IFMT) {
	case S_IFLNK:
		return -ELOOP;
	case S_IFDIR:
...
	case S_IFBLK:
	case S_IFCHR:
...
	case S_IFIFO:
	case S_IFSOCK:
...
	case S_IFREG:
		if ((acc_mode & MAY_EXEC) && path_noexec(path))
			return -EACCES;
		break;
	default:
		VFS_BUG_ON_INODE(!IS_ANON_FILE(inode), inode);
	}

During an openat syscall (do_sys_openat2 -> path_openat -> do_open -> may_open) executed by udevd with flag = 0x20141 (O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE) and acc_mode = MAY_WRITE (0x2), may_open() evaluates inode->i_mode & S_IFMT.

Because inode->i_mode is 0, the switch falls into the default: branch. It then checks !IS_ANON_FILE(inode), which evaluates !((inode)->i_flags & S_ANON_INODE). Because inode->i_flags is 0, this assertion fails and triggers VFS_BUG_ON_INODE:

VFS_BUG_ON_INODE(!IS_ANON_FILE(inode)): inode:ffff0000c7782b80 fs:<unknown, sb unreadable> mode:0 opflags:0x0 flags:0x0 state:0x0 count:0
kernel BUG at fs/namei.c:4295!

2. Examination of Inode Invariants and Memory State

As printed by dump_inode() (fs/inode.c:3082), all memory fields of struct inode at address ffff0000c7782b80 probed via get_kernel_nofault() returned zero:

  • inode->i_sb = NULL (fs:<unknown, sb unreadable>)
  • inode->i_mode = 0
  • inode->i_opflags = 0x0
  • inode->i_flags = 0x0
  • inode->i_state = 0x0
  • inode->i_count = 0

An inode cannot be created or instantiated in this state through standard VFS lifecycle paths:

  1. Inode Allocation Invariant (fs/inode.c:inode_init_always_gfp()): Every allocated inode initialized through inode_init_always_gfp() assigns inode->i_sb = sb (which is never NULL) and atomic_set(&inode->i_count, 1). Inodes that fail allocation are destroyed before ever becoming visible.
  2. Dentry Instantiation Invariant (fs/dcache.c:d_flags_for_inode()): Any assignment of dentry->d_inode = inode occurs in __d_set_inode_and_type(), which is called by __d_instantiate(), __d_obtain_alias(), and __d_add(). These functions compute dentry flags using d_flags_for_inode(inode). In d_flags_for_inode():
    if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) {
        if (unlikely(inode->i_op->get_link)) {
            add_flags = DCACHE_SYMLINK_TYPE;
            goto type_determined;
        }
        inode->i_opflags |= IOP_NOFOLLOW;
    }
    
    If an inode were attached with all-zero fields (i_opflags == 0 and i_op == NULL), d_flags_for_inode() would have dereferenced inode->i_op->get_link and crashed immediately with a NULL-pointer dereference at instantiation time, and would have modified inode->i_opflags.

Therefore, the inode was valid when originally attached to the dentry, but the pointer dentry->d_inode subsequently became stale.


3. Path Resolution and Propagation to may_open()

In open_last_lookups() -> lookup_open() (fs/namei.c):

  1. Lookup in the dcache (lookup_fast_for_open() or d_lookup()) encountered a cached positive dentry whose dentry->d_inode pointed to ffff0000c7782b80.
  2. Because dentry->d_inode was non-NULL, lookup_open() treated the dentry as an existing cached file and skipped creation, leaving file->f_mode without FMODE_CREATED.
  3. In do_open():
    • Dentry type checks such as d_is_dir(nd->path.dentry) and d_is_reg(nd->path.dentry) inspect cached DCACHE_ENTRY_TYPE bits in dentry->d_flags rather than dereferencing dentry->d_inode.
    • may_create_in_sticky() returns early if the parent directory does not have S_ISVTX.
    • Consequently, may_open() was the first function in do_open() to dereference dentry->d_inode->i_mode.

4. Root Cause Mechanism

The root cause is a use-after-free (dangling pointer in dentry->d_inode):

  • An inode reference counting or unlinking discrepancy prematurely freed the struct inode object while an active or cached struct dentry still held a pointer to it in dentry->d_inode.
  • Under the kernel build configuration (CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y), when the slab memory at ffff0000c7782b80 was returned to the allocator or reallocated for a new object, the memory block was zeroed.
  • When udevd attempted to open the path, the cached dentry provided the zeroed memory address as dentry->d_inode. In may_open(), reading inode->i_mode == 0 triggered the VFS_BUG_ON_INODE(!IS_ANON_FILE(inode), inode) assertion.
▶ ▼ ✨ AI Jobs (3)
ID Workflow Result Correct Bug Created Started Finished Revision
14db591b repro-c 💥 kernel BUG in may_open (4) 2026/11/04 06:09 2026/11/04 06:09 2026/11/04 14:41 5af5b6c6
36d36eb3 repro-c 💥 kernel BUG in may_open (4) 2026/11/03 00:05 2026/11/03 00:05 2026/11/03 09:28 0a94d799
501acf60 assessment-security DenialOfService: ✅ Exploitable: ✅ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ✅ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ❌ UserNamespace: ❌ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ kernel BUG in may_open (4) 2026/10/31 20:51 2026/10/31 20:51 2026/10/31 21:31 25a0ae84
▶ ▼ Similar bugs (3)
Kernel Title Rank 🛈 Repro Cause bisect Fix bisect Count Last Reported Patched Status
upstream kernel BUG in may_open fs -1 syz, C error 137019 484d 581d 29/29 fixed on 2025/07/08 00:33
upstream kernel BUG in may_open (2) fs -1 syz, C done 17716 301d 484d 29/29 fixed on 2026/01/07 12:29
upstream kernel BUG in may_open (3) hfs -1 syz, C error 11 279d 296d 29/29 fixed on 2026/05/06 16:40

Sample crash report:
VFS_BUG_ON_INODE(!IS_ANON_FILE(inode)): inode:ffff0000c7782b80 fs:<unknown, sb unreadable> mode:0 opflags:0x0 flags:0x0 state:0x0 count:0
------------[ cut here ]------------
kernel BUG at fs/namei.c:4295!
Internal error: Oops - BUG: 00000000f2000800 [#1]  SMP
Modules linked in:
CPU: 0 UID: 0 PID: 4367 Comm: udevd Not tainted syzkaller #0 PREEMPT 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/23/2026
pstate: 63400005 (nZCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
pc : may_open+0x3f8/0x3fc fs/namei.c:4295
lr : may_open+0x3f8/0x3fc fs/namei.c:4295
sp : ffff800094cc7900
x29: ffff800094cc7900 x28: dfff800000000000 x27: ffff0000ef98f380
x26: 0000000000000000 x25: dfff800000000000 x24: 00000000000fffff
x23: 0000000000000000 x22: 0000000000000002 x21: ffff0000c7782b80
x20: 0000000000020141 x19: ffff800089b495e0 x18: 0000000000000000
x17: 0000000000000000 x16: 0000000000000000 x15: 656c626164616572
x14: 000000000000119e x13: 00000000000001ac x12: 0000000000000003
x11: 0000000000000000 x10: 0000000000000001 x9 : cdd15a55eb110300
x8 : cdd15a55eb110300 x7 : ffff800080484084 x6 : 0000000000000000
x5 : 0000000000000000 x4 : 0000000000000000 x3 : ffff80008048eb84
x2 : 0000000100000000 x1 : ffff0000d2488000 x0 : 0000000000000089
Call trace:
 may_open+0x3f8/0x3fc fs/namei.c:4295 (P)
 do_open fs/namei.c:4864 [inline]
 path_openat+0xf90/0x18f0 fs/namei.c:5029
 do_file_open+0x1c8/0x2e8 fs/namei.c:5058
 do_sys_openat2+0x114/0x1e8 fs/open.c:1417
 do_sys_open+0xb0/0xe0 fs/open.c:1423
 __do_sys_openat fs/open.c:1439 [inline]
 __se_sys_openat fs/open.c:1434 [inline]
 __arm64_sys_openat+0xa8/0xc4 fs/open.c:1434
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+0x98/0x244 arch/arm64/kernel/syscall.c:49
 el0_svc_common+0xec/0x23c arch/arm64/kernel/syscall.c:121
 do_el0_svc+0x4c/0x5c arch/arm64/kernel/syscall.c:140
 el0_svc+0x60/0x1d8 arch/arm64/kernel/entry-common.c:796
 el0t_64_sync_handler+0x44/0x104 arch/arm64/kernel/entry-common.c:815
 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:606
Code: d002ed41 91180021 aa1503e0 9400eb81 (d4210000) 
---[ end trace 0000000000000000 ]---

Crashes (1):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/10/31 20:51 git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci 7a19f0cc94ad 2041d3f8 .config console log report info [disk image] [vmlinux] [kernel image] ci-upstream-gce-arm64 kernel BUG in may_open
* Struck through repros no longer work on HEAD.