linux-stable/fs/nilfs2
Ryusuke Konishi 7532ff6edb nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput
commit f8654743a0 upstream.

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
9b5a04ac3a ("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 struct

This can happen after commit 0ae45f63d4 ("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 28a65b49eb ("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 9b5a04ac3a ("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.

Link: https://lkml.kernel.org/r/20230728191318.33047-1-konishi.ryusuke@gmail.com
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Reported-by: syzbot+74db8b3087f293d3a13a@syzkaller.appspotmail.com
Closes: https://lkml.kernel.org/r/000000000000b4e906060113fd63@google.com
Fixes: 0ae45f63d4 ("vfs: add support for a lazytime mount option")
Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: <stable@vger.kernel.org> # 4.0+
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-08-16 18:27:22 +02:00
..
alloc.c
alloc.h
bmap.c nilfs2: fix infinite loop in nilfs_mdt_get_block() 2023-05-11 23:03:39 +09:00
bmap.h
btnode.c nilfs2: fix incomplete buffer cleanup in nilfs_btnode_abort_change_key() 2023-06-21 16:00:54 +02:00
btnode.h fs/nilfs2: Use the enum req_op and blk_opf_t types 2022-07-14 12:14:33 -06:00
btree.c nilfs2: fix general protection fault in nilfs_btree_insert() 2023-01-24 07:24:33 +01:00
btree.h
cpfile.c
cpfile.h
dat.c nilfs2: fix NULL pointer dereference in nilfs_palloc_commit_free_entry() 2022-11-30 14:49:40 -08:00
dat.h
dir.c nilfs2: Remove check for PageError 2022-06-29 08:51:07 -04:00
direct.c
direct.h
export.h
file.c
gcinode.c fs/nilfs2: Use the enum req_op and blk_opf_t types 2022-07-14 12:14:33 -06:00
ifile.c
ifile.h
inode.c nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput 2023-08-16 18:27:22 +02:00
ioctl.c nilfs2: fix kernel-infoleak in nilfs_ioctl_wrap_copy() 2023-03-30 12:49:27 +02:00
Kconfig
Makefile
mdt.c fs/nilfs2: Use the enum req_op and blk_opf_t types 2022-07-14 12:14:33 -06:00
mdt.h
namei.c
nilfs.h nilfs2: fix incorrect masking of permission flags for symlinks 2022-07-03 15:42:33 -07:00
page.c nilfs2: prevent general protection fault in nilfs_clear_dirty_page() 2023-06-28 11:12:27 +02:00
page.h
recovery.c
segbuf.c nilfs2: fix buffer corruption due to concurrent device reads 2023-06-28 11:12:22 +02:00
segbuf.h
segment.c nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput 2023-08-16 18:27:22 +02:00
segment.h
sufile.c nilfs2: fix possible out-of-bounds segment allocation in resize ioctl 2023-06-21 16:00:54 +02:00
sufile.h
super.c nilfs2: fix buffer corruption due to concurrent device reads 2023-06-28 11:12:22 +02:00
sysfs.c
sysfs.h
the_nilfs.c nilfs2: reject devices with insufficient block count 2023-06-21 16:00:54 +02:00
the_nilfs.h nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput 2023-08-16 18:27:22 +02:00