In the Linux kernel, the following vulnerability has been resolved: btrfs: fix a NULL pointer dereference when failed to start a new trasacntion [BUG] Syzbot reported a NULL pointer dereference with the following crash: FAULTINJECTION: forcing a failure. starttransaction+0x830/0x1670 fs/btrfs/transaction.c:676 preparetorelocate+0x31f/0x4c0 fs/btrfs/relocation.c:3642 relocateblockgroup+0x169/0xd20 fs/btrfs/relocation.c:3678 ... BTRFS info (device loop0): balance: ended with status: -12 Oops: general protection fault, probably for non-canonical address 0xdffffc00000000cc: 0000 [#1] PREEMPT SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000660-0x0000000000000667] RIP: 0010:btrfsupdaterelocroot+0x362/0xa80 fs/btrfs/relocation.c:926 Call Trace: <TASK> commitfsroots+0x2ee/0x720 fs/btrfs/transaction.c:1496 btrfscommittransaction+0xfaf/0x3740 fs/btrfs/transaction.c:2430 delbalanceitem fs/btrfs/volumes.c:3678 [inline] resetbalancestate+0x25e/0x3c0 fs/btrfs/volumes.c:3742 btrfsbalance+0xead/0x10c0 fs/btrfs/volumes.c:4574 btrfsioctlbalance+0x493/0x7c0 fs/btrfs/ioctl.c:3673 vfsioctl fs/ioctl.c:51 [inline] _dosysioctl fs/ioctl.c:907 [inline] _sesysioctl+0xf9/0x170 fs/ioctl.c:893 dosyscallx64 arch/x86/entry/common.c:52 [inline] dosyscall64+0xf3/0x230 arch/x86/entry/common.c:83 entrySYSCALL64afterhwframe+0x77/0x7f [CAUSE] The allocation failure happens at the starttransaction() inside preparetorelocate(), and during the error handling we call unsetreloccontrol(), which makes fsinfo->balancectl to be NULL. Then we continue the error path cleanup in btrfsbalance() by calling resetbalancestate() which will call delbalanceitem() to fully delete the balance item in the root tree. However during the small window between setreloccontrl() and unsetreloccontrol(), we can have a subvolume tree update and created a relocroot for that subvolume. Then we go into the final btrfscommittransaction() of delbalanceitem(), and into btrfsupdaterelocroot() inside commitfsroots(). That function checks if fsinfo->relocctl is in the mergereloctree stage, but since fsinfo->relocctl is NULL, it results a NULL pointer dereference. [FIX] Just add extra check on fsinfo->relocctl inside btrfsupdaterelocroot(), before checking fsinfo->relocctl->mergereloctree. That DEADRELOCTREE handling is to prevent further modification to the reloc tree during merge stage, but since there is no reloc_ctl at all, we do not need to bother that.