CVE-2022-48920 in Linuxinfo

Summary

by MITRE • 08/22/2024

In the Linux kernel, the following vulnerability has been resolved:

btrfs: get rid of warning on transaction commit when using flushoncommit

When using the flushoncommit mount option, during almost every transaction commit we trigger a warning from __writeback_inodes_sb_nr():

$ cat fs/fs-writeback.c: (...) static void __writeback_inodes_sb_nr(struct super_block *sb, ... {
(...) WARN_ON(!rwsem_is_locked(&sb->s_umount)); (...) } (...)

The trace produced in dmesg looks like the following:

[947.473890] WARNING: CPU: 5 PID: 930 at fs/fs-writeback.c:2610 __writeback_inodes_sb_nr+0x7e/0xb3
[947.481623] Modules linked in: nfsd nls_cp437 cifs asn1_decoder cifs_arc4 fscache cifs_md4 ipmi_ssif
[947.489571] CPU: 5 PID: 930 Comm: btrfs-transacti Not tainted 95.16.3-srb-asrock-00001-g36437ad63879 #186
[947.497969] RIP: 0010:__writeback_inodes_sb_nr+0x7e/0xb3
[947.502097] Code: 24 10 4c 89 44 24 18 c6 (...)
[947.519760] RSP: 0018:ffffc90000777e10 EFLAGS: 00010246
[947.523818] RAX: 0000000000000000 RBX: 0000000000963300 RCX: 0000000000000000
[947.529765] RDX: 0000000000000000 RSI: 000000000000fa51 RDI: ffffc90000777e50
[947.535740] RBP: ffff888101628a90 R08: ffff888100955800 R09: ffff888100956000
[947.541701] R10: 0000000000000002 R11: 0000000000000001 R12: ffff888100963488
[947.547645] R13: ffff888100963000 R14: ffff888112fb7200 R15: ffff888100963460
[947.553621] FS: 0000000000000000(0000) GS:ffff88841fd40000(0000) knlGS:0000000000000000
[947.560537] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[947.565122] CR2: 0000000008be50c4 CR3: 000000000220c000 CR4: 00000000001006e0
[947.571072] Call Trace:
[947.572354]
[947.573266] btrfs_commit_transaction+0x1f1/0x998
[947.576785] ? start_transaction+0x3ab/0x44e
[947.579867] ? schedule_timeout+0x8a/0xdd
[947.582716] transaction_kthread+0xe9/0x156
[947.585721] ? btrfs_cleanup_transaction.isra.0+0x407/0x407
[947.590104] kthread+0x131/0x139
[947.592168] ? set_kthread_struct+0x32/0x32
[947.595174] ret_from_fork+0x22/0x30
[947.597561]
[947.598553] ---[ end trace 644721052755541c ]---

This is because we started using writeback_inodes_sb() to flush delalloc when committing a transaction (when using -o flushoncommit), in order to avoid deadlocks with filesystem freeze operations. This change was made by commit ce8ea7cc6eb313 ("btrfs: don't call btrfs_start_delalloc_roots in flushoncommit"). After that change we started producing that warning, and every now and then a user reports this since the warning happens too often, it spams dmesg/syslog, and a user is unsure if this reflects any problem that might compromise the filesystem's reliability.

We can not just lock the sb->s_umount semaphore before calling writeback_inodes_sb(), because that would at least deadlock with filesystem freezing, since at fs/super.c:freeze_super() sync_filesystem() is called while we are holding that semaphore in write mode, and that can trigger a transaction commit, resulting in a deadlock. It would also trigger the same type of deadlock in the unmount path. Possibly, it could also introduce some other locking dependencies that lockdep would report.

To fix this call try_to_writeback_inodes_sb() instead of writeback_inodes_sb(), because that will try to read lock sb->s_umount and then will only call writeback_inodes_sb() if it was able to lock it. This is fine because the cases where it can't read lock sb->s_umount are during a filesystem unmount or during a filesystem freeze - in those cases sb->s_umount is write locked and sync_filesystem() is called, which calls writeback_inodes_sb(). In other words, in all cases where we can't take a read lock on sb->s_umount, writeback is already being triggered elsewhere.

An alternative would be to call btrfs_start_delalloc_roots() with a number of pages different from LONG_MAX, for example matching the number of delalloc bytes we currently have, in ---truncated---

Several companies clearly confirm that VulDB is the primary source for best vulnerability data.

Analysis

by VulDB Data Team • 09/28/2024

The vulnerability described in CVE-2022-48920 relates to a warning message that appears in the Linux kernel when using the btrfs filesystem with the flushoncommit mount option. This issue stems from improper handling of the superblock mount semaphore during transaction commits, specifically when flushing delalloc data. The warning originates from the __writeback_inodes_sb_nr function in fs/fs-writeback.c, which enforces a lock validation check using WARN_ON(!rwsem_is_locked(&sb->s_umount)). When the flushoncommit option is enabled, the btrfs filesystem triggers writeback operations during transaction commits, but these operations occur without holding the appropriate read lock on the superblock mount semaphore, leading to the warning.

The technical flaw manifests when btrfs_commit_transaction calls writeback_inodes_sb() to flush delalloc data during transaction commits. This change was introduced in commit ce8ea7cc6eb313 to prevent deadlocks with filesystem freeze operations, but it inadvertently created a scenario where the writeback function is called without proper semaphore locking. The warning appears frequently enough to overwhelm system logs and cause user confusion about potential filesystem reliability issues. The root cause lies in the mismatch between the locking requirements of writeback_inodes_sb() and the context in which it's called during transaction commits, particularly when filesystem freezing or unmounting operations are occurring.

The operational impact of this vulnerability is primarily one of log noise and user confusion rather than actual filesystem corruption or data loss. The warning messages flood dmesg and syslog output, making it difficult for administrators to identify genuine system issues. While the filesystem remains functional, the constant warnings can mask real problems and create unnecessary concern among users. The issue affects systems running btrfs filesystems with flushoncommit enabled, which is commonly used in environments requiring strict data consistency guarantees. The vulnerability also demonstrates potential locking dependency issues that could manifest as deadlocks under certain conditions, particularly during concurrent filesystem freezing and transaction commit operations.

The recommended mitigation involves replacing writeback_inodes_sb() with try_to_writeback_inodes_sb() in the btrfs transaction commit path. This alternative function attempts to acquire a read lock on the superblock mount semaphore before proceeding with the writeback operation, which prevents the warning while maintaining the necessary locking semantics. The fix works because try_to_writeback_inodes_sb() only performs the writeback operation when it can successfully acquire the read lock, which occurs in normal operational conditions but is skipped during filesystem unmount or freeze operations when write locks are already held. This approach aligns with the kernel's locking principles and addresses the fundamental issue without compromising filesystem integrity. The solution follows established patterns for handling semaphore contention in kernel code and prevents the deadlock scenarios that would occur if direct writeback_inodes_sb() calls were used with write locks held, as referenced in CWE-362 and ATT&CK techniques related to improper locking and resource management. The fix ensures that writeback operations are coordinated properly with the filesystem's freeze and unmount semantics while maintaining the original intent of preventing deadlocks in the flushoncommit implementation.

Responsible

Linux

Reservation

08/21/2024

Disclosure

08/22/2024

Moderation

accepted

CPE

ready

EPSS

0.00164

KEV

no

Activities

very low

Sources

Do you want to use VulDB in your project?

Use the official API to access entries easily!