CVE: CVE-2022-48920
Published: 2024-08-22
Description: 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: [PII_REDACTED] RBX: [PII_REDACTED] RCX: [PII_REDACTED]
  [947.529765] RDX: [PII_REDACTED] RSI:[PII_REDACTED]00fa51 RDI: ffffc90000777e50
  [947.535740] RBP: ffff888101628a90 R08: ffff[PII_REDACTED]00 R09: ffff[PII_REDACTED]00
  [947.541701] R10: [PII_REDACTED] R11: [PII_REDACTED] R12: ffff[PII_REDACTED]88
  [947.547645] R13: ffff[PII_REDACTED]00 R14: ffff888112fb7200 R15: ffff[PII_REDACTED]60
  [947.553621] FS:  [PII_REDACTED](0000) GS:ffff88841fd40000(0000) knlGS:[PII_REDACTED]
  [947.560537] CS:  0010 DS: 0000 ES: 0000 CR0: [PII_REDACTED]
  [947.565122] CR2:[PII_REDACTED]be50c4 CR3:[PII_REDACTED]20c000 CR4:[PII_REDACTED]1006e0
  [947.571072] Call Trace:
  [947.572354]  <TASK>
  [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]  </TASK>
  [947.598553] ---[ end trace[PII_REDACTED]55541c ]---

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---
CVSS Score: 5.5 (MEDIUM)
CWE: CWE-667
References: https://git.kernel.org/stable/c/850a77c999b81dd2724efd2684068d6f90db8c16; https://git.kernel.org/stable/c/a0f0cf8341e34e5d2265bfd3a7ad68342da1e2aa; https://git.kernel.org/stable/c/e4d044dbffcd570351f21c747fc77ff90aed7f2e