From 425b6ea3efc57845690998a960eaff2f6fbaa7a0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 6 Mar 2023 14:44:01 +0100 Subject: [PATCH] 5.15-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 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 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 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 +++++ ...-t-set-stop-rx-flag-after-node-reset.patch | 47 ++++ ...n-message-into-state-change-handling.patch | 109 +++++++++ ...dlm-send-fin-ack-back-in-right-cases.patch | 70 ++++++ ...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 ++++++++ ...p-overlayfs-tests-when-not-supported.patch | 118 ++++++++++ ...ptrace-as-much-as-possible-with-yama.patch | 215 ++++++++++++++++++ queue-5.15/series | 21 ++ ...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 ++++++ 22 files changed, 1610 insertions(+) create mode 100644 queue-5.15/exfat-fix-inode-i_blocks-for-non-512-byte-sector-size-device.patch create mode 100644 queue-5.15/exfat-fix-reporting-fs-error-when-reading-dir-beyond-eof.patch create mode 100644 queue-5.15/exfat-fix-unexpected-eof-while-reading-dir.patch create mode 100644 queue-5.15/exfat-redefine-dir_deleted-as-the-bad-cluster-number.patch create mode 100644 queue-5.15/f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch create mode 100644 queue-5.15/f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch create mode 100644 queue-5.15/fs-dlm-don-t-set-stop-rx-flag-after-node-reset.patch create mode 100644 queue-5.15/fs-dlm-move-sending-fin-message-into-state-change-handling.patch create mode 100644 queue-5.15/fs-dlm-send-fin-ack-back-in-right-cases.patch create mode 100644 queue-5.15/fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch create mode 100644 queue-5.15/hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch create mode 100644 queue-5.15/ocfs2-fix-defrag-path-triggering-jbd2-assert.patch create mode 100644 queue-5.15/ocfs2-fix-non-auto-defrag-path-not-working-issue.patch create mode 100644 queue-5.15/selftests-landlock-skip-overlayfs-tests-when-not-supported.patch create mode 100644 queue-5.15/selftests-landlock-test-ptrace-as-much-as-possible-with-yama.patch create mode 100644 queue-5.15/udf-detect-system-inodes-linked-into-directory-hierarchy.patch create mode 100644 queue-5.15/udf-do-not-bother-merging-very-long-extents.patch create mode 100644 queue-5.15/udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch create mode 100644 queue-5.15/udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch create mode 100644 queue-5.15/udf-preserve-link-count-of-system-files.patch create mode 100644 queue-5.15/udf-truncate-added-extents-on-failed-expansion.patch diff --git a/queue-5.15/exfat-fix-inode-i_blocks-for-non-512-byte-sector-size-device.patch b/queue-5.15/exfat-fix-inode-i_blocks-for-non-512-byte-sector-size-device.patch new file mode 100644 index 00000000000..d2b4eefc4b4 --- /dev/null +++ b/queue-5.15/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 +@@ -251,8 +251,7 @@ void exfat_truncate(struct inode *inode, + else + mark_inode_dirty(inode); + +- 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 +@@ -243,8 +243,7 @@ static int exfat_map_cluster(struct inod + return err; + } /* end of if != DIR_DELETED */ + +- 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 +@@ -602,8 +601,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 +@@ -398,7 +398,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 +@@ -364,8 +364,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-5.15/exfat-fix-reporting-fs-error-when-reading-dir-beyond-eof.patch b/queue-5.15/exfat-fix-reporting-fs-error-when-reading-dir-beyond-eof.patch new file mode 100644 index 00000000000..db72f704441 --- /dev/null +++ b/queue-5.15/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 +@@ -103,7 +103,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-5.15/exfat-fix-unexpected-eof-while-reading-dir.patch b/queue-5.15/exfat-fix-unexpected-eof-while-reading-dir.patch new file mode 100644 index 00000000000..08b330ef54a --- /dev/null +++ b/queue-5.15/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 +@@ -237,10 +237,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-5.15/exfat-redefine-dir_deleted-as-the-bad-cluster-number.patch b/queue-5.15/exfat-redefine-dir_deleted-as-the-bad-cluster-number.patch new file mode 100644 index 00000000000..a02d4fed067 --- /dev/null +++ b/queue-5.15/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 +@@ -42,7 +42,7 @@ enum { + #define ES_2_ENTRIES 2 + #define ES_ALL_ENTRIES 0 + +-#define DIR_DELETED 0xFFFF0321 ++#define DIR_DELETED 0xFFFFFFF7 + + /* type values */ + #define TYPE_UNUSED 0x0000 diff --git a/queue-5.15/f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch b/queue-5.15/f2fs-fix-cgroup-writeback-accounting-with-fs-layer-encryption.patch new file mode 100644 index 00000000000..0fa67c48677 --- /dev/null +++ b/queue-5.15/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 +@@ -677,7 +677,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); + + __attach_io_flag(fio); + bio_set_op_attrs(bio, fio->op, fio->op_flags); +@@ -887,7 +887,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)); + +@@ -961,7 +961,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-5.15/f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch b/queue-5.15/f2fs-fix-information-leak-in-f2fs_move_inline_dirents.patch new file mode 100644 index 00000000000..5060f224665 --- /dev/null +++ b/queue-5.15/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 +@@ -427,18 +427,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.15/fs-dlm-don-t-set-stop-rx-flag-after-node-reset.patch b/queue-5.15/fs-dlm-don-t-set-stop-rx-flag-after-node-reset.patch new file mode 100644 index 00000000000..b070a8f0363 --- /dev/null +++ b/queue-5.15/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 +@@ -504,6 +504,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; +@@ -524,8 +525,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(test_bit(DLM_NODE_FLAG_STOP_RX, &node->flags)); diff --git a/queue-5.15/fs-dlm-move-sending-fin-message-into-state-change-handling.patch b/queue-5.15/fs-dlm-move-sending-fin-message-into-state-change-handling.patch new file mode 100644 index 00000000000..57b53fbe886 --- /dev/null +++ b/queue-5.15/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 +@@ -394,7 +394,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; + +@@ -498,8 +498,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: +@@ -542,12 +542,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 * +@@ -1268,11 +1262,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; +@@ -1288,12 +1282,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) +@@ -1324,6 +1312,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 */ +@@ -1337,12 +1326,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-5.15/fs-dlm-send-fin-ack-back-in-right-cases.patch b/queue-5.15/fs-dlm-send-fin-ack-back-in-right-cases.patch new file mode 100644 index 00000000000..68d8bf0c2cd --- /dev/null +++ b/queue-5.15/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 +@@ -366,7 +366,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; +@@ -478,15 +478,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)); +@@ -503,12 +502,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-5.15/fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch b/queue-5.15/fs-hfsplus-fix-uaf-issue-in-hfsplus_put_super.patch new file mode 100644 index 00000000000..cf6cd558ebc --- /dev/null +++ b/queue-5.15/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.15/hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch b/queue-5.15/hfs-fix-missing-hfs_bnode_get-in-__hfs_bnode_create.patch new file mode 100644 index 00000000000..d18b0859bd1 --- /dev/null +++ b/queue-5.15/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.15/ocfs2-fix-defrag-path-triggering-jbd2-assert.patch b/queue-5.15/ocfs2-fix-defrag-path-triggering-jbd2-assert.patch new file mode 100644 index 00000000000..00f9791c93b --- /dev/null +++ b/queue-5.15/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-5.15/ocfs2-fix-non-auto-defrag-path-not-working-issue.patch b/queue-5.15/ocfs2-fix-non-auto-defrag-path-not-working-issue.patch new file mode 100644 index 00000000000..4a1c8071a00 --- /dev/null +++ b/queue-5.15/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-5.15/selftests-landlock-skip-overlayfs-tests-when-not-supported.patch b/queue-5.15/selftests-landlock-skip-overlayfs-tests-when-not-supported.patch new file mode 100644 index 00000000000..6672b6bd3c3 --- /dev/null +++ b/queue-5.15/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 +@@ -87,6 +88,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) + { +@@ -2650,6 +2685,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); +@@ -2686,6 +2724,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)); +@@ -2717,6 +2758,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)); +@@ -2880,6 +2924,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-5.15/selftests-landlock-test-ptrace-as-much-as-possible-with-yama.patch b/queue-5.15/selftests-landlock-test-ptrace-as-much-as-possible-with-yama.patch new file mode 100644 index 00000000000..f985eed0a6b --- /dev/null +++ b/queue-5.15/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-5.15/series b/queue-5.15/series index 7c9cd5b6c1e..f8e927797c4 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -444,3 +444,24 @@ locking-rwsem-prevent-non-first-waiter-from-spinning-in-down_write-slowpath.patc ksmbd-fix-wrong-data-area-length-for-smb2-lock-request.patch ksmbd-do-not-allow-the-actual-frame-length-to-be-smaller-than-the-rfc1002-length.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 +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-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-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 +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 diff --git a/queue-5.15/udf-detect-system-inodes-linked-into-directory-hierarchy.patch b/queue-5.15/udf-detect-system-inodes-linked-into-directory-hierarchy.patch new file mode 100644 index 00000000000..7dec5464afe --- /dev/null +++ b/queue-5.15/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 +@@ -1897,8 +1897,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.15/udf-do-not-bother-merging-very-long-extents.patch b/queue-5.15/udf-do-not-bother-merging-very-long-extents.patch new file mode 100644 index 00000000000..36e875e76a9 --- /dev/null +++ b/queue-5.15/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 +@@ -1093,23 +1093,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.15/udf-do-not-update-file-length-for-failed-writes-to-inline-files.patch b/queue-5.15/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.15/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.15/udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch b/queue-5.15/udf-fix-file-corruption-when-appending-just-after-end-of-preallocated-extent.patch new file mode 100644 index 00000000000..057b410da9d --- /dev/null +++ b/queue-5.15/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 +@@ -804,19 +804,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.15/udf-preserve-link-count-of-system-files.patch b/queue-5.15/udf-preserve-link-count-of-system-files.patch new file mode 100644 index 00000000000..d1140353662 --- /dev/null +++ b/queue-5.15/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 +@@ -1385,6 +1385,7 @@ reread: + ret = -EIO; + goto out; + } ++ iinfo->i_hidden = hidden_inode; + iinfo->i_unique = 0; + iinfo->i_lenEAttr = 0; + iinfo->i_lenExtents = 0; +@@ -1720,8 +1721,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-5.15/udf-truncate-added-extents-on-failed-expansion.patch b/queue-5.15/udf-truncate-added-extents-on-failed-expansion.patch new file mode 100644 index 00000000000..e6f7124229d --- /dev/null +++ b/queue-5.15/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 +@@ -525,8 +525,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; +@@ -560,7 +562,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) { +@@ -569,7 +571,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++; + } + +@@ -583,6 +585,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