kernel BUG in sysfs_break_active_protection

Status: upstream: reported C repro on 2026/11/01 00:24
Subsystems: driver-core fs
Labels: prio:normal
[Documentation on labels]
Reported-by: syzbot+dcad997ed2b5bd95cc5e@syzkaller.appspotmail.com
First crash: 4d05h, last: 11h52m
✨ AI-generated root cause summary:

In md_attr_store(), writing "clear" to array_state invokes sysfs_break_active_protection() prior to acquiring all_mddevs_lock and validating the device via mddev_get(). Since sysfs writes only hold kernfs active references rather than a kobject reference, a concurrent deletion or teardown of the mddev can drop the final reference on mddev->kobj, reducing kobj->kref to zero before kernfs removal drains pending active accesses. Calling sysfs_break_active_protection() then executes kobject_get() on the zero-refcount object, triggering a refcount use-after-free saturation/BUG and potentially corrupting memory or crashing the kernel.

▶ ▼ ✨ Full AI root cause analysis
Based on kernel commit 151a134a4e6e:

Root Cause Analysis

1. Functions, Structs, and Files Involved

  • drivers/md/md.c:
    • md_attr_store(): sysfs write callback for mddev attributes.
    • mddev_delayed_delete() / __mddev_put() / mddev_put(): cleanup path that invokes kobject_put(&mddev->kobj) when mddev->active drops to zero.
    • struct mddev: contains embedded struct kobject kobj and flags like MD_DELETED.
  • fs/sysfs/file.c:
    • sysfs_break_active_protection(): breaks active kernfs protection; unconditionally calls kobject_get(kobj).
  • lib/kobject.c:
    • kobject_get() -> kref_get() -> refcount_inc(): attempts to increment kobj->kref.refcount.
    • kobject_put() -> kref_put() -> kobject_release() / kobject_cleanup(): drops the last refcount and tears down sysfs files via __kobject_del().

2. Triggering Mechanism and Lifecycle Invariant Violation

In sysfs/kernfs, file operations (e.g. kernfs_fop_write_iter() -> sysfs_kf_write()) acquire an active reference on the kernfs_node (kernfs_get_active_of()), but they do not take a reference on the associated struct kobject (mddev->kobj). Instead, kernfs relies on kobject_del() / sysfs_remove_dir() invoking kernfs_drain() during teardown to wait for all in-flight file operations to finish before releasing resources.

