From 94319e03b91be8e241ca46a8db655ee99c1f1cd3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 6 Mar 2023 14:43:36 +0100 Subject: [PATCH] 6.2-stable patches added patches: exfat-fix-inode-i_blocks-for-non-512-byte-sector-size-device.patch exfat-fix-reporting-fs-error-when-reading-dir-beyond-eof.patch exfat-fix-unexpected-eof-while-reading-dir.patch exfat-redefine-dir_deleted-as-the-bad-cluster-number.patch f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch f2fs-fix-kernel-crash-due-to-null-io-bio.patch f2fs-retry-to-update-the-inode-page-given-data-corruption.patch f2fs-revert-f2fs-truncate-blocks-in-batch-in-__complete_revoke_list.patch fs-cramfs-inode.c-initialize-file_ra_state.patch fs-dlm-be-sure-to-call-dlm_send_queue_flush.patch fs-dlm-don-t-set-stop-rx-flag-after-node-reset.patch fs-dlm-fix-race-setting-stop-tx-flag.patch fs-dlm-fix-use-after-free-in-midcomms-commit.patch fs-dlm-move-sending-fin-message-into-state-change-handling.patch fs-dlm-send-fin-ack-back-in-right-cases.patch fs-dlm-start-midcomms-before-scand.patch fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch md-don-t-update-recovery_cp-when-curr_resync-is-active.patch ocfs2-fix-defrag-path-triggering-jbd2-assert.patch ocfs2-fix-non-auto-defrag-path-not-working-issue.patch selftests-landlock-skip-overlayfs-tests-when-not-supported.patch selftests-landlock-test-ptrace-as-much-as-possible-with-yama.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 --- ...-for-non-512-byte-sector-size-device.patch | 83 +++++++ ...fs-error-when-reading-dir-beyond-eof.patch | 49 ++++ ...fix-unexpected-eof-while-reading-dir.patch | 49 ++++ ...ir_deleted-as-the-bad-cluster-number.patch | 38 ++++ ...-accounting-with-fs-layer-encryption.patch | 63 +++++ ...ion-leak-in-f2fs_move_inline_dirents.patch | 56 +++++ ...-fix-kernel-crash-due-to-null-io-bio.patch | 58 +++++ ...the-inode-page-given-data-corruption.patch | 53 +++++ ...s-in-batch-in-__complete_revoke_list.patch | 51 +++++ ...mfs-inode.c-initialize-file_ra_state.patch | 35 +++ ...be-sure-to-call-dlm_send_queue_flush.patch | 34 +++ ...-t-set-stop-rx-flag-after-node-reset.patch | 47 ++++ ...fs-dlm-fix-race-setting-stop-tx-flag.patch | 45 ++++ ...ix-use-after-free-in-midcomms-commit.patch | 178 +++++++++++++++ ...n-message-into-state-change-handling.patch | 109 +++++++++ ...dlm-send-fin-ack-back-in-right-cases.patch | 70 ++++++ .../fs-dlm-start-midcomms-before-scand.patch | 57 +++++ ...s-fix-uaf-issue-in-hfsplus_put_super.patch | 52 +++++ ...-hfs_bnode_get-in-__hfs_bnode_create.patch | 98 ++++++++ ...covery_cp-when-curr_resync-is-active.patch | 51 +++++ ...x-defrag-path-triggering-jbd2-assert.patch | 100 ++++++++ ...n-auto-defrag-path-not-working-issue.patch | 91 ++++++++ ...p-overlayfs-tests-when-not-supported.patch | 118 ++++++++++ ...ptrace-as-much-as-possible-with-yama.patch | 215 ++++++++++++++++++ queue-6.2/series | 30 +++ ...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 ++++++ 31 files changed, 2181 insertions(+) create mode 100644 queue-6.2/exfat-fix-inode-i_blocks-for-non-512-byte-sector-size-device.patch create mode 100644 queue-6.2/exfat-fix-reporting-fs-error-when-reading-dir-beyond-eof.patch create mode 100644 queue-6.2/exfat-fix-unexpected-eof-while-reading-dir.patch create mode 100644 queue-6.2/exfat-redefine-dir_deleted-as-the-bad-cluster-number.patch create mode 100644 queue-6.2/f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch create mode 100644 queue-6.2/f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch create mode 100644 queue-6.2/f2fs-fix-kernel-crash-due-to-null-io-bio.patch create mode 100644 queue-6.2/f2fs-retry-to-update-the-inode-page-given-data-corruption.patch create mode 100644 queue-6.2/f2fs-revert-f2fs-truncate-blocks-in-batch-in-__complete_revoke_list.patch create mode 100644 queue-6.2/fs-cramfs-inode.c-initialize-file_ra_state.patch create mode 100644 queue-6.2/fs-dlm-be-sure-to-call-dlm_send_queue_flush.patch create mode 100644 queue-6.2/fs-dlm-don-t-set-stop-rx-flag-after-node-reset.patch create mode 100644 queue-6.2/fs-dlm-fix-race-setting-stop-tx-flag.patch create mode 100644 queue-6.2/fs-dlm-fix-use-after-free-in-midcomms-commit.patch create mode 100644 queue-6.2/fs-dlm-move-sending-fin-message-into-state-change-handling.patch create mode 100644 queue-6.2/fs-dlm-send-fin-ack-back-in-right-cases.patch create mode 100644 queue-6.2/fs-dlm-start-midcomms-before-scand.patch create mode 100644 queue-6.2/fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch create mode 100644 queue-6.2/hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch create mode 100644 queue-6.2/md-don-t-update-recovery_cp-when-curr_resync-is-active.patch create mode 100644 queue-6.2/ocfs2-fix-defrag-path-triggering-jbd2-assert.patch create mode 100644 queue-6.2/ocfs2-fix-non-auto-defrag-path-not-working-issue.patch create mode 100644 queue-6.2/selftests-landlock-skip-overlayfs-tests-when-not-supported.patch create mode 100644 queue-6.2/selftests-landlock-test-ptrace-as-much-as-possible-with-yama.patch create mode 100644 queue-6.2/udf-detect-system-inodes-linked-into-directory-hierarchy.patch create mode 100644 queue-6.2/udf-do-not-bother-merging-very-long-extents.patch create mode 100644 queue-6.2/udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch create mode 100644 queue-6.2/udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch create mode 100644 queue-6.2/udf-preserve-link-count-of-system-files.patch create mode 100644 queue-6.2/udf-truncate-added-extents-on-failed-expansion.patch diff --git a/queue-6.2/exfat-fix-inode-i_blocks-for-non-512-byte-sector-size-device.patch b/queue-6.2/exfat-fix-inode-i_blocks-for-non-512-byte-sector-size-device.patch new file mode 100644 index 00000000000..3ef8c3bbff2 --- /dev/null +++ b/queue-6.2/exfat-fix-inode-i_blocks-for-non-512-byte-sector-size-device.patch @@ -0,0 +1,83 @@ +From 39c1ce8eafc0ff64fb9e28536ccc7df6a8e2999d Mon Sep 17 00:00:00 2001 +From: Yuezhang Mo +Date: Wed, 4 Jan 2023 14:37:47 +0800 +Subject: exfat: fix inode->i_blocks for non-512 byte sector size device + +From: Yuezhang Mo + +commit 39c1ce8eafc0ff64fb9e28536ccc7df6a8e2999d upstream. + +inode->i_blocks is not real number of blocks, but 512 byte ones. + +Fixes: 98d917047e8b ("exfat: add file operations") +Cc: stable@vger.kernel.org # v5.7+ +Reported-by: Wang Yugui +Tested-by: Wang Yugui +Signed-off-by: Yuezhang Mo +Reviewed-by: Andy Wu +Signed-off-by: Namjae Jeon +Signed-off-by: Greg Kroah-Hartman +--- + fs/exfat/file.c | 3 +-- + fs/exfat/inode.c | 6 ++---- + fs/exfat/namei.c | 2 +- + fs/exfat/super.c | 3 +-- + 4 files changed, 5 insertions(+), 9 deletions(-) + +--- a/fs/exfat/file.c ++++ b/fs/exfat/file.c +@@ -209,8 +209,7 @@ void exfat_truncate(struct inode *inode) + if (err) + goto write_size; + +- inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> +- inode->i_blkbits; ++ inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> 9; + write_size: + aligned_size = i_size_read(inode); + if (aligned_size & (blocksize - 1)) { +--- a/fs/exfat/inode.c ++++ b/fs/exfat/inode.c +@@ -220,8 +220,7 @@ static int exfat_map_cluster(struct inod + num_clusters += num_to_be_allocated; + *clu = new_clu.dir; + +- inode->i_blocks += +- num_to_be_allocated << sbi->sect_per_clus_bits; ++ inode->i_blocks += EXFAT_CLU_TO_B(num_to_be_allocated, sbi) >> 9; + + /* + * Move *clu pointer along FAT chains (hole care) because the +@@ -576,8 +575,7 @@ static int exfat_fill_inode(struct inode + + exfat_save_attr(inode, info->attr); + +- inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> +- inode->i_blkbits; ++ inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> 9; + inode->i_mtime = info->mtime; + inode->i_ctime = info->mtime; + ei->i_crtime = info->crtime; +--- a/fs/exfat/namei.c ++++ b/fs/exfat/namei.c +@@ -396,7 +396,7 @@ static int exfat_find_empty_entry(struct + ei->i_size_ondisk += sbi->cluster_size; + ei->i_size_aligned += sbi->cluster_size; + ei->flags = p_dir->flags; +- inode->i_blocks += 1 << sbi->sect_per_clus_bits; ++ inode->i_blocks += sbi->cluster_size >> 9; + } + + return dentry; +--- a/fs/exfat/super.c ++++ b/fs/exfat/super.c +@@ -373,8 +373,7 @@ static int exfat_read_root(struct inode + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + +- inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> +- inode->i_blkbits; ++ inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> 9; + ei->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff; + ei->i_size_aligned = i_size_read(inode); + ei->i_size_ondisk = i_size_read(inode); diff --git a/queue-6.2/exfat-fix-reporting-fs-error-when-reading-dir-beyond-eof.patch b/queue-6.2/exfat-fix-reporting-fs-error-when-reading-dir-beyond-eof.patch new file mode 100644 index 00000000000..bd137d41d32 --- /dev/null +++ b/queue-6.2/exfat-fix-reporting-fs-error-when-reading-dir-beyond-eof.patch @@ -0,0 +1,49 @@ +From 706fdcac002316893434d753be8cfb549fe1d40d Mon Sep 17 00:00:00 2001 +From: Yuezhang Mo +Date: Thu, 20 Oct 2022 14:27:37 +0800 +Subject: exfat: fix reporting fs error when reading dir beyond EOF + +From: Yuezhang Mo + +commit 706fdcac002316893434d753be8cfb549fe1d40d upstream. + +Since seekdir() does not check whether the position is valid, the +position may exceed the size of the directory. We found that for +a directory with discontinuous clusters, if the position exceeds +the size of the directory and the excess size is greater than or +equal to the cluster size, exfat_readdir() will return -EIO, +causing a file system error and making the file system unavailable. + +Reproduce this bug by: + +seekdir(dir, dir_size + cluster_size); +dirent = readdir(dir); + +The following log will be printed if mount with 'errors=remount-ro'. + +[11166.712896] exFAT-fs (sdb1): error, invalid access to FAT (entry 0xffffffff) +[11166.712905] exFAT-fs (sdb1): Filesystem has been set read-only + +Fixes: 1e5654de0f51 ("exfat: handle wrong stream entry size in exfat_readdir()") +Cc: stable@vger.kernel.org # v5.7+ +Signed-off-by: Yuezhang Mo +Reviewed-by: Andy Wu +Reviewed-by: Aoyama Wataru +Reviewed-by: Sungjong Seo +Signed-off-by: Namjae Jeon +Signed-off-by: Greg Kroah-Hartman +--- + fs/exfat/dir.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/exfat/dir.c ++++ b/fs/exfat/dir.c +@@ -100,7 +100,7 @@ static int exfat_readdir(struct inode *i + clu.dir = ei->hint_bmap.clu; + } + +- while (clu_offset > 0) { ++ while (clu_offset > 0 && clu.dir != EXFAT_EOF_CLUSTER) { + if (exfat_get_next_cluster(sb, &(clu.dir))) + return -EIO; + diff --git a/queue-6.2/exfat-fix-unexpected-eof-while-reading-dir.patch b/queue-6.2/exfat-fix-unexpected-eof-while-reading-dir.patch new file mode 100644 index 00000000000..d346ea3d299 --- /dev/null +++ b/queue-6.2/exfat-fix-unexpected-eof-while-reading-dir.patch @@ -0,0 +1,49 @@ +From 6cb5d1a16a51d080fbc1649a5144cbc5ca7d6f88 Mon Sep 17 00:00:00 2001 +From: Yuezhang Mo +Date: Thu, 22 Sep 2022 14:43:47 +0800 +Subject: exfat: fix unexpected EOF while reading dir + +From: Yuezhang Mo + +commit 6cb5d1a16a51d080fbc1649a5144cbc5ca7d6f88 upstream. + +If the position is not aligned with the dentry size, the return +value of readdir() will be NULL and errno is 0, which means the +end of the directory stream is reached. + +If the position is aligned with dentry size, but there is no file +or directory at the position, exfat_readdir() will continue to +get dentry from the next dentry. So the dentry gotten by readdir() +may not be at the position. + +After this commit, if the position is not aligned with the dentry +size, round the position up to the dentry size and continue to get +the dentry. + +Fixes: ca06197382bd ("exfat: add directory operations") +Cc: stable@vger.kernel.org # v5.7+ +Reported-by: Wang Yugui +Signed-off-by: Yuezhang Mo +Reviewed-by: Andy Wu +Reviewed-by: Aoyama Wataru +Reviewed-by: Sungjong Seo +Signed-off-by: Namjae Jeon +Signed-off-by: Greg Kroah-Hartman +--- + fs/exfat/dir.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/fs/exfat/dir.c ++++ b/fs/exfat/dir.c +@@ -234,10 +234,7 @@ static int exfat_iterate(struct file *fi + fake_offset = 1; + } + +- if (cpos & (DENTRY_SIZE - 1)) { +- err = -ENOENT; +- goto unlock; +- } ++ cpos = round_up(cpos, DENTRY_SIZE); + + /* name buffer should be allocated before use */ + err = exfat_alloc_namebuf(nb); diff --git a/queue-6.2/exfat-redefine-dir_deleted-as-the-bad-cluster-number.patch b/queue-6.2/exfat-redefine-dir_deleted-as-the-bad-cluster-number.patch new file mode 100644 index 00000000000..f0c21479fce --- /dev/null +++ b/queue-6.2/exfat-redefine-dir_deleted-as-the-bad-cluster-number.patch @@ -0,0 +1,38 @@ +From bdaadfd343e3cba49ad0b009ff4b148dad0fa404 Mon Sep 17 00:00:00 2001 +From: Sungjong Seo +Date: Thu, 29 Dec 2022 20:52:38 +0900 +Subject: exfat: redefine DIR_DELETED as the bad cluster number + +From: Sungjong Seo + +commit bdaadfd343e3cba49ad0b009ff4b148dad0fa404 upstream. + +When a file or a directory is deleted, the hint for the cluster of +its parent directory in its in-memory inode is set as DIR_DELETED. +Therefore, DIR_DELETED must be one of invalid cluster numbers. According +to the exFAT specification, a volume can have at most 2^32-11 clusters. +However, DIR_DELETED is wrongly defined as 0xFFFF0321, which could be +a valid cluster number. To fix it, let's redefine DIR_DELETED as +0xFFFFFFF7, the bad cluster number. + +Fixes: 1acf1a564b60 ("exfat: add in-memory and on-disk structures and headers") +Cc: stable@vger.kernel.org # v5.7+ +Reported-by: Yuezhang Mo +Signed-off-by: Sungjong Seo +Signed-off-by: Namjae Jeon +Signed-off-by: Greg Kroah-Hartman +--- + fs/exfat/exfat_fs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/exfat/exfat_fs.h ++++ b/fs/exfat/exfat_fs.h +@@ -50,7 +50,7 @@ enum { + #define ES_IDX_LAST_FILENAME(name_len) \ + (ES_IDX_FIRST_FILENAME + EXFAT_FILENAME_ENTRY_NUM(name_len) - 1) + +-#define DIR_DELETED 0xFFFF0321 ++#define DIR_DELETED 0xFFFFFFF7 + + /* type values */ + #define TYPE_UNUSED 0x0000 diff --git a/queue-6.2/f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch b/queue-6.2/f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch new file mode 100644 index 00000000000..5281c9079f4 --- /dev/null +++ b/queue-6.2/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 +@@ -741,7 +741,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); + + inc_page_count(fio->sbi, is_read_io(fio->op) ? + __read_io_type(page) : WB_DATA_TYPE(fio->page)); +@@ -948,7 +948,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)); + +@@ -1022,7 +1022,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; + diff --git a/queue-6.2/f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch b/queue-6.2/f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch new file mode 100644 index 00000000000..4e1f9a404de --- /dev/null +++ b/queue-6.2/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 +@@ -422,18 +422,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-6.2/f2fs-fix-kernel-crash-due-to-null-io-bio.patch b/queue-6.2/f2fs-fix-kernel-crash-due-to-null-io-bio.patch new file mode 100644 index 00000000000..6842fa1f40b --- /dev/null +++ b/queue-6.2/f2fs-fix-kernel-crash-due-to-null-io-bio.patch @@ -0,0 +1,58 @@ +From 267c159f9c7bcb7009dae16889b880c5ed8759a8 Mon Sep 17 00:00:00 2001 +From: Jaegeuk Kim +Date: Sun, 5 Feb 2023 19:13:39 -0800 +Subject: f2fs: fix kernel crash due to null io->bio + +From: Jaegeuk Kim + +commit 267c159f9c7bcb7009dae16889b880c5ed8759a8 upstream. + +We should return when io->bio is null before doing anything. Otherwise, panic. + +BUG: kernel NULL pointer dereference, address: 0000000000000010 +RIP: 0010:__submit_merged_write_cond+0x164/0x240 [f2fs] +Call Trace: + + f2fs_submit_merged_write+0x1d/0x30 [f2fs] + commit_checkpoint+0x110/0x1e0 [f2fs] + f2fs_write_checkpoint+0x9f7/0xf00 [f2fs] + ? __pfx_issue_checkpoint_thread+0x10/0x10 [f2fs] + __checkpoint_and_complete_reqs+0x84/0x190 [f2fs] + ? preempt_count_add+0x82/0xc0 + ? __pfx_issue_checkpoint_thread+0x10/0x10 [f2fs] + issue_checkpoint_thread+0x4c/0xf0 [f2fs] + ? __pfx_autoremove_wake_function+0x10/0x10 + kthread+0xff/0x130 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x2c/0x50 + + +Cc: stable@vger.kernel.org # v5.18+ +Fixes: 64bf0eef0171 ("f2fs: pass the bio operation to bio_alloc_bioset") +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/data.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -655,6 +655,9 @@ static void __f2fs_submit_merged_write(s + + f2fs_down_write(&io->io_rwsem); + ++ if (!io->bio) ++ goto unlock_out; ++ + /* change META to META_FLUSH in the checkpoint procedure */ + if (type >= META_FLUSH) { + io->fio.type = META_FLUSH; +@@ -663,6 +666,7 @@ static void __f2fs_submit_merged_write(s + io->bio->bi_opf |= REQ_PREFLUSH | REQ_FUA; + } + __submit_merged_bio(io); ++unlock_out: + f2fs_up_write(&io->io_rwsem); + } + diff --git a/queue-6.2/f2fs-retry-to-update-the-inode-page-given-data-corruption.patch b/queue-6.2/f2fs-retry-to-update-the-inode-page-given-data-corruption.patch new file mode 100644 index 00000000000..140444ac1cb --- /dev/null +++ b/queue-6.2/f2fs-retry-to-update-the-inode-page-given-data-corruption.patch @@ -0,0 +1,53 @@ +From 3aa51c61cb4a4dcb40df51ac61171e9ac5a35321 Mon Sep 17 00:00:00 2001 +From: Jaegeuk Kim +Date: Mon, 30 Jan 2023 15:20:09 -0800 +Subject: f2fs: retry to update the inode page given data corruption + +From: Jaegeuk Kim + +commit 3aa51c61cb4a4dcb40df51ac61171e9ac5a35321 upstream. + +If the storage gives a corrupted node block due to short power failure and +reset, f2fs stops the entire operations by setting the checkpoint failure flag. + +Let's give more chances to live by re-issuing IOs for a while in such critical +path. + +Cc: stable@vger.kernel.org +Suggested-by: Randall Huang +Suggested-by: Chao Yu +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/inode.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -714,18 +714,19 @@ void f2fs_update_inode_page(struct inode + { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct page *node_page; ++ int count = 0; + retry: + node_page = f2fs_get_node_page(sbi, inode->i_ino); + if (IS_ERR(node_page)) { + int err = PTR_ERR(node_page); + +- if (err == -ENOMEM) { +- cond_resched(); ++ /* The node block was truncated. */ ++ if (err == -ENOENT) ++ return; ++ ++ if (err == -ENOMEM || ++count <= DEFAULT_RETRY_IO_COUNT) + goto retry; +- } else if (err != -ENOENT) { +- f2fs_stop_checkpoint(sbi, false, +- STOP_CP_REASON_UPDATE_INODE); +- } ++ f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_UPDATE_INODE); + return; + } + f2fs_update_inode(inode, node_page); diff --git a/queue-6.2/f2fs-revert-f2fs-truncate-blocks-in-batch-in-__complete_revoke_list.patch b/queue-6.2/f2fs-revert-f2fs-truncate-blocks-in-batch-in-__complete_revoke_list.patch new file mode 100644 index 00000000000..ff0e9fc7a87 --- /dev/null +++ b/queue-6.2/f2fs-revert-f2fs-truncate-blocks-in-batch-in-__complete_revoke_list.patch @@ -0,0 +1,51 @@ +From c7dbc06688292db34c1bb9c715e29ac4935af994 Mon Sep 17 00:00:00 2001 +From: Jaegeuk Kim +Date: Tue, 14 Feb 2023 15:53:52 -0800 +Subject: f2fs: Revert "f2fs: truncate blocks in batch in __complete_revoke_list()" + +From: Jaegeuk Kim + +commit c7dbc06688292db34c1bb9c715e29ac4935af994 upstream. + +We should not truncate replaced blocks, and were supposed to truncate the first +part as well. + +This reverts commit 78a99fe6254cad4be310cd84af39f6c46b668c72. + +Cc: stable@vger.kernel.org +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/segment.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -262,19 +262,24 @@ static void __complete_revoke_list(struc + bool revoke) + { + struct revoke_entry *cur, *tmp; ++ pgoff_t start_index = 0; + bool truncate = is_inode_flag_set(inode, FI_ATOMIC_REPLACE); + + list_for_each_entry_safe(cur, tmp, head, list) { +- if (revoke) ++ if (revoke) { + __replace_atomic_write_block(inode, cur->index, + cur->old_addr, NULL, true); ++ } else if (truncate) { ++ f2fs_truncate_hole(inode, start_index, cur->index); ++ start_index = cur->index + 1; ++ } + + list_del(&cur->list); + kmem_cache_free(revoke_entry_slab, cur); + } + + if (!revoke && truncate) +- f2fs_do_truncate_blocks(inode, 0, false); ++ f2fs_do_truncate_blocks(inode, start_index * PAGE_SIZE, false); + } + + static int __f2fs_commit_atomic_write(struct inode *inode) diff --git a/queue-6.2/fs-cramfs-inode.c-initialize-file_ra_state.patch b/queue-6.2/fs-cramfs-inode.c-initialize-file_ra_state.patch new file mode 100644 index 00000000000..4e309464346 --- /dev/null +++ b/queue-6.2/fs-cramfs-inode.c-initialize-file_ra_state.patch @@ -0,0 +1,35 @@ +From 3e35102666f873a135d31a726ac1ec8af4905206 Mon Sep 17 00:00:00 2001 +From: Andrew Morton +Date: Sun, 26 Feb 2023 12:31:11 -0800 +Subject: fs/cramfs/inode.c: initialize file_ra_state + +From: Andrew Morton + +commit 3e35102666f873a135d31a726ac1ec8af4905206 upstream. + +file_ra_state_init() assumes that the file_ra_state has been zeroed out. +Fixes a KMSAN used-unintialized issue (at least). + +Fixes: cf948cbc35e80 ("cramfs: read_mapping_page() is synchronous") +Reported-by: syzbot + Link: https://lkml.kernel.org/r/0000000000008f74e905f56df987@google.com +Cc: Matthew Wilcox +Cc: Nicolas Pitre +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/cramfs/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/cramfs/inode.c ++++ b/fs/cramfs/inode.c +@@ -183,7 +183,7 @@ static void *cramfs_blkdev_read(struct s + unsigned int len) + { + struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping; +- struct file_ra_state ra; ++ struct file_ra_state ra = {}; + struct page *pages[BLKS_PER_BUF]; + unsigned i, blocknr, buffer; + unsigned long devsize; diff --git a/queue-6.2/fs-dlm-be-sure-to-call-dlm_send_queue_flush.patch b/queue-6.2/fs-dlm-be-sure-to-call-dlm_send_queue_flush.patch new file mode 100644 index 00000000000..971757c5c0d --- /dev/null +++ b/queue-6.2/fs-dlm-be-sure-to-call-dlm_send_queue_flush.patch @@ -0,0 +1,34 @@ +From 7354fa4ef697191effedc2ae9a8293427708bbf5 Mon Sep 17 00:00:00 2001 +From: Alexander Aring +Date: Thu, 12 Jan 2023 17:10:33 -0500 +Subject: fs: dlm: be sure to call dlm_send_queue_flush() + +From: Alexander Aring + +commit 7354fa4ef697191effedc2ae9a8293427708bbf5 upstream. + +If we release a midcomms node structure, there should be nothing left +inside the dlm midcomms send queue. However, sometimes this is not true +because I believe some DLM_FIN message was not acked... if we run +into a shutdown timeout, then we should be sure there is no pending send +dlm message inside this queue when releasing midcomms node structure. + +Cc: stable@vger.kernel.org +Fixes: 489d8e559c65 ("fs: dlm: add reliable connection if reconnect") +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Greg Kroah-Hartman +--- + fs/dlm/midcomms.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/dlm/midcomms.c ++++ b/fs/dlm/midcomms.c +@@ -1402,6 +1402,7 @@ static void midcomms_node_release(struct + struct midcomms_node *node = container_of(rcu, struct midcomms_node, rcu); + + WARN_ON_ONCE(atomic_read(&node->send_queue_cnt)); ++ dlm_send_queue_flush(node); + kfree(node); + } + diff --git a/queue-6.2/fs-dlm-don-t-set-stop-rx-flag-after-node-reset.patch b/queue-6.2/fs-dlm-don-t-set-stop-rx-flag-after-node-reset.patch new file mode 100644 index 00000000000..926bbb78bbe --- /dev/null +++ b/queue-6.2/fs-dlm-don-t-set-stop-rx-flag-after-node-reset.patch @@ -0,0 +1,47 @@ +From 15c63db8e86a72e0d5cfb9bf0cd1870e39a3e5fe Mon Sep 17 00:00:00 2001 +From: Alexander Aring +Date: Thu, 12 Jan 2023 17:10:35 -0500 +Subject: fs: dlm: don't set stop rx flag after node reset + +From: Alexander Aring + +commit 15c63db8e86a72e0d5cfb9bf0cd1870e39a3e5fe upstream. + +Similar to the stop tx flag, the rx flag should warn about a dlm message +being received at DLM_FIN state change, when we are assuming no other +dlm application messages. If we receive a FIN message and we are in the +state DLM_FIN_WAIT2 we call midcomms_node_reset() which puts the +midcomms node into DLM_CLOSED state. Afterwards we should not set the +DLM_NODE_FLAG_STOP_RX flag any more. This patch changes the setting +DLM_NODE_FLAG_STOP_RX in those state changes when we receive a FIN +message and we assume there will be no other dlm application messages +received until we hit DLM_CLOSED state. + +Cc: stable@vger.kernel.org +Fixes: 489d8e559c65 ("fs: dlm: add reliable connection if reconnect") +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Greg Kroah-Hartman +--- + fs/dlm/midcomms.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/fs/dlm/midcomms.c ++++ b/fs/dlm/midcomms.c +@@ -524,6 +524,7 @@ static void dlm_midcomms_receive_buffer( + break; + case DLM_FIN_WAIT1: + node->state = DLM_CLOSING; ++ set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags); + pr_debug("switch node %d to state %s\n", + node->nodeid, dlm_state_str(node->state)); + break; +@@ -544,8 +545,6 @@ static void dlm_midcomms_receive_buffer( + return; + } + spin_unlock(&node->state_lock); +- +- set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags); + break; + default: + WARN_ON_ONCE(test_bit(DLM_NODE_FLAG_STOP_RX, &node->flags)); diff --git a/queue-6.2/fs-dlm-fix-race-setting-stop-tx-flag.patch b/queue-6.2/fs-dlm-fix-race-setting-stop-tx-flag.patch new file mode 100644 index 00000000000..37f3edd0060 --- /dev/null +++ b/queue-6.2/fs-dlm-fix-race-setting-stop-tx-flag.patch @@ -0,0 +1,45 @@ +From 164272113b685927126c938b4a9cbd2075eb15ee Mon Sep 17 00:00:00 2001 +From: Alexander Aring +Date: Thu, 12 Jan 2023 17:10:34 -0500 +Subject: fs: dlm: fix race setting stop tx flag + +From: Alexander Aring + +commit 164272113b685927126c938b4a9cbd2075eb15ee upstream. + +This patch sets the stop tx flag before we commit the dlm message. +This flag will report about unexpected transmissions after we +send the DLM_FIN message out, which should be the last message sent. +When we commit the dlm fin message, it could be that we already +got an ack back and the CLOSED state change already happened. +We should not set this flag when we are in CLOSED state. To avoid this +race we simply set the tx flag before the state change can be in +progress by moving it before dlm_midcomms_commit_mhandle(). + +Cc: stable@vger.kernel.org +Fixes: 489d8e559c65 ("fs: dlm: add reliable connection if reconnect") +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Greg Kroah-Hartman +--- + fs/dlm/midcomms.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/dlm/midcomms.c ++++ b/fs/dlm/midcomms.c +@@ -406,6 +406,7 @@ static int dlm_send_fin(struct midcomms_ + if (!mh) + return -ENOMEM; + ++ set_bit(DLM_NODE_FLAG_STOP_TX, &node->flags); + mh->ack_rcv = ack_rcv; + + m_header = (struct dlm_header *)ppc; +@@ -417,7 +418,6 @@ static int dlm_send_fin(struct midcomms_ + + pr_debug("sending fin msg to node %d\n", node->nodeid); + dlm_midcomms_commit_mhandle(mh, NULL, 0); +- set_bit(DLM_NODE_FLAG_STOP_TX, &node->flags); + + return 0; + } diff --git a/queue-6.2/fs-dlm-fix-use-after-free-in-midcomms-commit.patch b/queue-6.2/fs-dlm-fix-use-after-free-in-midcomms-commit.patch new file mode 100644 index 00000000000..93eb519db30 --- /dev/null +++ b/queue-6.2/fs-dlm-fix-use-after-free-in-midcomms-commit.patch @@ -0,0 +1,178 @@ +From 724b6bab0d75f1dc01fdfbf7fe8d4217a5cb90ba Mon Sep 17 00:00:00 2001 +From: Alexander Aring +Date: Thu, 12 Jan 2023 17:10:32 -0500 +Subject: fs: dlm: fix use after free in midcomms commit + +From: Alexander Aring + +commit 724b6bab0d75f1dc01fdfbf7fe8d4217a5cb90ba upstream. + +While working on processing dlm message in softirq context I experienced +the following KASAN use-after-free warning: + +[ 151.760477] ================================================================== +[ 151.761803] BUG: KASAN: use-after-free in dlm_midcomms_commit_mhandle+0x19d/0x4b0 +[ 151.763414] Read of size 4 at addr ffff88811a980c60 by task lock_torture/1347 + +[ 151.765284] CPU: 7 PID: 1347 Comm: lock_torture Not tainted 6.1.0-rc4+ #2828 +[ 151.766778] Hardware name: Red Hat KVM/RHEL-AV, BIOS 1.16.0-3.module+el8.7.0+16134+e5908aa2 04/01/2014 +[ 151.768726] Call Trace: +[ 151.769277] +[ 151.769748] dump_stack_lvl+0x5b/0x86 +[ 151.770556] print_report+0x180/0x4c8 +[ 151.771378] ? kasan_complete_mode_report_info+0x7c/0x1e0 +[ 151.772241] ? dlm_midcomms_commit_mhandle+0x19d/0x4b0 +[ 151.773069] kasan_report+0x93/0x1a0 +[ 151.773668] ? dlm_midcomms_commit_mhandle+0x19d/0x4b0 +[ 151.774514] __asan_load4+0x7e/0xa0 +[ 151.775089] dlm_midcomms_commit_mhandle+0x19d/0x4b0 +[ 151.775890] ? create_message.isra.29.constprop.64+0x57/0xc0 +[ 151.776770] send_common+0x19f/0x1b0 +[ 151.777342] ? remove_from_waiters+0x60/0x60 +[ 151.778017] ? lock_downgrade+0x410/0x410 +[ 151.778648] ? __this_cpu_preempt_check+0x13/0x20 +[ 151.779421] ? rcu_lockdep_current_cpu_online+0x88/0xc0 +[ 151.780292] _convert_lock+0x46/0x150 +[ 151.780893] convert_lock+0x7b/0xc0 +[ 151.781459] dlm_lock+0x3ac/0x580 +[ 151.781993] ? 0xffffffffc0540000 +[ 151.782522] ? torture_stop+0x120/0x120 [dlm_locktorture] +[ 151.783379] ? dlm_scan_rsbs+0xa70/0xa70 +[ 151.784003] ? preempt_count_sub+0xd6/0x130 +[ 151.784661] ? is_module_address+0x47/0x70 +[ 151.785309] ? torture_stop+0x120/0x120 [dlm_locktorture] +[ 151.786166] ? 0xffffffffc0540000 +[ 151.786693] ? lockdep_init_map_type+0xc3/0x360 +[ 151.787414] ? 0xffffffffc0540000 +[ 151.787947] torture_dlm_lock_sync.isra.3+0xe9/0x150 [dlm_locktorture] +[ 151.789004] ? torture_stop+0x120/0x120 [dlm_locktorture] +[ 151.789858] ? 0xffffffffc0540000 +[ 151.790392] ? lock_torture_cleanup+0x20/0x20 [dlm_locktorture] +[ 151.791347] ? delay_tsc+0x94/0xc0 +[ 151.791898] torture_ex_iter+0xc3/0xea [dlm_locktorture] +[ 151.792735] ? torture_start+0x30/0x30 [dlm_locktorture] +[ 151.793606] lock_torture+0x177/0x270 [dlm_locktorture] +[ 151.794448] ? torture_dlm_lock_sync.isra.3+0x150/0x150 [dlm_locktorture] +[ 151.795539] ? lock_torture_stats+0x80/0x80 [dlm_locktorture] +[ 151.796476] ? do_raw_spin_lock+0x11e/0x1e0 +[ 151.797152] ? mark_held_locks+0x34/0xb0 +[ 151.797784] ? _raw_spin_unlock_irqrestore+0x30/0x70 +[ 151.798581] ? __kthread_parkme+0x79/0x110 +[ 151.799246] ? trace_preempt_on+0x2a/0xf0 +[ 151.799902] ? __kthread_parkme+0x79/0x110 +[ 151.800579] ? preempt_count_sub+0xd6/0x130 +[ 151.801271] ? __kasan_check_read+0x11/0x20 +[ 151.801963] ? __kthread_parkme+0xec/0x110 +[ 151.802630] ? lock_torture_stats+0x80/0x80 [dlm_locktorture] +[ 151.803569] kthread+0x192/0x1d0 +[ 151.804104] ? kthread_complete_and_exit+0x30/0x30 +[ 151.804881] ret_from_fork+0x1f/0x30 +[ 151.805480] + +[ 151.806111] Allocated by task 1347: +[ 151.806681] kasan_save_stack+0x26/0x50 +[ 151.807308] kasan_set_track+0x25/0x30 +[ 151.807920] kasan_save_alloc_info+0x1e/0x30 +[ 151.808609] __kasan_slab_alloc+0x63/0x80 +[ 151.809263] kmem_cache_alloc+0x1ad/0x830 +[ 151.809916] dlm_allocate_mhandle+0x17/0x20 +[ 151.810590] dlm_midcomms_get_mhandle+0x96/0x260 +[ 151.811344] _create_message+0x95/0x180 +[ 151.811994] create_message.isra.29.constprop.64+0x57/0xc0 +[ 151.812880] send_common+0x129/0x1b0 +[ 151.813467] _convert_lock+0x46/0x150 +[ 151.814074] convert_lock+0x7b/0xc0 +[ 151.814648] dlm_lock+0x3ac/0x580 +[ 151.815199] torture_dlm_lock_sync.isra.3+0xe9/0x150 [dlm_locktorture] +[ 151.816258] torture_ex_iter+0xc3/0xea [dlm_locktorture] +[ 151.817129] lock_torture+0x177/0x270 [dlm_locktorture] +[ 151.817986] kthread+0x192/0x1d0 +[ 151.818518] ret_from_fork+0x1f/0x30 + +[ 151.819369] Freed by task 1336: +[ 151.819890] kasan_save_stack+0x26/0x50 +[ 151.820514] kasan_set_track+0x25/0x30 +[ 151.821128] kasan_save_free_info+0x2e/0x50 +[ 151.821812] __kasan_slab_free+0x107/0x1a0 +[ 151.822483] kmem_cache_free+0x204/0x5e0 +[ 151.823152] dlm_free_mhandle+0x18/0x20 +[ 151.823781] dlm_mhandle_release+0x2e/0x40 +[ 151.824454] rcu_core+0x583/0x1330 +[ 151.825047] rcu_core_si+0xe/0x20 +[ 151.825594] __do_softirq+0xf4/0x5c2 + +[ 151.826450] Last potentially related work creation: +[ 151.827238] kasan_save_stack+0x26/0x50 +[ 151.827870] __kasan_record_aux_stack+0xa2/0xc0 +[ 151.828609] kasan_record_aux_stack_noalloc+0xb/0x20 +[ 151.829415] call_rcu+0x4c/0x760 +[ 151.829954] dlm_mhandle_delete+0x97/0xb0 +[ 151.830718] dlm_process_incoming_buffer+0x2fc/0xb30 +[ 151.831524] process_dlm_messages+0x16e/0x470 +[ 151.832245] process_one_work+0x505/0xa10 +[ 151.832905] worker_thread+0x67/0x650 +[ 151.833507] kthread+0x192/0x1d0 +[ 151.834046] ret_from_fork+0x1f/0x30 + +[ 151.834900] The buggy address belongs to the object at ffff88811a980c30 + which belongs to the cache dlm_mhandle of size 88 +[ 151.836894] The buggy address is located 48 bytes inside of + 88-byte region [ffff88811a980c30, ffff88811a980c88) + +[ 151.839007] The buggy address belongs to the physical page: +[ 151.839904] page:0000000076cf5d62 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x11a980 +[ 151.841378] flags: 0x8000000000000200(slab|zone=2) +[ 151.842141] raw: 8000000000000200 0000000000000000 dead000000000122 ffff8881089b43c0 +[ 151.843401] raw: 0000000000000000 0000000000220022 00000001ffffffff 0000000000000000 +[ 151.844640] page dumped because: kasan: bad access detected + +[ 151.845822] Memory state around the buggy address: +[ 151.846602] ffff88811a980b00: fb fb fb fb fc fc fc fc fa fb fb fb fb fb fb fb +[ 151.847761] ffff88811a980b80: fb fb fb fc fc fc fc fa fb fb fb fb fb fb fb fb +[ 151.848921] >ffff88811a980c00: fb fb fc fc fc fc fa fb fb fb fb fb fb fb fb fb +[ 151.850076] ^ +[ 151.851085] ffff88811a980c80: fb fc fc fc fc fa fb fb fb fb fb fb fb fb fb fb +[ 151.852269] ffff88811a980d00: fc fc fc fc fa fb fb fb fb fb fb fb fb fb fb fc +[ 151.853428] ================================================================== +[ 151.855618] Disabling lock debugging due to kernel taint + +It is accessing a mhandle in dlm_midcomms_commit_mhandle() and the mhandle +was freed by a call_rcu() call in dlm_process_incoming_buffer(), +dlm_mhandle_delete(). It looks like it was freed because an ack of +this message was received. There is a short race between committing the +dlm message to be transmitted and getting an ack back. If the ack is +faster than returning from dlm_midcomms_commit_msg_3_2(), then we run +into a use-after free because we still need to reference the mhandle when +calling srcu_read_unlock(). + +To avoid that, we don't allow that mhandle to be freed between +dlm_midcomms_commit_msg_3_2() and srcu_read_unlock() by using rcu read +lock. We can do that because mhandle is protected by rcu handling. + +Cc: stable@vger.kernel.org +Fixes: 489d8e559c65 ("fs: dlm: add reliable connection if reconnect") +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Greg Kroah-Hartman +--- + fs/dlm/midcomms.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/fs/dlm/midcomms.c ++++ b/fs/dlm/midcomms.c +@@ -1214,8 +1214,15 @@ void dlm_midcomms_commit_mhandle(struct + dlm_free_mhandle(mh); + break; + case DLM_VERSION_3_2: ++ /* held rcu read lock here, because we sending the ++ * dlm message out, when we do that we could receive ++ * an ack back which releases the mhandle and we ++ * get a use after free. ++ */ ++ rcu_read_lock(); + dlm_midcomms_commit_msg_3_2(mh, name, namelen); + srcu_read_unlock(&nodes_srcu, mh->idx); ++ rcu_read_unlock(); + break; + default: + srcu_read_unlock(&nodes_srcu, mh->idx); diff --git a/queue-6.2/fs-dlm-move-sending-fin-message-into-state-change-handling.patch b/queue-6.2/fs-dlm-move-sending-fin-message-into-state-change-handling.patch new file mode 100644 index 00000000000..495ba5c4d91 --- /dev/null +++ b/queue-6.2/fs-dlm-move-sending-fin-message-into-state-change-handling.patch @@ -0,0 +1,109 @@ +From a58496361802070996f9bd76e941d109c4a85ebd Mon Sep 17 00:00:00 2001 +From: Alexander Aring +Date: Thu, 12 Jan 2023 17:10:36 -0500 +Subject: fs: dlm: move sending fin message into state change handling + +From: Alexander Aring + +commit a58496361802070996f9bd76e941d109c4a85ebd upstream. + +This patch moves the send fin handling, which should appear in a specific +state change, into the state change handling while the per node +state_lock is held. I experienced issues with other messages because +we changed the state and a fin message was sent out in a different state. + +Cc: stable@vger.kernel.org +Fixes: 489d8e559c65 ("fs: dlm: add reliable connection if reconnect") +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Greg Kroah-Hartman +--- + fs/dlm/midcomms.c | 33 +++++++++------------------------ + 1 file changed, 9 insertions(+), 24 deletions(-) + +--- a/fs/dlm/midcomms.c ++++ b/fs/dlm/midcomms.c +@@ -402,7 +402,7 @@ static int dlm_send_fin(struct midcomms_ + struct dlm_mhandle *mh; + char *ppc; + +- mh = dlm_midcomms_get_mhandle(node->nodeid, mb_len, GFP_NOFS, &ppc); ++ mh = dlm_midcomms_get_mhandle(node->nodeid, mb_len, GFP_ATOMIC, &ppc); + if (!mh) + return -ENOMEM; + +@@ -518,8 +518,8 @@ static void dlm_midcomms_receive_buffer( + node->state = DLM_LAST_ACK; + pr_debug("switch node %d to state %s case 1\n", + node->nodeid, dlm_state_str(node->state)); +- spin_unlock(&node->state_lock); +- goto send_fin; ++ set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags); ++ dlm_send_fin(node, dlm_pas_fin_ack_rcv); + } + break; + case DLM_FIN_WAIT1: +@@ -563,12 +563,6 @@ static void dlm_midcomms_receive_buffer( + log_print_ratelimited("ignore dlm msg because seq mismatch, seq: %u, expected: %u, nodeid: %d", + seq, node->seq_next, node->nodeid); + } +- +- return; +- +-send_fin: +- set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags); +- dlm_send_fin(node, dlm_pas_fin_ack_rcv); + } + + static struct midcomms_node * +@@ -1368,11 +1362,11 @@ void dlm_midcomms_remove_member(int node + case DLM_CLOSE_WAIT: + /* passive shutdown DLM_LAST_ACK case 2 */ + node->state = DLM_LAST_ACK; +- spin_unlock(&node->state_lock); +- + pr_debug("switch node %d to state %s case 2\n", + node->nodeid, dlm_state_str(node->state)); +- goto send_fin; ++ set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags); ++ dlm_send_fin(node, dlm_pas_fin_ack_rcv); ++ break; + case DLM_LAST_ACK: + /* probably receive fin caught it, do nothing */ + break; +@@ -1388,12 +1382,6 @@ void dlm_midcomms_remove_member(int node + spin_unlock(&node->state_lock); + + srcu_read_unlock(&nodes_srcu, idx); +- return; +- +-send_fin: +- set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags); +- dlm_send_fin(node, dlm_pas_fin_ack_rcv); +- srcu_read_unlock(&nodes_srcu, idx); + } + + static void midcomms_node_release(struct rcu_head *rcu) +@@ -1425,6 +1413,7 @@ static void midcomms_shutdown(struct mid + node->state = DLM_FIN_WAIT1; + pr_debug("switch node %d to state %s case 2\n", + node->nodeid, dlm_state_str(node->state)); ++ dlm_send_fin(node, dlm_act_fin_ack_rcv); + break; + case DLM_CLOSED: + /* we have what we want */ +@@ -1438,12 +1427,8 @@ static void midcomms_shutdown(struct mid + } + spin_unlock(&node->state_lock); + +- if (node->state == DLM_FIN_WAIT1) { +- dlm_send_fin(node, dlm_act_fin_ack_rcv); +- +- if (DLM_DEBUG_FENCE_TERMINATION) +- msleep(5000); +- } ++ if (DLM_DEBUG_FENCE_TERMINATION) ++ msleep(5000); + + /* wait for other side dlm + fin */ + ret = wait_event_timeout(node->shutdown_wait, diff --git a/queue-6.2/fs-dlm-send-fin-ack-back-in-right-cases.patch b/queue-6.2/fs-dlm-send-fin-ack-back-in-right-cases.patch new file mode 100644 index 00000000000..1bffd8571c1 --- /dev/null +++ b/queue-6.2/fs-dlm-send-fin-ack-back-in-right-cases.patch @@ -0,0 +1,70 @@ +From 00908b3388255fc1d3782b744d07f327712f401f Mon Sep 17 00:00:00 2001 +From: Alexander Aring +Date: Thu, 12 Jan 2023 17:10:37 -0500 +Subject: fs: dlm: send FIN ack back in right cases + +From: Alexander Aring + +commit 00908b3388255fc1d3782b744d07f327712f401f upstream. + +This patch moves to send a ack back for receiving a FIN message only +when we are in valid states. In other cases and there might be a sender +waiting for a ack we just let it timeout at the senders time and +hopefully all other cleanups will remove the FIN message on their +sending queue. As an example we should never send out an ACK being in +LAST_ACK state or we cannot assume a working socket communication when +we are in CLOSED state. + +Cc: stable@vger.kernel.org +Fixes: 489d8e559c65 ("fs: dlm: add reliable connection if reconnect") +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Greg Kroah-Hartman +--- + fs/dlm/midcomms.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/fs/dlm/midcomms.c ++++ b/fs/dlm/midcomms.c +@@ -375,7 +375,7 @@ static int dlm_send_ack(int nodeid, uint + struct dlm_msg *msg; + char *ppc; + +- msg = dlm_lowcomms_new_msg(nodeid, mb_len, GFP_NOFS, &ppc, ++ msg = dlm_lowcomms_new_msg(nodeid, mb_len, GFP_ATOMIC, &ppc, + NULL, NULL); + if (!msg) + return -ENOMEM; +@@ -498,15 +498,14 @@ static void dlm_midcomms_receive_buffer( + + switch (p->header.h_cmd) { + case DLM_FIN: +- /* send ack before fin */ +- dlm_send_ack(node->nodeid, node->seq_next); +- + spin_lock(&node->state_lock); + pr_debug("receive fin msg from node %d with state %s\n", + node->nodeid, dlm_state_str(node->state)); + + switch (node->state) { + case DLM_ESTABLISHED: ++ dlm_send_ack(node->nodeid, node->seq_next); ++ + node->state = DLM_CLOSE_WAIT; + pr_debug("switch node %d to state %s\n", + node->nodeid, dlm_state_str(node->state)); +@@ -523,12 +522,14 @@ static void dlm_midcomms_receive_buffer( + } + break; + case DLM_FIN_WAIT1: ++ dlm_send_ack(node->nodeid, node->seq_next); + node->state = DLM_CLOSING; + set_bit(DLM_NODE_FLAG_STOP_RX, &node->flags); + pr_debug("switch node %d to state %s\n", + node->nodeid, dlm_state_str(node->state)); + break; + case DLM_FIN_WAIT2: ++ dlm_send_ack(node->nodeid, node->seq_next); + midcomms_node_reset(node); + pr_debug("switch node %d to state %s\n", + node->nodeid, dlm_state_str(node->state)); diff --git a/queue-6.2/fs-dlm-start-midcomms-before-scand.patch b/queue-6.2/fs-dlm-start-midcomms-before-scand.patch new file mode 100644 index 00000000000..0b9f3278587 --- /dev/null +++ b/queue-6.2/fs-dlm-start-midcomms-before-scand.patch @@ -0,0 +1,57 @@ +From aad633dc0cf90093998b1ae0ba9f19b5f1dab644 Mon Sep 17 00:00:00 2001 +From: Alexander Aring +Date: Thu, 12 Jan 2023 17:10:31 -0500 +Subject: fs: dlm: start midcomms before scand + +From: Alexander Aring + +commit aad633dc0cf90093998b1ae0ba9f19b5f1dab644 upstream. + +The scand kthread can send dlm messages out, especially dlm remove +messages to free memory for unused rsb on other nodes. To send out dlm +messages, midcomms must be initialized. This patch moves the midcomms +start before scand is started. + +Cc: stable@vger.kernel.org +Fixes: e7fd41792fc0 ("[DLM] The core of the DLM for GFS2/CLVM") +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Greg Kroah-Hartman +--- + fs/dlm/lockspace.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/fs/dlm/lockspace.c ++++ b/fs/dlm/lockspace.c +@@ -381,23 +381,23 @@ static int threads_start(void) + { + int error; + +- error = dlm_scand_start(); ++ /* Thread for sending/receiving messages for all lockspace's */ ++ error = dlm_midcomms_start(); + if (error) { +- log_print("cannot start dlm_scand thread %d", error); ++ log_print("cannot start dlm midcomms %d", error); + goto fail; + } + +- /* Thread for sending/receiving messages for all lockspace's */ +- error = dlm_midcomms_start(); ++ error = dlm_scand_start(); + if (error) { +- log_print("cannot start dlm midcomms %d", error); +- goto scand_fail; ++ log_print("cannot start dlm_scand thread %d", error); ++ goto midcomms_fail; + } + + return 0; + +- scand_fail: +- dlm_scand_stop(); ++ midcomms_fail: ++ dlm_midcomms_stop(); + fail: + return error; + } diff --git a/queue-6.2/fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch b/queue-6.2/fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch new file mode 100644 index 00000000000..cf6cd558ebc --- /dev/null +++ b/queue-6.2/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-6.2/hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch b/queue-6.2/hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch new file mode 100644 index 00000000000..8be488d88f7 --- /dev/null +++ b/queue-6.2/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 +@@ -274,6 +274,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-6.2/md-don-t-update-recovery_cp-when-curr_resync-is-active.patch b/queue-6.2/md-don-t-update-recovery_cp-when-curr_resync-is-active.patch new file mode 100644 index 00000000000..2c8f6926812 --- /dev/null +++ b/queue-6.2/md-don-t-update-recovery_cp-when-curr_resync-is-active.patch @@ -0,0 +1,51 @@ +From 1d1f25bfda432a6b61bd0205d426226bbbd73504 Mon Sep 17 00:00:00 2001 +From: Hou Tao +Date: Tue, 31 Jan 2023 15:07:19 +0800 +Subject: md: don't update recovery_cp when curr_resync is ACTIVE + +From: Hou Tao + +commit 1d1f25bfda432a6b61bd0205d426226bbbd73504 upstream. + +Don't update recovery_cp when curr_resync is MD_RESYNC_ACTIVE, otherwise +md may skip the resync of the first 3 sectors if the resync procedure is +interrupted before the first calling of ->sync_request() as shown below: + +md_do_sync thread control thread + // setup resync + mddev->recovery_cp = 0 + j = 0 + mddev->curr_resync = MD_RESYNC_ACTIVE + + // e.g., set array as idle + set_bit(MD_RECOVERY_INTR, &&mddev_recovery) + // resync loop + // check INTR before calling sync_request + !test_bit(MD_RECOVERY_INTR, &mddev->recovery + + // resync interrupted + // update recovery_cp from 0 to 3 + // the resync of three 3 sectors will be skipped + mddev->recovery_cp = 3 + +Fixes: eac58d08d493 ("md: Use enum for overloaded magic numbers used by mddev->curr_resync") +Cc: stable@vger.kernel.org # 6.0+ +Signed-off-by: Hou Tao +Reviewed-by: Logan Gunthorpe +Signed-off-by: Song Liu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/md.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -9030,7 +9030,7 @@ void md_do_sync(struct md_thread *thread + mddev->pers->sync_request(mddev, max_sectors, &skipped); + + if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && +- mddev->curr_resync >= MD_RESYNC_ACTIVE) { ++ mddev->curr_resync > MD_RESYNC_ACTIVE) { + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { + if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { + if (mddev->curr_resync >= mddev->recovery_cp) { diff --git a/queue-6.2/ocfs2-fix-defrag-path-triggering-jbd2-assert.patch b/queue-6.2/ocfs2-fix-defrag-path-triggering-jbd2-assert.patch new file mode 100644 index 00000000000..00f9791c93b --- /dev/null +++ b/queue-6.2/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 +@@ -105,14 +105,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); +@@ -121,8 +113,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-6.2/ocfs2-fix-non-auto-defrag-path-not-working-issue.patch b/queue-6.2/ocfs2-fix-non-auto-defrag-path-not-working-issue.patch new file mode 100644 index 00000000000..4a1c8071a00 --- /dev/null +++ b/queue-6.2/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 +@@ -434,7 +434,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) >> +@@ -549,6 +549,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; +@@ -1020,18 +1021,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-6.2/selftests-landlock-skip-overlayfs-tests-when-not-supported.patch b/queue-6.2/selftests-landlock-skip-overlayfs-tests-when-not-supported.patch new file mode 100644 index 00000000000..659e2bcf26e --- /dev/null +++ b/queue-6.2/selftests-landlock-skip-overlayfs-tests-when-not-supported.patch @@ -0,0 +1,118 @@ +From 366617a69e60610912836570546f118006ebc7cb Mon Sep 17 00:00:00 2001 +From: Jeff Xu +Date: Fri, 13 Jan 2023 05:32:29 +0000 +Subject: selftests/landlock: Skip overlayfs tests when not supported +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jeff Xu + +commit 366617a69e60610912836570546f118006ebc7cb upstream. + +overlayfs may be disabled in the kernel configuration, causing related +tests to fail. Check that overlayfs is supported at runtime, so we can +skip layout2_overlay.* accordingly. + +Signed-off-by: Jeff Xu +Reviewed-by: Guenter Roeck +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20230113053229.1281774-2-jeffxu@google.com +[mic: Reword comments and constify variables] +Signed-off-by: Mickaël Salaün +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/landlock/fs_test.c | 47 +++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) + +--- a/tools/testing/selftests/landlock/fs_test.c ++++ b/tools/testing/selftests/landlock/fs_test.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -89,6 +90,40 @@ static const char dir_s3d3[] = TMP_DIR " + * └── s3d3 + */ + ++static bool fgrep(FILE *const inf, const char *const str) ++{ ++ char line[32]; ++ const int slen = strlen(str); ++ ++ while (!feof(inf)) { ++ if (!fgets(line, sizeof(line), inf)) ++ break; ++ if (strncmp(line, str, slen)) ++ continue; ++ ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool supports_overlayfs(void) ++{ ++ bool res; ++ FILE *const inf = fopen("/proc/filesystems", "r"); ++ ++ /* ++ * Consider that the filesystem is supported if we cannot get the ++ * supported ones. ++ */ ++ if (!inf) ++ return true; ++ ++ res = fgrep(inf, "nodev\toverlay\n"); ++ fclose(inf); ++ return res; ++} ++ + static void mkdir_parents(struct __test_metadata *const _metadata, + const char *const path) + { +@@ -4001,6 +4036,9 @@ FIXTURE(layout2_overlay) {}; + + FIXTURE_SETUP(layout2_overlay) + { ++ if (!supports_overlayfs()) ++ SKIP(return, "overlayfs is not supported"); ++ + prepare_layout(_metadata); + + create_directory(_metadata, LOWER_BASE); +@@ -4037,6 +4075,9 @@ FIXTURE_SETUP(layout2_overlay) + + FIXTURE_TEARDOWN(layout2_overlay) + { ++ if (!supports_overlayfs()) ++ SKIP(return, "overlayfs is not supported"); ++ + EXPECT_EQ(0, remove_path(lower_do1_fl3)); + EXPECT_EQ(0, remove_path(lower_dl1_fl2)); + EXPECT_EQ(0, remove_path(lower_fl1)); +@@ -4068,6 +4109,9 @@ FIXTURE_TEARDOWN(layout2_overlay) + + TEST_F_FORK(layout2_overlay, no_restriction) + { ++ if (!supports_overlayfs()) ++ SKIP(return, "overlayfs is not supported"); ++ + ASSERT_EQ(0, test_open(lower_fl1, O_RDONLY)); + ASSERT_EQ(0, test_open(lower_dl1, O_RDONLY)); + ASSERT_EQ(0, test_open(lower_dl1_fl2, O_RDONLY)); +@@ -4231,6 +4275,9 @@ TEST_F_FORK(layout2_overlay, same_conten + size_t i; + const char *path_entry; + ++ if (!supports_overlayfs()) ++ SKIP(return, "overlayfs is not supported"); ++ + /* Sets rules on base directories (i.e. outside overlay scope). */ + ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base); + ASSERT_LE(0, ruleset_fd); diff --git a/queue-6.2/selftests-landlock-test-ptrace-as-much-as-possible-with-yama.patch b/queue-6.2/selftests-landlock-test-ptrace-as-much-as-possible-with-yama.patch new file mode 100644 index 00000000000..f985eed0a6b --- /dev/null +++ b/queue-6.2/selftests-landlock-test-ptrace-as-much-as-possible-with-yama.patch @@ -0,0 +1,215 @@ +From 8677e555f17f51321d0730b945aeb7d4b95f998f Mon Sep 17 00:00:00 2001 +From: Jeff Xu +Date: Sat, 14 Jan 2023 02:03:06 +0000 +Subject: selftests/landlock: Test ptrace as much as possible with Yama +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jeff Xu + +commit 8677e555f17f51321d0730b945aeb7d4b95f998f upstream. + +Update ptrace tests according to all potential Yama security policies. +This is required to make such tests pass even if Yama is enabled. + +Tests are not skipped but they now check both Landlock and Yama boundary +restrictions at run time to keep a maximum test coverage (i.e. positive +and negative testing). + +Signed-off-by: Jeff Xu +Link: https://lore.kernel.org/r/20230114020306.1407195-2-jeffxu@google.com +Cc: stable@vger.kernel.org +[mic: Add curly braces around EXPECT_EQ() to make it build, and improve +commit message] +Co-developed-by: Mickaël Salaün +Signed-off-by: Mickaël Salaün +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/landlock/ptrace_test.c | 113 +++++++++++++++++++++---- + 1 file changed, 96 insertions(+), 17 deletions(-) + +--- a/tools/testing/selftests/landlock/ptrace_test.c ++++ b/tools/testing/selftests/landlock/ptrace_test.c +@@ -19,6 +19,12 @@ + + #include "common.h" + ++/* Copied from security/yama/yama_lsm.c */ ++#define YAMA_SCOPE_DISABLED 0 ++#define YAMA_SCOPE_RELATIONAL 1 ++#define YAMA_SCOPE_CAPABILITY 2 ++#define YAMA_SCOPE_NO_ATTACH 3 ++ + static void create_domain(struct __test_metadata *const _metadata) + { + int ruleset_fd; +@@ -60,6 +66,25 @@ static int test_ptrace_read(const pid_t + return 0; + } + ++static int get_yama_ptrace_scope(void) ++{ ++ int ret; ++ char buf[2] = {}; ++ const int fd = open("/proc/sys/kernel/yama/ptrace_scope", O_RDONLY); ++ ++ if (fd < 0) ++ return 0; ++ ++ if (read(fd, buf, 1) < 0) { ++ close(fd); ++ return -1; ++ } ++ ++ ret = atoi(buf); ++ close(fd); ++ return ret; ++} ++ + /* clang-format off */ + FIXTURE(hierarchy) {}; + /* clang-format on */ +@@ -232,8 +257,51 @@ TEST_F(hierarchy, trace) + pid_t child, parent; + int status, err_proc_read; + int pipe_child[2], pipe_parent[2]; ++ int yama_ptrace_scope; + char buf_parent; + long ret; ++ bool can_read_child, can_trace_child, can_read_parent, can_trace_parent; ++ ++ yama_ptrace_scope = get_yama_ptrace_scope(); ++ ASSERT_LE(0, yama_ptrace_scope); ++ ++ if (yama_ptrace_scope > YAMA_SCOPE_DISABLED) ++ TH_LOG("Incomplete tests due to Yama restrictions (scope %d)", ++ yama_ptrace_scope); ++ ++ /* ++ * can_read_child is true if a parent process can read its child ++ * process, which is only the case when the parent process is not ++ * isolated from the child with a dedicated Landlock domain. ++ */ ++ can_read_child = !variant->domain_parent; ++ ++ /* ++ * can_trace_child is true if a parent process can trace its child ++ * process. This depends on two conditions: ++ * - The parent process is not isolated from the child with a dedicated ++ * Landlock domain. ++ * - Yama allows tracing children (up to YAMA_SCOPE_RELATIONAL). ++ */ ++ can_trace_child = can_read_child && ++ yama_ptrace_scope <= YAMA_SCOPE_RELATIONAL; ++ ++ /* ++ * can_read_parent is true if a child process can read its parent ++ * process, which is only the case when the child process is not ++ * isolated from the parent with a dedicated Landlock domain. ++ */ ++ can_read_parent = !variant->domain_child; ++ ++ /* ++ * can_trace_parent is true if a child process can trace its parent ++ * process. This depends on two conditions: ++ * - The child process is not isolated from the parent with a dedicated ++ * Landlock domain. ++ * - Yama is disabled (YAMA_SCOPE_DISABLED). ++ */ ++ can_trace_parent = can_read_parent && ++ yama_ptrace_scope <= YAMA_SCOPE_DISABLED; + + /* + * Removes all effective and permitted capabilities to not interfere +@@ -264,16 +332,21 @@ TEST_F(hierarchy, trace) + /* Waits for the parent to be in a domain, if any. */ + ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1)); + +- /* Tests PTRACE_ATTACH and PTRACE_MODE_READ on the parent. */ ++ /* Tests PTRACE_MODE_READ on the parent. */ + err_proc_read = test_ptrace_read(parent); ++ if (can_read_parent) { ++ EXPECT_EQ(0, err_proc_read); ++ } else { ++ EXPECT_EQ(EACCES, err_proc_read); ++ } ++ ++ /* Tests PTRACE_ATTACH on the parent. */ + ret = ptrace(PTRACE_ATTACH, parent, NULL, 0); +- if (variant->domain_child) { ++ if (can_trace_parent) { ++ EXPECT_EQ(0, ret); ++ } else { + EXPECT_EQ(-1, ret); + EXPECT_EQ(EPERM, errno); +- EXPECT_EQ(EACCES, err_proc_read); +- } else { +- EXPECT_EQ(0, ret); +- EXPECT_EQ(0, err_proc_read); + } + if (ret == 0) { + ASSERT_EQ(parent, waitpid(parent, &status, 0)); +@@ -283,11 +356,11 @@ TEST_F(hierarchy, trace) + + /* Tests child PTRACE_TRACEME. */ + ret = ptrace(PTRACE_TRACEME); +- if (variant->domain_parent) { ++ if (can_trace_child) { ++ EXPECT_EQ(0, ret); ++ } else { + EXPECT_EQ(-1, ret); + EXPECT_EQ(EPERM, errno); +- } else { +- EXPECT_EQ(0, ret); + } + + /* +@@ -296,7 +369,7 @@ TEST_F(hierarchy, trace) + */ + ASSERT_EQ(1, write(pipe_child[1], ".", 1)); + +- if (!variant->domain_parent) { ++ if (can_trace_child) { + ASSERT_EQ(0, raise(SIGSTOP)); + } + +@@ -321,7 +394,7 @@ TEST_F(hierarchy, trace) + ASSERT_EQ(1, read(pipe_child[0], &buf_parent, 1)); + + /* Tests child PTRACE_TRACEME. */ +- if (!variant->domain_parent) { ++ if (can_trace_child) { + ASSERT_EQ(child, waitpid(child, &status, 0)); + ASSERT_EQ(1, WIFSTOPPED(status)); + ASSERT_EQ(0, ptrace(PTRACE_DETACH, child, NULL, 0)); +@@ -331,17 +404,23 @@ TEST_F(hierarchy, trace) + EXPECT_EQ(ESRCH, errno); + } + +- /* Tests PTRACE_ATTACH and PTRACE_MODE_READ on the child. */ ++ /* Tests PTRACE_MODE_READ on the child. */ + err_proc_read = test_ptrace_read(child); ++ if (can_read_child) { ++ EXPECT_EQ(0, err_proc_read); ++ } else { ++ EXPECT_EQ(EACCES, err_proc_read); ++ } ++ ++ /* Tests PTRACE_ATTACH on the child. */ + ret = ptrace(PTRACE_ATTACH, child, NULL, 0); +- if (variant->domain_parent) { ++ if (can_trace_child) { ++ EXPECT_EQ(0, ret); ++ } else { + EXPECT_EQ(-1, ret); + EXPECT_EQ(EPERM, errno); +- EXPECT_EQ(EACCES, err_proc_read); +- } else { +- EXPECT_EQ(0, ret); +- EXPECT_EQ(0, err_proc_read); + } ++ + if (ret == 0) { + ASSERT_EQ(child, waitpid(child, &status, 0)); + ASSERT_EQ(1, WIFSTOPPED(status)); diff --git a/queue-6.2/series b/queue-6.2/series index e870c957fad..e15545fc322 100644 --- a/queue-6.2/series +++ b/queue-6.2/series @@ -789,3 +789,33 @@ ksmbd-fix-possible-memory-leak-in-smb2_lock.patch torture-fix-hang-during-kthread-shutdown-phase.patch arm-dts-exynos-correct-hdmi-phy-compatible-in-exynos4.patch io_uring-mark-task-task_running-before-handling-resume-task-work.patch +hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch +fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch +exfat-fix-reporting-fs-error-when-reading-dir-beyond-eof.patch +exfat-fix-unexpected-eof-while-reading-dir.patch +exfat-redefine-dir_deleted-as-the-bad-cluster-number.patch +exfat-fix-inode-i_blocks-for-non-512-byte-sector-size-device.patch +fs-dlm-start-midcomms-before-scand.patch +fs-dlm-fix-use-after-free-in-midcomms-commit.patch +fs-dlm-be-sure-to-call-dlm_send_queue_flush.patch +fs-dlm-fix-race-setting-stop-tx-flag.patch +fs-dlm-don-t-set-stop-rx-flag-after-node-reset.patch +fs-dlm-move-sending-fin-message-into-state-change-handling.patch +fs-dlm-send-fin-ack-back-in-right-cases.patch +f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch +f2fs-retry-to-update-the-inode-page-given-data-corruption.patch +f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch +f2fs-fix-kernel-crash-due-to-null-io-bio.patch +f2fs-revert-f2fs-truncate-blocks-in-batch-in-__complete_revoke_list.patch +ocfs2-fix-defrag-path-triggering-jbd2-assert.patch +ocfs2-fix-non-auto-defrag-path-not-working-issue.patch +fs-cramfs-inode.c-initialize-file_ra_state.patch +selftests-landlock-skip-overlayfs-tests-when-not-supported.patch +selftests-landlock-test-ptrace-as-much-as-possible-with-yama.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 +md-don-t-update-recovery_cp-when-curr_resync-is-active.patch diff --git a/queue-6.2/udf-detect-system-inodes-linked-into-directory-hierarchy.patch b/queue-6.2/udf-detect-system-inodes-linked-into-directory-hierarchy.patch new file mode 100644 index 00000000000..b224a720c11 --- /dev/null +++ b/queue-6.2/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 +@@ -1885,8 +1885,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-6.2/udf-do-not-bother-merging-very-long-extents.patch b/queue-6.2/udf-do-not-bother-merging-very-long-extents.patch new file mode 100644 index 00000000000..33cbe602a94 --- /dev/null +++ b/queue-6.2/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 +@@ -1087,23 +1087,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-6.2/udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch b/queue-6.2/udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch new file mode 100644 index 00000000000..5478bcd2ef7 --- /dev/null +++ b/queue-6.2/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 +@@ -149,26 +149,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-6.2/udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch b/queue-6.2/udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch new file mode 100644 index 00000000000..26c5ad6acdc --- /dev/null +++ b/queue-6.2/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 +@@ -799,19 +799,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-6.2/udf-preserve-link-count-of-system-files.patch b/queue-6.2/udf-preserve-link-count-of-system-files.patch new file mode 100644 index 00000000000..68ea922f9c2 --- /dev/null +++ b/queue-6.2/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 +@@ -1373,6 +1373,7 @@ reread: + ret = -EIO; + goto out; + } ++ iinfo->i_hidden = hidden_inode; + iinfo->i_unique = 0; + iinfo->i_lenEAttr = 0; + iinfo->i_lenExtents = 0; +@@ -1708,8 +1709,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; + __u8 *i_data; + struct kernel_lb_addr i_locStreamdir; + __u64 i_lenStreams; diff --git a/queue-6.2/udf-truncate-added-extents-on-failed-expansion.patch b/queue-6.2/udf-truncate-added-extents-on-failed-expansion.patch new file mode 100644 index 00000000000..02259287b12 --- /dev/null +++ b/queue-6.2/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 +@@ -521,8 +521,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; +@@ -556,7 +558,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) { +@@ -565,7 +567,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++; + } + +@@ -579,6 +581,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