From f039955c320fdde1e4d8f466d211e6c2fa32ca8a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 6 Mar 2023 14:44:20 +0100 Subject: [PATCH] 5.4-stable patches added patches: f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch ocfs2-fix-defrag-path-triggering-jbd2-assert.patch ocfs2-fix-non-auto-defrag-path-not-working-issue.patch udf-detect-system-inodes-linked-into-directory-hierarchy.patch udf-do-not-bother-merging-very-long-extents.patch udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch udf-preserve-link-count-of-system-files.patch udf-truncate-added-extents-on-failed-expansion.patch --- ...-accounting-with-fs-layer-encryption.patch | 63 +++++++++++ ...ion-leak-in-f2fs_move_inline_dirents.patch | 56 ++++++++++ ...s-fix-uaf-issue-in-hfsplus_put_super.patch | 52 +++++++++ ...-hfs_bnode_get-in-__hfs_bnode_create.patch | 98 +++++++++++++++++ ...x-defrag-path-triggering-jbd2-assert.patch | 100 ++++++++++++++++++ ...n-auto-defrag-path-not-working-issue.patch | 91 ++++++++++++++++ queue-5.4/series | 12 +++ ...odes-linked-into-directory-hierarchy.patch | 40 +++++++ ...not-bother-merging-very-long-extents.patch | 52 +++++++++ ...th-for-failed-writes-to-inline-files.patch | 62 +++++++++++ ...ust-after-end-of-preallocated-extent.patch | 63 +++++++++++ ...-preserve-link-count-of-system-files.patch | 69 ++++++++++++ ...te-added-extents-on-failed-expansion.patch | 65 ++++++++++++ 13 files changed, 823 insertions(+) create mode 100644 queue-5.4/f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch create mode 100644 queue-5.4/f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch create mode 100644 queue-5.4/fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch create mode 100644 queue-5.4/hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch create mode 100644 queue-5.4/ocfs2-fix-defrag-path-triggering-jbd2-assert.patch create mode 100644 queue-5.4/ocfs2-fix-non-auto-defrag-path-not-working-issue.patch create mode 100644 queue-5.4/udf-detect-system-inodes-linked-into-directory-hierarchy.patch create mode 100644 queue-5.4/udf-do-not-bother-merging-very-long-extents.patch create mode 100644 queue-5.4/udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch create mode 100644 queue-5.4/udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch create mode 100644 queue-5.4/udf-preserve-link-count-of-system-files.patch create mode 100644 queue-5.4/udf-truncate-added-extents-on-failed-expansion.patch diff --git a/queue-5.4/f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch b/queue-5.4/f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch new file mode 100644 index 00000000000..7a19bf49597 --- /dev/null +++ b/queue-5.4/f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch @@ -0,0 +1,63 @@ +From 844545c51a5b2a524b22a2fe9d0b353b827d24b4 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Thu, 2 Feb 2023 17:02:39 -0800 +Subject: f2fs: fix cgroup writeback accounting with fs-layer encryption + +From: Eric Biggers + +commit 844545c51a5b2a524b22a2fe9d0b353b827d24b4 upstream. + +When writing a page from an encrypted file that is using +filesystem-layer encryption (not inline encryption), f2fs encrypts the +pagecache page into a bounce page, then writes the bounce page. + +It also passes the bounce page to wbc_account_cgroup_owner(). That's +incorrect, because the bounce page is a newly allocated temporary page +that doesn't have the memory cgroup of the original pagecache page. +This makes wbc_account_cgroup_owner() not account the I/O to the owner +of the pagecache page as it should. + +Fix this by always passing the pagecache page to +wbc_account_cgroup_owner(). + +Fixes: 578c647879f7 ("f2fs: implement cgroup writeback support") +Cc: stable@vger.kernel.org +Reported-by: Matthew Wilcox (Oracle) +Signed-off-by: Eric Biggers +Acked-by: Tejun Heo +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/data.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -496,7 +496,7 @@ int f2fs_submit_page_bio(struct f2fs_io_ + } + + if (fio->io_wbc && !is_read_io(fio->op)) +- wbc_account_cgroup_owner(fio->io_wbc, page, PAGE_SIZE); ++ wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE); + + bio_set_op_attrs(bio, fio->op, fio->op_flags); + +@@ -575,7 +575,7 @@ alloc_new: + } + + if (fio->io_wbc) +- wbc_account_cgroup_owner(fio->io_wbc, page, PAGE_SIZE); ++ wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE); + + inc_page_count(fio->sbi, WB_DATA_TYPE(page)); + +@@ -652,7 +652,7 @@ alloc_new: + } + + if (fio->io_wbc) +- wbc_account_cgroup_owner(fio->io_wbc, bio_page, PAGE_SIZE); ++ wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE); + + io->last_block_in_bio = fio->new_blkaddr; + f2fs_trace_ios(fio, 0); diff --git a/queue-5.4/f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch b/queue-5.4/f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch new file mode 100644 index 00000000000..6496ab03477 --- /dev/null +++ b/queue-5.4/f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch @@ -0,0 +1,56 @@ +From 9a5571cff4ffcfc24847df9fd545cc5799ac0ee5 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Sun, 22 Jan 2023 23:04:14 -0800 +Subject: f2fs: fix information leak in f2fs_move_inline_dirents() + +From: Eric Biggers + +commit 9a5571cff4ffcfc24847df9fd545cc5799ac0ee5 upstream. + +When converting an inline directory to a regular one, f2fs is leaking +uninitialized memory to disk because it doesn't initialize the entire +directory block. Fix this by zero-initializing the block. + +This bug was introduced by commit 4ec17d688d74 ("f2fs: avoid unneeded +initializing when converting inline dentry"), which didn't consider the +security implications of leaking uninitialized memory to disk. + +This was found by running xfstest generic/435 on a KMSAN-enabled kernel. + +Fixes: 4ec17d688d74 ("f2fs: avoid unneeded initializing when converting inline dentry") +Cc: # v4.3+ +Signed-off-by: Eric Biggers +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/inline.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/fs/f2fs/inline.c ++++ b/fs/f2fs/inline.c +@@ -402,18 +402,17 @@ static int f2fs_move_inline_dirents(stru + + dentry_blk = page_address(page); + ++ /* ++ * Start by zeroing the full block, to ensure that all unused space is ++ * zeroed and no uninitialized memory is leaked to disk. ++ */ ++ memset(dentry_blk, 0, F2FS_BLKSIZE); ++ + make_dentry_ptr_inline(dir, &src, inline_dentry); + make_dentry_ptr_block(dir, &dst, dentry_blk); + + /* copy data from inline dentry block to new dentry block */ + memcpy(dst.bitmap, src.bitmap, src.nr_bitmap); +- memset(dst.bitmap + src.nr_bitmap, 0, dst.nr_bitmap - src.nr_bitmap); +- /* +- * we do not need to zero out remainder part of dentry and filename +- * field, since we have used bitmap for marking the usage status of +- * them, besides, we can also ignore copying/zeroing reserved space +- * of dentry block, because them haven't been used so far. +- */ + memcpy(dst.dentry, src.dentry, SIZE_OF_DIR_ENTRY * src.max); + memcpy(dst.filename, src.filename, src.max * F2FS_SLOT_LEN); + diff --git a/queue-5.4/fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch b/queue-5.4/fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch new file mode 100644 index 00000000000..cf6cd558ebc --- /dev/null +++ b/queue-5.4/fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch @@ -0,0 +1,52 @@ +From 07db5e247ab5858439b14dd7cc1fe538b9efcf32 Mon Sep 17 00:00:00 2001 +From: Dongliang Mu +Date: Sun, 26 Feb 2023 20:49:47 +0800 +Subject: fs: hfsplus: fix UAF issue in hfsplus_put_super + +From: Dongliang Mu + +commit 07db5e247ab5858439b14dd7cc1fe538b9efcf32 upstream. + +The current hfsplus_put_super first calls hfs_btree_close on +sbi->ext_tree, then invokes iput on sbi->hidden_dir, resulting in an +use-after-free issue in hfsplus_release_folio. + +As shown in hfsplus_fill_super, the error handling code also calls iput +before hfs_btree_close. + +To fix this error, we move all iput calls before hfsplus_btree_close. + +Note that this patch is tested on Syzbot. + +Link: https://lkml.kernel.org/r/20230226124948.3175736-1-mudongliangabcd@gmail.com +Reported-by: syzbot+57e3e98f7e3b80f64d56@syzkaller.appspotmail.com +Tested-by: Dongliang Mu +Signed-off-by: Dongliang Mu +Cc: Bart Van Assche +Cc: Jens Axboe +Cc: Muchun Song +Cc: Roman Gushchin +Cc: "Theodore Ts'o" +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/hfsplus/super.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/hfsplus/super.c ++++ b/fs/hfsplus/super.c +@@ -295,11 +295,11 @@ static void hfsplus_put_super(struct sup + hfsplus_sync_fs(sb, 1); + } + ++ iput(sbi->alloc_file); ++ iput(sbi->hidden_dir); + hfs_btree_close(sbi->attr_tree); + hfs_btree_close(sbi->cat_tree); + hfs_btree_close(sbi->ext_tree); +- iput(sbi->alloc_file); +- iput(sbi->hidden_dir); + kfree(sbi->s_vhdr_buf); + kfree(sbi->s_backup_vhdr_buf); + unload_nls(sbi->nls); diff --git a/queue-5.4/hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch b/queue-5.4/hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch new file mode 100644 index 00000000000..d18b0859bd1 --- /dev/null +++ b/queue-5.4/hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch @@ -0,0 +1,98 @@ +From a9dc087fd3c484fd1ed18c5efb290efaaf44ce03 Mon Sep 17 00:00:00 2001 +From: Liu Shixin +Date: Mon, 12 Dec 2022 10:16:27 +0800 +Subject: hfs: fix missing hfs_bnode_get() in __hfs_bnode_create + +From: Liu Shixin + +commit a9dc087fd3c484fd1ed18c5efb290efaaf44ce03 upstream. + +Syzbot found a kernel BUG in hfs_bnode_put(): + + kernel BUG at fs/hfs/bnode.c:466! + invalid opcode: 0000 [#1] PREEMPT SMP KASAN + CPU: 0 PID: 3634 Comm: kworker/u4:5 Not tainted 6.1.0-rc7-syzkaller-00190-g97ee9d1c1696 #0 + Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 + Workqueue: writeback wb_workfn (flush-7:0) + RIP: 0010:hfs_bnode_put+0x46f/0x480 fs/hfs/bnode.c:466 + Code: 8a 80 ff e9 73 fe ff ff 89 d9 80 e1 07 80 c1 03 38 c1 0f 8c a0 fe ff ff 48 89 df e8 db 8a 80 ff e9 93 fe ff ff e8 a1 68 2c ff <0f> 0b e8 9a 68 2c ff 0f 0b 0f 1f 84 00 00 00 00 00 55 41 57 41 56 + RSP: 0018:ffffc90003b4f258 EFLAGS: 00010293 + RAX: ffffffff825e318f RBX: 0000000000000000 RCX: ffff8880739dd7c0 + RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 + RBP: ffffc90003b4f430 R08: ffffffff825e2d9b R09: ffffed10045157d1 + R10: ffffed10045157d1 R11: 1ffff110045157d0 R12: ffff8880228abe80 + R13: ffff88807016c000 R14: dffffc0000000000 R15: ffff8880228abe00 + FS: 0000000000000000(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007fa6ebe88718 CR3: 000000001e93d000 CR4: 00000000003506f0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + Call Trace: + + hfs_write_inode+0x1bc/0xb40 + write_inode fs/fs-writeback.c:1440 [inline] + __writeback_single_inode+0x4d6/0x670 fs/fs-writeback.c:1652 + writeback_sb_inodes+0xb3b/0x18f0 fs/fs-writeback.c:1878 + __writeback_inodes_wb+0x125/0x420 fs/fs-writeback.c:1949 + wb_writeback+0x440/0x7b0 fs/fs-writeback.c:2054 + wb_check_start_all fs/fs-writeback.c:2176 [inline] + wb_do_writeback fs/fs-writeback.c:2202 [inline] + wb_workfn+0x827/0xef0 fs/fs-writeback.c:2235 + process_one_work+0x877/0xdb0 kernel/workqueue.c:2289 + worker_thread+0xb14/0x1330 kernel/workqueue.c:2436 + kthread+0x266/0x300 kernel/kthread.c:376 + ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306 + + +The BUG_ON() is triggered at here: + +/* Dispose of resources used by a node */ +void hfs_bnode_put(struct hfs_bnode *node) +{ + if (node) { + + BUG_ON(!atomic_read(&node->refcnt)); <- we have issue here!!!! + + } +} + +By tracing the refcnt, I found the node is created by hfs_bmap_alloc() +with refcnt 1. Then the node is used by hfs_btree_write(). There is a +missing of hfs_bnode_get() after find the node. The issue happened in +following path: + + + hfs_bmap_alloc + hfs_bnode_find + __hfs_bnode_create <- allocate a new node with refcnt 1. + hfs_bnode_put <- decrease the refcnt + + + hfs_btree_write + hfs_bnode_find + __hfs_bnode_create + hfs_bnode_findhash <- find the node without refcnt increased. + hfs_bnode_put <- trigger the BUG_ON() since refcnt is 0. + +Link: https://lkml.kernel.org/r/20221212021627.3766829-1-liushixin2@huawei.com +Reported-by: syzbot+5b04b49a7ec7226c7426@syzkaller.appspotmail.com +Signed-off-by: Liu Shixin +Cc: Fabio M. De Francesco +Cc: Viacheslav Dubeyko +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/hfs/bnode.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/hfs/bnode.c ++++ b/fs/hfs/bnode.c +@@ -281,6 +281,7 @@ static struct hfs_bnode *__hfs_bnode_cre + tree->node_hash[hash] = node; + tree->node_hash_cnt++; + } else { ++ hfs_bnode_get(node2); + spin_unlock(&tree->hash_lock); + kfree(node); + wait_event(node2->lock_wq, !test_bit(HFS_BNODE_NEW, &node2->flags)); diff --git a/queue-5.4/ocfs2-fix-defrag-path-triggering-jbd2-assert.patch b/queue-5.4/ocfs2-fix-defrag-path-triggering-jbd2-assert.patch new file mode 100644 index 00000000000..f713cbd7390 --- /dev/null +++ b/queue-5.4/ocfs2-fix-defrag-path-triggering-jbd2-assert.patch @@ -0,0 +1,100 @@ +From 60eed1e3d45045623e46944ebc7c42c30a4350f0 Mon Sep 17 00:00:00 2001 +From: Heming Zhao via Ocfs2-devel +Date: Fri, 17 Feb 2023 08:37:17 +0800 +Subject: ocfs2: fix defrag path triggering jbd2 ASSERT + +From: Heming Zhao via Ocfs2-devel + +commit 60eed1e3d45045623e46944ebc7c42c30a4350f0 upstream. + +code path: + +ocfs2_ioctl_move_extents + ocfs2_move_extents + ocfs2_defrag_extent + __ocfs2_move_extent + + ocfs2_journal_access_di + + ocfs2_split_extent //sub-paths call jbd2_journal_restart + + ocfs2_journal_dirty //crash by jbs2 ASSERT + +crash stacks: + +PID: 11297 TASK: ffff974a676dcd00 CPU: 67 COMMAND: "defragfs.ocfs2" + #0 [ffffb25d8dad3900] machine_kexec at ffffffff8386fe01 + #1 [ffffb25d8dad3958] __crash_kexec at ffffffff8395959d + #2 [ffffb25d8dad3a20] crash_kexec at ffffffff8395a45d + #3 [ffffb25d8dad3a38] oops_end at ffffffff83836d3f + #4 [ffffb25d8dad3a58] do_trap at ffffffff83833205 + #5 [ffffb25d8dad3aa0] do_invalid_op at ffffffff83833aa6 + #6 [ffffb25d8dad3ac0] invalid_op at ffffffff84200d18 + [exception RIP: jbd2_journal_dirty_metadata+0x2ba] + RIP: ffffffffc09ca54a RSP: ffffb25d8dad3b70 RFLAGS: 00010207 + RAX: 0000000000000000 RBX: ffff9706eedc5248 RCX: 0000000000000000 + RDX: 0000000000000001 RSI: ffff97337029ea28 RDI: ffff9706eedc5250 + RBP: ffff9703c3520200 R8: 000000000f46b0b2 R9: 0000000000000000 + R10: 0000000000000001 R11: 00000001000000fe R12: ffff97337029ea28 + R13: 0000000000000000 R14: ffff9703de59bf60 R15: ffff9706eedc5250 + ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 + #7 [ffffb25d8dad3ba8] ocfs2_journal_dirty at ffffffffc137fb95 [ocfs2] + #8 [ffffb25d8dad3be8] __ocfs2_move_extent at ffffffffc139a950 [ocfs2] + #9 [ffffb25d8dad3c80] ocfs2_defrag_extent at ffffffffc139b2d2 [ocfs2] + +Analysis + +This bug has the same root cause of 'commit 7f27ec978b0e ("ocfs2: call +ocfs2_journal_access_di() before ocfs2_journal_dirty() in +ocfs2_write_end_nolock()")'. For this bug, jbd2_journal_restart() is +called by ocfs2_split_extent() during defragmenting. + +How to fix + +For ocfs2_split_extent() can handle journal operations totally by itself. +Caller doesn't need to call journal access/dirty pair, and caller only +needs to call journal start/stop pair. The fix method is to remove +journal access/dirty from __ocfs2_move_extent(). + +The discussion for this patch: +https://oss.oracle.com/pipermail/ocfs2-devel/2023-February/000647.html + +Link: https://lkml.kernel.org/r/20230217003717.32469-1-heming.zhao@suse.com +Signed-off-by: Heming Zhao +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Gang He +Cc: Jun Piao +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/move_extents.c | 10 ---------- + 1 file changed, 10 deletions(-) + +--- a/fs/ocfs2/move_extents.c ++++ b/fs/ocfs2/move_extents.c +@@ -107,14 +107,6 @@ static int __ocfs2_move_extent(handle_t + */ + replace_rec.e_flags = ext_flags & ~OCFS2_EXT_REFCOUNTED; + +- ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), +- context->et.et_root_bh, +- OCFS2_JOURNAL_ACCESS_WRITE); +- if (ret) { +- mlog_errno(ret); +- goto out; +- } +- + ret = ocfs2_split_extent(handle, &context->et, path, index, + &replace_rec, context->meta_ac, + &context->dealloc); +@@ -123,8 +115,6 @@ static int __ocfs2_move_extent(handle_t + goto out; + } + +- ocfs2_journal_dirty(handle, context->et.et_root_bh); +- + context->new_phys_cpos = new_p_cpos; + + /* diff --git a/queue-5.4/ocfs2-fix-non-auto-defrag-path-not-working-issue.patch b/queue-5.4/ocfs2-fix-non-auto-defrag-path-not-working-issue.patch new file mode 100644 index 00000000000..011060dbb24 --- /dev/null +++ b/queue-5.4/ocfs2-fix-non-auto-defrag-path-not-working-issue.patch @@ -0,0 +1,91 @@ +From 236b9254f8d1edc273ad88b420aa85fbd84f492d Mon Sep 17 00:00:00 2001 +From: Heming Zhao via Ocfs2-devel +Date: Mon, 20 Feb 2023 13:05:26 +0800 +Subject: ocfs2: fix non-auto defrag path not working issue + +From: Heming Zhao via Ocfs2-devel + +commit 236b9254f8d1edc273ad88b420aa85fbd84f492d upstream. + +This fixes three issues on move extents ioctl without auto defrag: + +a) In ocfs2_find_victim_alloc_group(), we have to convert bits to block + first in case of global bitmap. + +b) In ocfs2_probe_alloc_group(), when finding enough bits in block + group bitmap, we have to back off move_len to start pos as well, + otherwise it may corrupt filesystem. + +c) In ocfs2_ioctl_move_extents(), set me_threshold both for non-auto + and auto defrag paths. Otherwise it will set move_max_hop to 0 and + finally cause unexpectedly ENOSPC error. + +Currently there are no tools triggering the above issues since +defragfs.ocfs2 enables auto defrag by default. Tested with manually +changing defragfs.ocfs2 to run non auto defrag path. + +Link: https://lkml.kernel.org/r/20230220050526.22020-1-heming.zhao@suse.com +Signed-off-by: Heming Zhao +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Gang He +Cc: Jun Piao +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/move_extents.c | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +--- a/fs/ocfs2/move_extents.c ++++ b/fs/ocfs2/move_extents.c +@@ -436,7 +436,7 @@ static int ocfs2_find_victim_alloc_group + bg = (struct ocfs2_group_desc *)gd_bh->b_data; + + if (vict_blkno < (le64_to_cpu(bg->bg_blkno) + +- le16_to_cpu(bg->bg_bits))) { ++ (le16_to_cpu(bg->bg_bits) << bits_per_unit))) { + + *ret_bh = gd_bh; + *vict_bit = (vict_blkno - blkno) >> +@@ -551,6 +551,7 @@ static void ocfs2_probe_alloc_group(stru + last_free_bits++; + + if (last_free_bits == move_len) { ++ i -= move_len; + *goal_bit = i; + *phys_cpos = base_cpos + i; + break; +@@ -1022,18 +1023,19 @@ int ocfs2_ioctl_move_extents(struct file + + context->range = ⦥ + ++ /* ++ * ok, the default theshold for the defragmentation ++ * is 1M, since our maximum clustersize was 1M also. ++ * any thought? ++ */ ++ if (!range.me_threshold) ++ range.me_threshold = 1024 * 1024; ++ ++ if (range.me_threshold > i_size_read(inode)) ++ range.me_threshold = i_size_read(inode); ++ + if (range.me_flags & OCFS2_MOVE_EXT_FL_AUTO_DEFRAG) { + context->auto_defrag = 1; +- /* +- * ok, the default theshold for the defragmentation +- * is 1M, since our maximum clustersize was 1M also. +- * any thought? +- */ +- if (!range.me_threshold) +- range.me_threshold = 1024 * 1024; +- +- if (range.me_threshold > i_size_read(inode)) +- range.me_threshold = i_size_read(inode); + + if (range.me_flags & OCFS2_MOVE_EXT_FL_PART_DEFRAG) + context->partial = 1; diff --git a/queue-5.4/series b/queue-5.4/series index c36a1634d94..c4b5e7b30c8 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -219,3 +219,15 @@ s390-discard-.interp-section.patch s390-kprobes-fix-irq-mask-clobbering-on-kprobe-reenter-from-post_handler.patch s390-kprobes-fix-current_kprobe-never-cleared-after-kprobes-reenter.patch arm-dts-exynos-correct-hdmi-phy-compatible-in-exynos4.patch +hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch +fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch +f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch +f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch +ocfs2-fix-defrag-path-triggering-jbd2-assert.patch +ocfs2-fix-non-auto-defrag-path-not-working-issue.patch +udf-truncate-added-extents-on-failed-expansion.patch +udf-do-not-bother-merging-very-long-extents.patch +udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch +udf-preserve-link-count-of-system-files.patch +udf-detect-system-inodes-linked-into-directory-hierarchy.patch +udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch diff --git a/queue-5.4/udf-detect-system-inodes-linked-into-directory-hierarchy.patch b/queue-5.4/udf-detect-system-inodes-linked-into-directory-hierarchy.patch new file mode 100644 index 00000000000..d6506656fff --- /dev/null +++ b/queue-5.4/udf-detect-system-inodes-linked-into-directory-hierarchy.patch @@ -0,0 +1,40 @@ +From 85a37983ec69cc9fcd188bc37c4de15ee326355a Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Tue, 3 Jan 2023 10:03:35 +0100 +Subject: udf: Detect system inodes linked into directory hierarchy + +From: Jan Kara + +commit 85a37983ec69cc9fcd188bc37c4de15ee326355a upstream. + +When UDF filesystem is corrupted, hidden system inodes can be linked +into directory hierarchy which is an avenue for further serious +corruption of the filesystem and kernel confusion as noticed by syzbot +fuzzed images. Refuse to access system inodes linked into directory +hierarchy and vice versa. + +CC: stable@vger.kernel.org +Reported-by: syzbot+38695a20b8addcbc1084@syzkaller.appspotmail.com +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/inode.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -1900,8 +1900,13 @@ struct inode *__udf_iget(struct super_bl + if (!inode) + return ERR_PTR(-ENOMEM); + +- if (!(inode->i_state & I_NEW)) ++ if (!(inode->i_state & I_NEW)) { ++ if (UDF_I(inode)->i_hidden != hidden_inode) { ++ iput(inode); ++ return ERR_PTR(-EFSCORRUPTED); ++ } + return inode; ++ } + + memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr)); + err = udf_read_inode(inode, hidden_inode); diff --git a/queue-5.4/udf-do-not-bother-merging-very-long-extents.patch b/queue-5.4/udf-do-not-bother-merging-very-long-extents.patch new file mode 100644 index 00000000000..27f3a91801a --- /dev/null +++ b/queue-5.4/udf-do-not-bother-merging-very-long-extents.patch @@ -0,0 +1,52 @@ +From 53cafe1d6d8ef9f93318e5bfccc0d24f27d41ced Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 16 Dec 2022 12:37:51 +0100 +Subject: udf: Do not bother merging very long extents + +From: Jan Kara + +commit 53cafe1d6d8ef9f93318e5bfccc0d24f27d41ced upstream. + +When merging very long extents we try to push as much length as possible +to the first extent. However this is unnecessarily complicated and not +really worth the trouble. Furthermore there was a bug in the logic +resulting in corrupting extents in the file as syzbot reproducer shows. +So just don't bother with the merging of extents that are too long +together. + +CC: stable@vger.kernel.org +Reported-by: syzbot+60f291a24acecb3c2bd5@syzkaller.appspotmail.com +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/inode.c | 19 ++----------------- + 1 file changed, 2 insertions(+), 17 deletions(-) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -1096,23 +1096,8 @@ static void udf_merge_extents(struct ino + blocksize - 1) >> blocksize_bits)))) { + + if (((li->extLength & UDF_EXTENT_LENGTH_MASK) + +- (lip1->extLength & UDF_EXTENT_LENGTH_MASK) + +- blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK) { +- lip1->extLength = (lip1->extLength - +- (li->extLength & +- UDF_EXTENT_LENGTH_MASK) + +- UDF_EXTENT_LENGTH_MASK) & +- ~(blocksize - 1); +- li->extLength = (li->extLength & +- UDF_EXTENT_FLAG_MASK) + +- (UDF_EXTENT_LENGTH_MASK + 1) - +- blocksize; +- lip1->extLocation.logicalBlockNum = +- li->extLocation.logicalBlockNum + +- ((li->extLength & +- UDF_EXTENT_LENGTH_MASK) >> +- blocksize_bits); +- } else { ++ (lip1->extLength & UDF_EXTENT_LENGTH_MASK) + ++ blocksize - 1) <= UDF_EXTENT_LENGTH_MASK) { + li->extLength = lip1->extLength + + (((li->extLength & + UDF_EXTENT_LENGTH_MASK) + diff --git a/queue-5.4/udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch b/queue-5.4/udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch new file mode 100644 index 00000000000..ccea9079323 --- /dev/null +++ b/queue-5.4/udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch @@ -0,0 +1,62 @@ +From 256fe4162f8b5a1625b8603ca5f7ff79725bfb47 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 2 Jan 2023 20:14:47 +0100 +Subject: udf: Do not update file length for failed writes to inline files + +From: Jan Kara + +commit 256fe4162f8b5a1625b8603ca5f7ff79725bfb47 upstream. + +When write to inline file fails (or happens only partly), we still +updated length of inline data as if the whole write succeeded. Fix the +update of length of inline data to happen only if the write succeeds. + +Reported-by: syzbot+0937935b993956ba28ab@syzkaller.appspotmail.com +CC: stable@vger.kernel.org +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/file.c | 26 ++++++++++++-------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +--- a/fs/udf/file.c ++++ b/fs/udf/file.c +@@ -148,26 +148,24 @@ static ssize_t udf_file_write_iter(struc + goto out; + + down_write(&iinfo->i_data_sem); +- if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { +- loff_t end = iocb->ki_pos + iov_iter_count(from); +- +- if (inode->i_sb->s_blocksize < +- (udf_file_entry_alloc_offset(inode) + end)) { +- err = udf_expand_file_adinicb(inode); +- if (err) { +- inode_unlock(inode); +- udf_debug("udf_expand_adinicb: err=%d\n", err); +- return err; +- } +- } else { +- iinfo->i_lenAlloc = max(end, inode->i_size); +- up_write(&iinfo->i_data_sem); ++ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB && ++ inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) + ++ iocb->ki_pos + iov_iter_count(from))) { ++ err = udf_expand_file_adinicb(inode); ++ if (err) { ++ inode_unlock(inode); ++ udf_debug("udf_expand_adinicb: err=%d\n", err); ++ return err; + } + } else + up_write(&iinfo->i_data_sem); + + retval = __generic_file_write_iter(iocb, from); + out: ++ down_write(&iinfo->i_data_sem); ++ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB && retval > 0) ++ iinfo->i_lenAlloc = inode->i_size; ++ up_write(&iinfo->i_data_sem); + inode_unlock(inode); + + if (retval > 0) { diff --git a/queue-5.4/udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch b/queue-5.4/udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch new file mode 100644 index 00000000000..0465f37b18e --- /dev/null +++ b/queue-5.4/udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch @@ -0,0 +1,63 @@ +From 36ec52ea038b18a53e198116ef7d7e70c87db046 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 23 Jan 2023 14:18:47 +0100 +Subject: udf: Fix file corruption when appending just after end of preallocated extent + +From: Jan Kara + +commit 36ec52ea038b18a53e198116ef7d7e70c87db046 upstream. + +When we append new block just after the end of preallocated extent, the +code in inode_getblk() wrongly determined we're going to use the +preallocated extent which resulted in adding block into a wrong logical +offset in the file. Sequence like this manifests it: + +xfs_io -f -c "pwrite 0x2cacf 0xd122" -c "truncate 0x2dd6f" \ + -c "pwrite 0x27fd9 0x69a9" -c "pwrite 0x32981 0x7244" + +The code that determined the use of preallocated extent is actually +stale because udf_do_extend_file() does not create preallocation anymore +so after calling that function we are sure there's no usable +preallocation. Just remove the faulty condition. + +CC: stable@vger.kernel.org +Fixes: 16d055656814 ("udf: Discard preallocation before extending file with a hole") +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/inode.c | 24 +++++++++++------------- + 1 file changed, 11 insertions(+), 13 deletions(-) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -807,19 +807,17 @@ static sector_t inode_getblk(struct inod + c = 0; + offset = 0; + count += ret; +- /* We are not covered by a preallocated extent? */ +- if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) != +- EXT_NOT_RECORDED_ALLOCATED) { +- /* Is there any real extent? - otherwise we overwrite +- * the fake one... */ +- if (count) +- c = !c; +- laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | +- inode->i_sb->s_blocksize; +- memset(&laarr[c].extLocation, 0x00, +- sizeof(struct kernel_lb_addr)); +- count++; +- } ++ /* ++ * Is there any real extent? - otherwise we overwrite the fake ++ * one... ++ */ ++ if (count) ++ c = !c; ++ laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | ++ inode->i_sb->s_blocksize; ++ memset(&laarr[c].extLocation, 0x00, ++ sizeof(struct kernel_lb_addr)); ++ count++; + endnum = c + 1; + lastblock = 1; + } else { diff --git a/queue-5.4/udf-preserve-link-count-of-system-files.patch b/queue-5.4/udf-preserve-link-count-of-system-files.patch new file mode 100644 index 00000000000..d4405e657e3 --- /dev/null +++ b/queue-5.4/udf-preserve-link-count-of-system-files.patch @@ -0,0 +1,69 @@ +From fc8033a34a3ca7d23353e645e6dde5d364ac5f12 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Tue, 3 Jan 2023 09:56:56 +0100 +Subject: udf: Preserve link count of system files + +From: Jan Kara + +commit fc8033a34a3ca7d23353e645e6dde5d364ac5f12 upstream. + +System files in UDF filesystem have link count 0. To not confuse VFS we +fudge the link count to be 1 when reading such inodes however we forget +to restore the link count of 0 when writing such inodes. Fix that. + +CC: stable@vger.kernel.org +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/inode.c | 9 +++++++-- + fs/udf/super.c | 1 + + fs/udf/udf_i.h | 3 ++- + 3 files changed, 10 insertions(+), 3 deletions(-) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -1388,6 +1388,7 @@ reread: + ret = -EIO; + goto out; + } ++ iinfo->i_hidden = hidden_inode; + iinfo->i_unique = 0; + iinfo->i_lenEAttr = 0; + iinfo->i_lenExtents = 0; +@@ -1723,8 +1724,12 @@ static int udf_update_inode(struct inode + + if (S_ISDIR(inode->i_mode) && inode->i_nlink > 0) + fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1); +- else +- fe->fileLinkCount = cpu_to_le16(inode->i_nlink); ++ else { ++ if (iinfo->i_hidden) ++ fe->fileLinkCount = cpu_to_le16(0); ++ else ++ fe->fileLinkCount = cpu_to_le16(inode->i_nlink); ++ } + + fe->informationLength = cpu_to_le64(inode->i_size); + +--- a/fs/udf/super.c ++++ b/fs/udf/super.c +@@ -147,6 +147,7 @@ static struct inode *udf_alloc_inode(str + ei->i_next_alloc_goal = 0; + ei->i_strat4096 = 0; + ei->i_streamdir = 0; ++ ei->i_hidden = 0; + init_rwsem(&ei->i_data_sem); + ei->cached_extent.lstart = -1; + spin_lock_init(&ei->i_extent_cache_lock); +--- a/fs/udf/udf_i.h ++++ b/fs/udf/udf_i.h +@@ -44,7 +44,8 @@ struct udf_inode_info { + unsigned i_use : 1; /* unallocSpaceEntry */ + unsigned i_strat4096 : 1; + unsigned i_streamdir : 1; +- unsigned reserved : 25; ++ unsigned i_hidden : 1; /* hidden system inode */ ++ unsigned reserved : 24; + union { + struct short_ad *i_sad; + struct long_ad *i_lad; diff --git a/queue-5.4/udf-truncate-added-extents-on-failed-expansion.patch b/queue-5.4/udf-truncate-added-extents-on-failed-expansion.patch new file mode 100644 index 00000000000..c26d25ff798 --- /dev/null +++ b/queue-5.4/udf-truncate-added-extents-on-failed-expansion.patch @@ -0,0 +1,65 @@ +From 70bfb3a8d661d4fdc742afc061b88a7f3fc9f500 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 15 Dec 2022 14:24:03 +0100 +Subject: udf: Truncate added extents on failed expansion + +From: Jan Kara + +commit 70bfb3a8d661d4fdc742afc061b88a7f3fc9f500 upstream. + +When a file expansion failed because we didn't have enough space for +indirect extents make sure we truncate extents created so far so that we +don't leave extents beyond EOF. + +CC: stable@vger.kernel.org +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/inode.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -528,8 +528,10 @@ static int udf_do_extend_file(struct ino + } + + if (fake) { +- udf_add_aext(inode, last_pos, &last_ext->extLocation, +- last_ext->extLength, 1); ++ err = udf_add_aext(inode, last_pos, &last_ext->extLocation, ++ last_ext->extLength, 1); ++ if (err < 0) ++ goto out_err; + count++; + } else { + struct kernel_lb_addr tmploc; +@@ -563,7 +565,7 @@ static int udf_do_extend_file(struct ino + err = udf_add_aext(inode, last_pos, &last_ext->extLocation, + last_ext->extLength, 1); + if (err) +- return err; ++ goto out_err; + count++; + } + if (new_block_bytes) { +@@ -572,7 +574,7 @@ static int udf_do_extend_file(struct ino + err = udf_add_aext(inode, last_pos, &last_ext->extLocation, + last_ext->extLength, 1); + if (err) +- return err; ++ goto out_err; + count++; + } + +@@ -586,6 +588,11 @@ out: + return -EIO; + + return count; ++out_err: ++ /* Remove extents we've created so far */ ++ udf_clear_extent_cache(inode); ++ udf_truncate_extents(inode); ++ return err; + } + + /* Extend the final block of the file to final_block_len bytes */ -- 2.47.3