FAILED: patch "[PATCH] nilfs2: fix use-after-free bug of ns_writer on remount" failed to apply to 4.14-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
Possible dependencies:
8cccf05fe857 ("nilfs2: fix use-after-free bug of ns_writer on remount")1751e8a6cb93 ("Rename superblock flags (MS_xyz -> SB_xyz)")b04a23421bf6 ("Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 8cccf05fe857a18ee26e20d11a8455a73ffd4efd Mon Sep 17 00:00:00 2001
From: Ryusuke Konishi <[email protected]>
Date: Fri, 4 Nov 2022 23:29:59 +0900
Subject: [PATCH] nilfs2: fix use-after-free bug of ns_writer on remount
If a nilfs2 filesystem is downgraded to read-only due to metadata corruption on disk and is remounted read/write, or if emergency read-only remount is performed, detaching a log writer and synchronizing the filesystem can be done at the same time.
In these cases, use-after-free of the log writer (hereinafter nilfs->ns_writer) can happen as shown in the scenario below:
Task1 Task2
-------------------------------- ------------------------------
nilfs_construct_segment
nilfs_segctor_sync
init_wait
init_waitqueue_entry
add_wait_queue
schedule
nilfs_remount (R/W remount case)
nilfs_attach_log_writer
nilfs_detach_log_writer
nilfs_segctor_destroy
kfree
finish_wait
_raw_spin_lock_irqsave
__raw_spin_lock_irqsave
do_raw_spin_lock
debug_spin_lock_before <-- use-after-free
While Task1 is sleeping, nilfs->ns_writer is freed by Task2. After Task1 waked up, Task1 accesses nilfs->ns_writer which is already freed. This scenario diagram is based on the Shigeru Yoshida's post [1].
This patch fixes the issue by not detaching nilfs->ns_writer on remount so that this UAF race doesn't happen. Along with this change, this patch also inserts a few necessary read-only checks with superblock instance where only the ns_writer pointer was used to check if the filesystem is read-only.
fs/nilfs2/segment.c +8 -7
@@ -317,7 +317,7 @@ void nilfs_relax_pressure_in_lock(struct super_block *sb)struct the_nilfs *nilfs = sb->s_fs_info;struct nilfs_sc_info *sci = nilfs->ns_writer; -if (!sci || !sci->sc_flush_request) +if (sb_rdonly (sb) ||unlikely (!sci) || !sci->sc_flush_request)return ;set_bit (NILFS_SC_PRIOR_FLUSH , &sci->sc_flags);
@@ -2242,7 +2242,7 @@ int nilfs_construct_segment(struct super_block *sb)struct nilfs_sc_info *sci = nilfs->ns_writer;struct nilfs_transaction_info *ti; -if (!sci) +if (sb_rdonly (sb) ||unlikely (!sci))return -EROFS ;/* A call inside transactions causes a deadlock. */
@@ -2280,7 +2280,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,struct nilfs_transaction_info ti;int err =0 ; -if (!sci) +if (sb_rdonly (sb) ||unlikely (!sci))return -EROFS ;nilfs_transaction_lock (sb, &ti,0 );
@@ -2776,11 +2776,12 @@ int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root)if (nilfs->ns_writer) {/* -* This happens if the filesystem was remounted -* read/write after nilfs_error degenerated it into a -* read-only mount. +* This happens if the filesystem is made read-only by +* __nilfs_error or nilfs_remount and then remounted +* read/write. In these cases, reuse the existing +* writer. */ -nilfs_detach_log_writer (sb); +return 0 ; } nilfs->ns_writer =nilfs_segctor_new (sb, root);
fs/nilfs2/super.c +0 -2
@@ -1133,8 +1133,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)if ((bool )(*flags &SB_RDONLY ) ==sb_rdonly (sb)) goto out;if (*flags &SB_RDONLY ) { -/* Shutting down log writer */ -nilfs_detach_log_writer (sb); sb->s_flags |=SB_RDONLY ;/*