android_kernel_xiaomi_sm8450/fs/nilfs2
Ryusuke Konishi 3720724087 nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput
commit f8654743a0e6909dc634cbfad6db6816f10f3399 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
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 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 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.

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:21:00 +02:00
..
alloc.c nilfs2: use a more common logging style 2020-08-12 10:58:01 -07:00
alloc.h
bmap.c nilfs2: fix infinite loop in nilfs_mdt_get_block() 2023-05-17 11:47:36 +02:00
bmap.h
btnode.c nilfs2: fix incomplete buffer cleanup in nilfs_btnode_abort_change_key() 2023-06-21 15:45:37 +02:00
btnode.h nilfs2: fix lockdep warnings in page operations for btree nodes 2022-05-25 09:17:54 +02:00
btree.c nilfs2: fix general protection fault in nilfs_btree_insert() 2023-01-24 07:19:56 +01:00
btree.h
cpfile.c nilfs2: fix some kernel-doc warnings for nilfs2 2020-10-16 11:11:22 -07:00
cpfile.h
dat.c nilfs2: fix NULL pointer dereference in nilfs_palloc_commit_free_entry() 2022-12-08 11:23:57 +01:00
dat.h
dir.c
direct.c nilfs2: use a more common logging style 2020-08-12 10:58:01 -07:00
direct.h
export.h
file.c nilfs2: make splice write available again 2021-02-13 13:55:16 +01:00
gcinode.c nilfs2: fix lockdep warnings in page operations for btree nodes 2022-05-25 09:17:54 +02:00
ifile.c nilfs2: use a more common logging style 2020-08-12 10:58:01 -07:00
ifile.h
inode.c nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput 2023-08-16 18:21:00 +02:00
ioctl.c nilfs2: fix kernel-infoleak in nilfs_ioctl_wrap_copy() 2023-04-05 11:23:41 +02:00
Kconfig
Makefile
mdt.c nilfs2: fix lockdep warnings during disk space reclamation 2022-05-25 09:17:54 +02:00
mdt.h nilfs2: fix lockdep warnings during disk space reclamation 2022-05-25 09:17:54 +02:00
namei.c nilfs2: use a more common logging style 2020-08-12 10:58:01 -07:00
nilfs.h nilfs2: fix incorrect masking of permission flags for symlinks 2022-07-21 21:20:01 +02:00
page.c nilfs2: prevent general protection fault in nilfs_clear_dirty_page() 2023-06-28 10:28:09 +02:00
page.h
recovery.c treewide: Use fallthrough pseudo-keyword 2020-08-23 17:36:59 -05:00
segbuf.c nilfs2: fix buffer corruption due to concurrent device reads 2023-06-28 10:28:07 +02:00
segbuf.h
segment.c nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput 2023-08-16 18:21:00 +02:00
segment.h
sufile.c nilfs2: fix possible out-of-bounds segment allocation in resize ioctl 2023-06-21 15:45:37 +02:00
sufile.h
super.c nilfs2: fix buffer corruption due to concurrent device reads 2023-06-28 10:28:07 +02:00
sysfs.c nilfs2: fix memory leak in nilfs_sysfs_delete_snapshot_group 2021-09-26 14:09:01 +02:00
sysfs.h
the_nilfs.c nilfs2: reject devices with insufficient block count 2023-06-21 15:45:41 +02:00
the_nilfs.h nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput 2023-08-16 18:21:00 +02:00