In the Linux kernel, the following vulnerability has been resolved:
ext4: avoid journaling sb update on error if journal is destroying
Presently we always BUGON if trying to start a transaction on a journal marked with JBD2UNMOUNT, since this should never happen. However, while ltp running stress tests, it was observed that in case of some error handling paths, it is possible for updatesuperwork to start a transaction after the journal is destroyed eg:
(umount) ext4killsb killblocksuper genericshutdownsuper syncfilesystem /* commits all txns */ evictinodes /* might start a new txn / ext4_put_super flush_work(&sbi->s_sb_upd_work) / flush the workqueue */ jbd2journaldestroy journalkillthread journal->jflags |= JBD2UNMOUNT; jbd2journalcommittransaction jbd2journalgetdescriptorbuffer jbd2journalbmap ext4journalbmap ext4mapblocks ... ext4inodeerror ext4handleerror schedulework(&sbi->ssbupd_work)
/* work queue kicks in */
update_super_work
jbd2_journal_start
start_this_handle
BUG_ON(journal->j_flags &
JBD2_UNMOUNT)
Hence, introduce a new mount flag to indicate journal is destroying and only do a journaled (and deferred) update of sb if this flag is not set. Otherwise, just fallback to an un-journaled commit.
Further, in the journal destroy path, we have the following sequence:
This sequence is important as it ensures that, after this point, there is no sb update that might be journaled so it is safe to update the sb outside the journal. (To avoid race discussed in 2d01ddc86606)
Also, we don't need a similar check in ext4grplocked_error since it is only called from mballoc and AFAICT it would be always valid to schedule work here.