From 54ebcaf094f792e163dced55e676ab68036d4894 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 20 Jul 2023 20:28:29 +0200 Subject: [PATCH] 6.4-stable patches added patches: f2fs-don-t-reset-unchangable-mount-option-in-f2fs_remount.patch f2fs-fix-deadlock-in-i_xattr_sem-and-inode-page-lock.patch --- ...angable-mount-option-in-f2fs_remount.patch | 136 ++++++++++++++++++ ...k-in-i_xattr_sem-and-inode-page-lock.patch | 89 ++++++++++++ queue-6.4/series | 2 + 3 files changed, 227 insertions(+) create mode 100644 queue-6.4/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_remount.patch create mode 100644 queue-6.4/f2fs-fix-deadlock-in-i_xattr_sem-and-inode-page-lock.patch diff --git a/queue-6.4/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_remount.patch b/queue-6.4/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_remount.patch new file mode 100644 index 00000000000..119fcdebdee --- /dev/null +++ b/queue-6.4/f2fs-don-t-reset-unchangable-mount-option-in-f2fs_remount.patch @@ -0,0 +1,136 @@ +From 458c15dfbce62c35fefd9ca637b20a051309c9f1 Mon Sep 17 00:00:00 2001 +From: Chao Yu +Date: Tue, 23 May 2023 11:58:22 +0800 +Subject: f2fs: don't reset unchangable mount option in f2fs_remount() + +From: Chao Yu + +commit 458c15dfbce62c35fefd9ca637b20a051309c9f1 upstream. + +syzbot reports a bug as below: + +general protection fault, probably for non-canonical address 0xdffffc0000000009: 0000 [#1] PREEMPT SMP KASAN +RIP: 0010:__lock_acquire+0x69/0x2000 kernel/locking/lockdep.c:4942 +Call Trace: + lock_acquire+0x1e3/0x520 kernel/locking/lockdep.c:5691 + __raw_write_lock include/linux/rwlock_api_smp.h:209 [inline] + _raw_write_lock+0x2e/0x40 kernel/locking/spinlock.c:300 + __drop_extent_tree+0x3ac/0x660 fs/f2fs/extent_cache.c:1100 + f2fs_drop_extent_tree+0x17/0x30 fs/f2fs/extent_cache.c:1116 + f2fs_insert_range+0x2d5/0x3c0 fs/f2fs/file.c:1664 + f2fs_fallocate+0x4e4/0x6d0 fs/f2fs/file.c:1838 + vfs_fallocate+0x54b/0x6b0 fs/open.c:324 + ksys_fallocate fs/open.c:347 [inline] + __do_sys_fallocate fs/open.c:355 [inline] + __se_sys_fallocate fs/open.c:353 [inline] + __x64_sys_fallocate+0xbd/0x100 fs/open.c:353 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x41/0xc0 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +The root cause is race condition as below: +- since it tries to remount rw filesystem, so that do_remount won't +call sb_prepare_remount_readonly to block fallocate, there may be race +condition in between remount and fallocate. +- in f2fs_remount(), default_options() will reset mount option to default +one, and then update it based on result of parse_options(), so there is +a hole which race condition can happen. + +Thread A Thread B +- f2fs_fill_super + - parse_options + - clear_opt(READ_EXTENT_CACHE) + +- f2fs_remount + - default_options + - set_opt(READ_EXTENT_CACHE) + - f2fs_fallocate + - f2fs_insert_range + - f2fs_drop_extent_tree + - __drop_extent_tree + - __may_extent_tree + - test_opt(READ_EXTENT_CACHE) return true + - write_lock(&et->lock) access NULL pointer + - parse_options + - clear_opt(READ_EXTENT_CACHE) + +Cc: +Reported-by: syzbot+d015b6c2fbb5c383bf08@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-f2fs-devel/20230522124203.3838360-1-chao@kernel.org +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/super.c | 30 ++++++++++++++++++------------ + 1 file changed, 18 insertions(+), 12 deletions(-) + +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -2086,9 +2086,22 @@ static int f2fs_show_options(struct seq_ + return 0; + } + +-static void default_options(struct f2fs_sb_info *sbi) ++static void default_options(struct f2fs_sb_info *sbi, bool remount) + { + /* init some FS parameters */ ++ if (!remount) { ++ set_opt(sbi, READ_EXTENT_CACHE); ++ clear_opt(sbi, DISABLE_CHECKPOINT); ++ ++ if (f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) ++ set_opt(sbi, DISCARD); ++ ++ if (f2fs_sb_has_blkzoned(sbi)) ++ F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_SECTION; ++ else ++ F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_BLOCK; ++ } ++ + if (f2fs_sb_has_readonly(sbi)) + F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE; + else +@@ -2118,23 +2131,16 @@ static void default_options(struct f2fs_ + set_opt(sbi, INLINE_XATTR); + set_opt(sbi, INLINE_DATA); + set_opt(sbi, INLINE_DENTRY); +- set_opt(sbi, READ_EXTENT_CACHE); + set_opt(sbi, NOHEAP); +- clear_opt(sbi, DISABLE_CHECKPOINT); + set_opt(sbi, MERGE_CHECKPOINT); + F2FS_OPTION(sbi).unusable_cap = 0; + sbi->sb->s_flags |= SB_LAZYTIME; + if (!f2fs_is_readonly(sbi)) + set_opt(sbi, FLUSH_MERGE); +- if (f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) +- set_opt(sbi, DISCARD); +- if (f2fs_sb_has_blkzoned(sbi)) { ++ if (f2fs_sb_has_blkzoned(sbi)) + F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS; +- F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_SECTION; +- } else { ++ else + F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE; +- F2FS_OPTION(sbi).discard_unit = DISCARD_UNIT_BLOCK; +- } + + #ifdef CONFIG_F2FS_FS_XATTR + set_opt(sbi, XATTR_USER); +@@ -2306,7 +2312,7 @@ static int f2fs_remount(struct super_blo + clear_sbi_flag(sbi, SBI_NEED_SB_WRITE); + } + +- default_options(sbi); ++ default_options(sbi, true); + + /* parse mount options */ + err = parse_options(sb, data, true); +@@ -4357,7 +4363,7 @@ try_onemore: + sbi->s_chksum_seed = f2fs_chksum(sbi, ~0, raw_super->uuid, + sizeof(raw_super->uuid)); + +- default_options(sbi); ++ default_options(sbi, false); + /* parse mount options */ + options = kstrdup((const char *)data, GFP_KERNEL); + if (data && !options) { diff --git a/queue-6.4/f2fs-fix-deadlock-in-i_xattr_sem-and-inode-page-lock.patch b/queue-6.4/f2fs-fix-deadlock-in-i_xattr_sem-and-inode-page-lock.patch new file mode 100644 index 00000000000..b06adc72959 --- /dev/null +++ b/queue-6.4/f2fs-fix-deadlock-in-i_xattr_sem-and-inode-page-lock.patch @@ -0,0 +1,89 @@ +From 5eda1ad1aaffdfebdecf7a164e586060a210f74f Mon Sep 17 00:00:00 2001 +From: Jaegeuk Kim +Date: Wed, 28 Jun 2023 01:00:56 -0700 +Subject: f2fs: fix deadlock in i_xattr_sem and inode page lock + +From: Jaegeuk Kim + +commit 5eda1ad1aaffdfebdecf7a164e586060a210f74f upstream. + +Thread #1: + +[122554.641906][ T92] f2fs_getxattr+0xd4/0x5fc + -> waiting for f2fs_down_read(&F2FS_I(inode)->i_xattr_sem); + +[122554.641927][ T92] __f2fs_get_acl+0x50/0x284 +[122554.641948][ T92] f2fs_init_acl+0x84/0x54c +[122554.641969][ T92] f2fs_init_inode_metadata+0x460/0x5f0 +[122554.641990][ T92] f2fs_add_inline_entry+0x11c/0x350 + -> Locked dir->inode_page by f2fs_get_node_page() + +[122554.642009][ T92] f2fs_do_add_link+0x100/0x1e4 +[122554.642025][ T92] f2fs_create+0xf4/0x22c +[122554.642047][ T92] vfs_create+0x130/0x1f4 + +Thread #2: + +[123996.386358][ T92] __get_node_page+0x8c/0x504 + -> waiting for dir->inode_page lock + +[123996.386383][ T92] read_all_xattrs+0x11c/0x1f4 +[123996.386405][ T92] __f2fs_setxattr+0xcc/0x528 +[123996.386424][ T92] f2fs_setxattr+0x158/0x1f4 + -> f2fs_down_write(&F2FS_I(inode)->i_xattr_sem); + +[123996.386443][ T92] __f2fs_set_acl+0x328/0x430 +[123996.386618][ T92] f2fs_set_acl+0x38/0x50 +[123996.386642][ T92] posix_acl_chmod+0xc8/0x1c8 +[123996.386669][ T92] f2fs_setattr+0x5e0/0x6bc +[123996.386689][ T92] notify_change+0x4d8/0x580 +[123996.386717][ T92] chmod_common+0xd8/0x184 +[123996.386748][ T92] do_fchmodat+0x60/0x124 +[123996.386766][ T92] __arm64_sys_fchmodat+0x28/0x3c + +Cc: +Fixes: 27161f13e3c3 "f2fs: avoid race in between read xattr & write xattr" +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/dir.c | 9 ++++++++- + fs/f2fs/xattr.c | 6 ++++-- + 2 files changed, 12 insertions(+), 3 deletions(-) + +--- a/fs/f2fs/dir.c ++++ b/fs/f2fs/dir.c +@@ -775,8 +775,15 @@ int f2fs_add_dentry(struct inode *dir, c + { + int err = -EAGAIN; + +- if (f2fs_has_inline_dentry(dir)) ++ if (f2fs_has_inline_dentry(dir)) { ++ /* ++ * Should get i_xattr_sem to keep the lock order: ++ * i_xattr_sem -> inode_page lock used by f2fs_setxattr. ++ */ ++ f2fs_down_read(&F2FS_I(dir)->i_xattr_sem); + err = f2fs_add_inline_entry(dir, fname, inode, ino, mode); ++ f2fs_up_read(&F2FS_I(dir)->i_xattr_sem); ++ } + if (err == -EAGAIN) + err = f2fs_add_regular_entry(dir, fname, inode, ino, mode); + +--- a/fs/f2fs/xattr.c ++++ b/fs/f2fs/xattr.c +@@ -528,10 +528,12 @@ int f2fs_getxattr(struct inode *inode, i + if (len > F2FS_NAME_LEN) + return -ERANGE; + +- f2fs_down_read(&F2FS_I(inode)->i_xattr_sem); ++ if (!ipage) ++ f2fs_down_read(&F2FS_I(inode)->i_xattr_sem); + error = lookup_all_xattrs(inode, ipage, index, len, name, + &entry, &base_addr, &base_size, &is_inline); +- f2fs_up_read(&F2FS_I(inode)->i_xattr_sem); ++ if (!ipage) ++ f2fs_up_read(&F2FS_I(inode)->i_xattr_sem); + if (error) + return error; + diff --git a/queue-6.4/series b/queue-6.4/series index 4cb3d8cca28..7b69d3abafc 100644 --- a/queue-6.4/series +++ b/queue-6.4/series @@ -109,3 +109,5 @@ smb-client-improve-dfs-mount-check.patch cifs-fix-session-state-check-in-smb2_find_smb_ses.patch smb-client-fix-parsing-of-source-mount-option.patch drm-client-send-hotplug-event-after-registering-a-client.patch +f2fs-don-t-reset-unchangable-mount-option-in-f2fs_remount.patch +f2fs-fix-deadlock-in-i_xattr_sem-and-inode-page-lock.patch -- 2.47.3