In the Linux kernel, the following vulnerability has been resolved:
btrfs: fix deadlock in waitcurrenttrans() due to ignored transaction type
When waitcurrenttrans() is called during starttransaction(), it currently waits for a blocked transaction without considering whether the given transaction type actually needs to wait for that particular transaction state. The btrfsblockedtranstypes[] array already defines which transaction types should wait for which transaction states, but this check was missing in waitcurrenttrans().
This can lead to a deadlock scenario involving two transactions and pending ordered extents:
Transaction A is in TRANSSTATECOMMIT_DOING state
A worker processing an ordered extent calls starttransaction() with TRANSJOIN
jointransaction() returns -EBUSY because Transaction A is in TRANSSTATECOMMITDOING
Transaction A moves to TRANSSTATEUNBLOCKED and completes
A new Transaction B is created (TRANSSTATERUNNING)
The ordered extent from step 2 is added to Transaction B's pending ordered extents
Transaction B immediately starts commit by another task and enters TRANSSTATECOMMIT_START
The worker finally reaches waitcurrenttrans(), sees Transaction B in TRANSSTATECOMMIT_START (a blocked state), and waits unconditionally
However, TRANSJOIN should NOT wait for TRANSSTATECOMMITSTART according to btrfsblockedtrans_types[]
Transaction B is waiting for pending ordered extents to complete
Deadlock: Transaction B waits for ordered extent, ordered extent waits for Transaction B
This can be illustrated by the following call stacks: CPU0 CPU1 btrfsfinishorderedio() starttransaction(TRANSJOIN) jointransaction() # -EBUSY (Transaction A is # TRANSSTATECOMMITDOING) # Transaction A completes # Transaction B created # ordered extent added to # Transaction B's pending list btrfscommittransaction() # Transaction B enters # TRANSSTATECOMMITSTART # waiting for pending ordered # extents waitcurrenttrans() # waits for Transaction B # (should not wait!)
Task bstorekvsync in btrfscommittransaction waiting for ordered extents:
_schedule+0x2e7/0x8a0 schedule+0x64/0xe0 btrfscommittransaction+0xbf7/0xda0 [btrfs] btrfssyncfile+0x342/0x4d0 [btrfs] _x64sysfdatasync+0x4b/0x80 dosyscall64+0x33/0x40 entrySYSCALL64afterhwframe+0x44/0xa9
Task kworker in waitcurrenttrans waiting for transaction commit:
Workqueue: btrfs-synonocow btrfsworkhelper [btrfs] _schedule+0x2e7/0x8a0 schedule+0x64/0xe0 waitcurrenttrans+0xb0/0x110 [btrfs] starttransaction+0x346/0x5b0 [btrfs] btrfsfinishorderedio.isra.0+0x49b/0x9c0 [btrfs] btrfsworkhelper+0xe8/0x350 [btrfs] processonework+0x1d3/0x3c0 workerthread+0x4d/0x3e0 kthread+0x12d/0x150 retfrom_fork+0x1f/0x30
Fix this by passing the transaction type to waitcurrenttrans() and checking btrfsblockedtranstypes[curtrans->state] against the given type before deciding to wait. This ensures that transaction types which are allowed to join during certain blocked states will not unnecessarily wait and cause deadlocks.
{
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/71xxx/CVE-2025-71194.json",
"cna_assigner": "Linux"
}