In drivers/md/md.c:

  1. When an mddev is torn down or stopped, mddev_put() drops mddev->active to 0. __mddev_put() queues mddev->del_work (mddev_delayed_delete), which calls kobject_put(&mddev->kobj).
  2. kobject_put() invokes kref_put(&kobj->kref, kobject_release), which decrements kobj->kref.refcount from 1 to 0 before entering kobject_cleanup().
  3. In kobject_cleanup(), __kobject_del() is called to remove the sysfs directory and drain active kernfs references.
  4. However, if a user write of "clear" to /sys/block/mdX/md/array_state executes concurrently, it can successfully acquire the kernfs active reference (kernfs_get_active_of()) right before __kobject_del() drains the node.
  5. In md_attr_store() (drivers/md/md.c:6166-6176):
    if (entry->store == array_state_store && cmd_match(page, "clear"))
        kn = sysfs_break_active_protection(kobj, attr);
    
    spin_lock(&all_mddevs_lock);
    if (!mddev_get(mddev)) {
        ...
    
    sysfs_break_active_protection(kobj, attr) is invoked before taking all_mddevs_lock and checking mddev_get(mddev) (which checks MD_DELETED and returns NULL).
  6. sysfs_break_active_protection() calls kobject_get(kobj), which executes refcount_inc(&kobj->kref.refcount). Because the refcount is already 0, this violates the refcount invariant that an increment cannot occur on an object with refcount 0, triggering: refcount_t: addition on 0; use-after-free. -> kernel BUG at lib/refcount.c:34!

3. Runtime Consequences in Production Kernels

  • MemoryCorruption (true): An addition on a refcount of 0 signifies that kobject_cleanup() is running or about to run concurrently. In kobject_cleanup(), md_kobj_release() -> put_disk() -> md_free_disk() frees struct mddev via kfree(mddev). Concurrently incrementing the refcount on a dying object and continuing to access mddev or subsequently calling kobject_put() / sysfs_unbreak_active_protection() leads to use-after-free, double-free, and refcount corruption.
  • RawDenialOfService (true): On systems built with CONFIG_BUG_ON_DATA_CORRUPTION=y, the kernel hits an unrecoverable BUG() in refcount_warn_saturate(). On systems without it, use-after-free on struct mddev / kobj leads to kernel crash / panic or memory corruption when accessing the freed device.
  • InfoLeak ("none"): The defect does not read or expose uninitialized or out-of-bounds kernel memory contents to userspace.
  • IsNetCandidate (false): The defect is in the block MD RAID subsystem and sysfs file operations, unrelated to networking or network protocols.
  • IsKVMCandidate (false): The defect is unrelated to virtualization, KVM, hypervisors, or virtio.
▶ ▼ ✨ AI Jobs (2)
ID Workflow Result Correct Bug Created Started Finished Revision
c764fd6d repro-c Reproduced: ✅ ❓ kernel BUG in sysfs_break_active_protection 2026/10/31 13:14 2026/10/31 13:14 2026/10/31 15:08 2041d3f8
14b4e108 assessment-security DenialOfService: ✅ Exploitable: ✅ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ✅ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ❌ UserNamespace: ❌ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ kernel BUG in sysfs_break_active_protection 2026/10/29 05:09 2026/10/29 05:09 2026/10/29 05:20 b1d00f76
▶ ▼ Discussions (1)
Title Replies (including bot) Last reply
[syzbot] [driver-core?] [fs?] kernel BUG in sysfs_break_active_protection 0 (1) 2026/11/01 00:24
▶ ▼ Last patch testing requests (1)
Created Duration User Patch Repo Result
2026/10/31 18:04 22m retest repro git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git 7649ba73f9e7e1e04d0b46213e39c79ae09dd55c report job log log

Sample crash report:
refcount_t: addition on 0; use-after-free.
------------[ cut here ]------------
kernel BUG at lib/refcount.c:34!
Oops: invalid opcode: 0000 [#1] SMP KASAN PTI
CPU: 1 UID: 0 PID: 6056 Comm: syz-executor398 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/15/2026
RIP: 0010:refcount_warn_saturate+0xf0/0x110 lib/refcount.c:34
Code: 80 c1 03 38 c1 0f 8c 6a ff ff ff 4c 89 f7 e8 e7 44 51 fd e9 5d ff ff ff e8 dd 23 da fc 48 c7 c7 e0 a3 8c 8c e8 a1 d1 38 fc 90 <0f> 0b e8 c9 23 da fc 48 c7 c7 60 a4 8c 8c e8 8d d1 38 fc 90 0f 0b
RSP: 0018:ffffc90002e5fb78 EFLAGS: 00010246
RAX: 000000000000002a RBX: 0000000000000002 RCX: 4550039d880cf800
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000000
RBP: 0000000000000000 R08: ffffffff9014c84b R09: 1ffffffff2029909
R10: dffffc0000000000 R11: fffffbfff202990a R12: dffffc0000000000
R13: 1ffffffff22654c6 R14: ffff88807c40e128 R15: dffffc0000000000
FS:  00007f63dcdeb6c0(0000) GS:ffff88812350b000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055b9ba686138 CR3: 0000000074ef4000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 __refcount_add include/linux/refcount.h:-1 [inline]
 __refcount_inc include/linux/refcount.h:366 [inline]
 refcount_inc include/linux/refcount.h:383 [inline]
 kref_get include/linux/kref.h:45 [inline]
 kobject_get+0xfa/0x120 lib/kobject.c:643
 sysfs_break_active_protection+0x28/0xa0 fs/sysfs/file.c:471
 md_attr_store+0x28f/0x640 drivers/md/md.c:6167
 kernfs_fop_write_iter+0x3a4/0x540 fs/kernfs/file.c:345
 new_sync_write fs/read_write.c:595 [inline]
 vfs_write+0x612/0xba0 fs/read_write.c:687
 ksys_pwrite64 fs/read_write.c:1504 [inline]
 __do_sys_pwrite64 fs/read_write.c:1512 [inline]
 __se_sys_pwrite64 fs/read_write.c:1509 [inline]
 __x64_sys_pwrite64+0x210/0x2c0 fs/read_write.c:1509
 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
 do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f63de64ba9e
Code: 08 0f 85 f5 e2 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 90 41 57 41 56 4d 89 c6 41 55 4d 89 cd 41 54 55 53 48 83 ec 08
RSP: 002b:00007f63dcdeb0f8 EFLAGS: 00000246 ORIG_RAX: 0000000000000012
RAX: ffffffffffffffda RBX: 00007f63dcdeb6c0 RCX: 00007f63de64ba9e
RDX: 0000000000000005 RSI: 00007f63de69003a RDI: 0000000000000006
RBP: 0000000000000006 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f63de69003a
R13: 0000000000000003 R14: 00007f63de6c3100 R15: 00007f63de6c4b4c
 </TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:refcount_warn_saturate+0xf0/0x110 lib/refcount.c:34
Code: 80 c1 03 38 c1 0f 8c 6a ff ff ff 4c 89 f7 e8 e7 44 51 fd e9 5d ff ff ff e8 dd 23 da fc 48 c7 c7 e0 a3 8c 8c e8 a1 d1 38 fc 90 <0f> 0b e8 c9 23 da fc 48 c7 c7 60 a4 8c 8c e8 8d d1 38 fc 90 0f 0b
RSP: 0018:ffffc90002e5fb78 EFLAGS: 00010246
RAX: 000000000000002a RBX: 0000000000000002 RCX: 4550039d880cf800
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000000
RBP: 0000000000000000 R08: ffffffff9014c84b R09: 1ffffffff2029909
R10: dffffc0000000000 R11: fffffbfff202990a R12: dffffc0000000000
R13: 1ffffffff22654c6 R14: ffff88807c40e128 R15: dffffc0000000000
FS:  00007f63dcdeb6c0(0000) GS:ffff88812350b000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f94a870e7d0 CR3: 0000000074ef4000 CR4: 00000000003526f0

Crashes (2):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/10/31 18:26 git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git 7649ba73f9e7 96923c60 .config console log report C ci-upstream-linux-next-kasan-gce-root kernel BUG in sysfs_break_active_protection
2026/10/28 00:21 linux-next 151a134a4e6e 96923c60 .config console log report info [disk image] [vmlinux] [kernel image] ci-upstream-linux-next-kasan-gce-root kernel BUG in sysfs_break_active_protection
* Struck through repros no longer work on HEAD.