nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput.patch removed from -mm tree
The quilt patch titled
Subject: nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput
has been removed from the -mm tree. Its filename was
nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput.patch
This patch was dropped because it was merged into the mm-hotfixes-stable branch of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
------------------------------------------------------
From: Ryusuke Konishi <[email protected]>
Subject: nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput
Date: Sat, 29 Jul 2023 04:13:18 +0900
During unmount process of nilfs2, nothing holds nilfs_root structure after nilfs2 detaches its writer in nilfs_detach_log_writer(). Previously, nilfs_evict_inode() could cause use-after-free read for nilfs_root if inodes are left in "garbage_list" and released by nilfs_dispose_list at the end of nilfs_detach_log_writer(), and this bug was fixed by commit 9b5a04ac3ad9 ("nilfs2: fix use-after-free bug of nilfs_root in nilfs_evict_inode()").
However, it turned out that there is another possibility of UAF in the call path where mark_inode_dirty_sync() is called from iput():
nilfs_detach_log_writer()
nilfs_dispose_list()
iput()
mark_inode_dirty_sync()
__mark_inode_dirty()
nilfs_dirty_inode()
__nilfs_mark_inode_dirty()
nilfs_load_inode_block() --> causes UAF of nilfs_root structThis can happen after commit 0ae45f63d4ef ("vfs: add support for a lazytime mount option"), which changed iput() to call mark_inode_dirty_sync() on its final reference if i_state has I_DIRTY_TIME flag and i_nlink is non-zero.
This issue appears after commit 28a65b49eb53 ("nilfs2: do not write dirty data after degenerating to read-only") when using the syzbot reproducer, but the issue has potentially existed before.
Fix this issue by adding a "purging flag" to the nilfs structure, setting that flag while disposing the "garbage_list" and checking it in __nilfs_mark_inode_dirty().
Unlike commit 9b5a04ac3ad9 ("nilfs2: fix use-after-free bug of nilfs_root in nilfs_evict_inode()"), this patch does not rely on ns_writer to determine whether to skip operations, so as not to break recovery on mount. The nilfs_salvage_orphan_logs routine dirties the buffer of salvaged data before attaching the log writer, so changing __nilfs_mark_inode_dirty() to skip the operation when ns_writer is NULL will cause recovery write to fail. The purpose of using the cleanup-only flag is to allow for narrowing of such conditions.
---
fs/nilfs2/inode.c | 8 ++++++++ fs/nilfs2/segment.c | 2 ++ fs/nilfs2/the_nilfs.h | 2 ++ 3 files changed, 12 insertions(+)
fs/nilfs2/inode.c renamed from fs/nilfs2/inode.c~nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput +8 -0
@@ -1101,9 +1101,17 @@ int nilfs_set_file_dirty(struct inode *iint __nilfs_mark_inode_dirty (struct inode *inode,int flags) { +struct the_nilfs *nilfs = inode->i_sb->s_fs_info;struct buffer_head *ibh;int err; +/* +* Do not dirty inodes after the log writer has been detached +* and its nilfs_root struct has been freed. +*/ +if (unlikely (nilfs_purging (nilfs))) +return 0 ; + err =nilfs_load_inode_block (inode, &ibh);if (unlikely (err)) { nilfs_warn(inode->i_sb,
fs/nilfs2/segment.c renamed from fs/nilfs2/segment.c~nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput +2 -0
@@ -2845,6 +2845,7 @@ void nilfs_detach_log_writer(struct supenilfs_segctor_destroy (nilfs->ns_writer); nilfs->ns_writer =NULL ; } +set_nilfs_purging (nilfs);/* Force to free the list of dirty files */ spin_lock (&nilfs->ns_inode_lock);
@@ -2857,4 +2858,5 @@ void nilfs_detach_log_writer(struct supeup_write (&nilfs->ns_segctor_sem);nilfs_dispose_list (nilfs, &garbage_list,1 ); +clear_nilfs_purging (nilfs); }
fs/nilfs2/the_nilfs.h renamed from fs/nilfs2/the_nilfs.h~nilfs2-fix-use-after-free-of-nilfs_root-in-dirtying-inodes-via-iput +2 -0
@@ -29,6 +29,7 @@ enum {THE_NILFS_DISCONTINUED ,/* 'next' pointer chain has broken */ THE_NILFS_GC_RUNNING ,/* gc process is running */ THE_NILFS_SB_DIRTY ,/* super block is dirty */ + THE_NILFS_PURGING, /* disposing dirty files for cleanup */ };/**
@@ -208,6 +209,7 @@ THE_NILFS_FNS(INIT, init) THE_NILFS_FNS(DISCONTINUED, discontinued) THE_NILFS_FNS(GC_RUNNING, gc_running) THE_NILFS_FNS(SB_DIRTY, sb_dirty) +THE_NILFS_FNS (PURGING , purging)/* * Mount option operations
_
Patches currently in -mm which might be from [email protected] are