From: Greg Kroah-Hartman Date: Wed, 4 Jan 2023 15:13:01 +0000 (+0100) Subject: 6.1-stable patches X-Git-Tag: v6.1.4~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=330969ddb38bc1b5b5491e09b5c4e347e12e43f7;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: ext4-allocate-extended-attribute-value-in-vmalloc-area.patch ext4-avoid-bug_on-when-creating-xattrs.patch ext4-avoid-unaccounted-block-allocation-when-expanding-inode.patch ext4-don-t-fail-getfsuuid-when-the-caller-provides-a-long-buffer.patch ext4-dont-return-einval-from-getfsuuid-when-reporting-uuid-length.patch ext4-fix-bad-checksum-after-online-resize.patch ext4-fix-corrupt-backup-group-descriptors-after-online-resize.patch ext4-fix-corruption-when-online-resizing-a-1k-bigalloc-fs.patch ext4-fix-deadlock-due-to-mbcache-entry-corruption.patch ext4-fix-delayed-allocation-bug-in-ext4_clu_mapped-for-bigalloc-inline.patch ext4-fix-error-code-return-to-user-space-in-ext4_get_branch.patch ext4-fix-inode-leak-in-ext4_xattr_inode_create-on-an-error-path.patch ext4-fix-kernel-bug-in-ext4_write_inline_data_end.patch ext4-init-quota-for-old.inode-in-ext4_rename.patch ext4-initialize-quota-before-expanding-inode-in-setproject-ioctl.patch --- diff --git a/queue-6.1/ext4-allocate-extended-attribute-value-in-vmalloc-area.patch b/queue-6.1/ext4-allocate-extended-attribute-value-in-vmalloc-area.patch new file mode 100644 index 00000000000..380f9654745 --- /dev/null +++ b/queue-6.1/ext4-allocate-extended-attribute-value-in-vmalloc-area.patch @@ -0,0 +1,45 @@ +From cc12a6f25e07ed05d5825a1664b67a970842b2ca Mon Sep 17 00:00:00 2001 +From: Ye Bin +Date: Thu, 8 Dec 2022 10:32:31 +0800 +Subject: ext4: allocate extended attribute value in vmalloc area + +From: Ye Bin + +commit cc12a6f25e07ed05d5825a1664b67a970842b2ca upstream. + +Now, extended attribute value maximum length is 64K. The memory +requested here does not need continuous physical addresses, so it is +appropriate to use kvmalloc to request memory. At the same time, it +can also cope with the situation that the extended attribute will +become longer in the future. + +Signed-off-by: Ye Bin +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20221208023233.1231330-3-yebin@huaweicloud.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/xattr.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -2550,7 +2550,7 @@ static int ext4_xattr_move_to_block(hand + + is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS); + bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS); +- buffer = kmalloc(value_size, GFP_NOFS); ++ buffer = kvmalloc(value_size, GFP_NOFS); + b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS); + if (!is || !bs || !buffer || !b_entry_name) { + error = -ENOMEM; +@@ -2602,7 +2602,7 @@ static int ext4_xattr_move_to_block(hand + error = 0; + out: + kfree(b_entry_name); +- kfree(buffer); ++ kvfree(buffer); + if (is) + brelse(is->iloc.bh); + if (bs) diff --git a/queue-6.1/ext4-avoid-bug_on-when-creating-xattrs.patch b/queue-6.1/ext4-avoid-bug_on-when-creating-xattrs.patch new file mode 100644 index 00000000000..6d9e4dc5fcd --- /dev/null +++ b/queue-6.1/ext4-avoid-bug_on-when-creating-xattrs.patch @@ -0,0 +1,53 @@ +From b40ebaf63851b3a401b0dc9263843538f64f5ce6 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 21 Nov 2022 14:09:29 +0100 +Subject: ext4: avoid BUG_ON when creating xattrs + +From: Jan Kara + +commit b40ebaf63851b3a401b0dc9263843538f64f5ce6 upstream. + +Commit fb0a387dcdcd ("ext4: limit block allocations for indirect-block +files to < 2^32") added code to try to allocate xattr block with 32-bit +block number for indirect block based files on the grounds that these +files cannot use larger block numbers. It also added BUG_ON when +allocated block could not fit into 32 bits. This is however bogus +reasoning because xattr block is stored in inode->i_file_acl and +inode->i_file_acl_hi and as such even indirect block based files can +happily use full 48 bits for xattr block number. The proper handling +seems to be there basically since 64-bit block number support was added. +So remove the bogus limitation and BUG_ON. + +Cc: Eric Sandeen +Fixes: fb0a387dcdcd ("ext4: limit block allocations for indirect-block files to < 2^32") +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20221121130929.32031-1-jack@suse.cz +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/xattr.c | 8 -------- + 1 file changed, 8 deletions(-) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -2070,19 +2070,11 @@ inserted: + + goal = ext4_group_first_block_no(sb, + EXT4_I(inode)->i_block_group); +- +- /* non-extent files can't have physical blocks past 2^32 */ +- if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) +- goal = goal & EXT4_MAX_BLOCK_FILE_PHYS; +- + block = ext4_new_meta_blocks(handle, inode, goal, 0, + NULL, &error); + if (error) + goto cleanup; + +- if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) +- BUG_ON(block > EXT4_MAX_BLOCK_FILE_PHYS); +- + ea_idebug(inode, "creating block %llu", + (unsigned long long)block); + diff --git a/queue-6.1/ext4-avoid-unaccounted-block-allocation-when-expanding-inode.patch b/queue-6.1/ext4-avoid-unaccounted-block-allocation-when-expanding-inode.patch new file mode 100644 index 00000000000..ae0a2ffbf4f --- /dev/null +++ b/queue-6.1/ext4-avoid-unaccounted-block-allocation-when-expanding-inode.patch @@ -0,0 +1,42 @@ +From 8994d11395f8165b3deca1971946f549f0822630 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 7 Dec 2022 12:59:28 +0100 +Subject: ext4: avoid unaccounted block allocation when expanding inode + +From: Jan Kara + +commit 8994d11395f8165b3deca1971946f549f0822630 upstream. + +When expanding inode space in ext4_expand_extra_isize_ea() we may need +to allocate external xattr block. If quota is not initialized for the +inode, the block allocation will not be accounted into quota usage. Make +sure the quota is initialized before we try to expand inode space. + +Reported-by: Pengfei Xu +Link: https://lore.kernel.org/all/Y5BT+k6xWqthZc1P@xpf.sh.intel.com +Signed-off-by: Jan Kara +Cc: stable@kernel.org +Link: https://lore.kernel.org/r/20221207115937.26601-2-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/inode.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -5875,6 +5875,14 @@ static int __ext4_expand_extra_isize(str + return 0; + } + ++ /* ++ * We may need to allocate external xattr block so we need quotas ++ * initialized. Here we can be called with various locks held so we ++ * cannot affort to initialize quotas ourselves. So just bail. ++ */ ++ if (dquot_initialize_needed(inode)) ++ return -EAGAIN; ++ + /* try to expand with EAs present */ + error = ext4_expand_extra_isize_ea(inode, new_extra_isize, + raw_inode, handle); diff --git a/queue-6.1/ext4-don-t-fail-getfsuuid-when-the-caller-provides-a-long-buffer.patch b/queue-6.1/ext4-don-t-fail-getfsuuid-when-the-caller-provides-a-long-buffer.patch new file mode 100644 index 00000000000..8da420b83c3 --- /dev/null +++ b/queue-6.1/ext4-don-t-fail-getfsuuid-when-the-caller-provides-a-long-buffer.patch @@ -0,0 +1,47 @@ +From a7e9d977e031fceefe1e7cd69ebd7202d5758b56 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Thu, 10 Nov 2022 12:16:34 -0800 +Subject: ext4: don't fail GETFSUUID when the caller provides a long buffer + +From: Darrick J. Wong + +commit a7e9d977e031fceefe1e7cd69ebd7202d5758b56 upstream. + +If userspace provides a longer UUID buffer than is required, we +shouldn't fail the call with EINVAL -- rather, we can fill the caller's +buffer with the bytes we /can/ fill, and update the length field to +reflect what we copied. This doesn't break the UAPI since we're +enabling a case that currently fails, and so far Ted hasn't released a +version of e2fsprogs that uses the new ext4 ioctl. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Catherine Hoang +Link: https://lore.kernel.org/r/166811139478.327006.13879198441587445544.stgit@magnolia +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ioctl.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -1159,14 +1159,16 @@ static int ext4_ioctl_getuuid(struct ext + return -EINVAL; + } + +- if (fsuuid.fsu_len != UUID_SIZE || fsuuid.fsu_flags != 0) ++ if (fsuuid.fsu_len < UUID_SIZE || fsuuid.fsu_flags != 0) + return -EINVAL; + + lock_buffer(sbi->s_sbh); + memcpy(uuid, sbi->s_es->s_uuid, UUID_SIZE); + unlock_buffer(sbi->s_sbh); + +- if (copy_to_user(&ufsuuid->fsu_uuid[0], uuid, UUID_SIZE)) ++ fsuuid.fsu_len = UUID_SIZE; ++ if (copy_to_user(ufsuuid, &fsuuid, sizeof(fsuuid)) || ++ copy_to_user(&ufsuuid->fsu_uuid[0], uuid, UUID_SIZE)) + return -EFAULT; + return 0; + } diff --git a/queue-6.1/ext4-dont-return-einval-from-getfsuuid-when-reporting-uuid-length.patch b/queue-6.1/ext4-dont-return-einval-from-getfsuuid-when-reporting-uuid-length.patch new file mode 100644 index 00000000000..94be29cc375 --- /dev/null +++ b/queue-6.1/ext4-dont-return-einval-from-getfsuuid-when-reporting-uuid-length.patch @@ -0,0 +1,42 @@ +From b76abb5157468756163fe7e3431c9fe32cba57ca Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Thu, 10 Nov 2022 12:16:29 -0800 +Subject: ext4: dont return EINVAL from GETFSUUID when reporting UUID length + +From: Darrick J. Wong + +commit b76abb5157468756163fe7e3431c9fe32cba57ca upstream. + +If userspace calls this ioctl with fsu_length (the length of the +fsuuid.fsu_uuid array) set to zero, ext4 copies the desired uuid length +out to userspace. The kernel call returned a result from a valid input, +so the return value here should be zero, not EINVAL. + +While we're at it, fix the copy_to_user call to make it clear that we're +only copying out fsu_len. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Catherine Hoang +Link: https://lore.kernel.org/r/166811138914.327006.9241306894437166566.stgit@magnolia +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ioctl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -1154,9 +1154,10 @@ static int ext4_ioctl_getuuid(struct ext + + if (fsuuid.fsu_len == 0) { + fsuuid.fsu_len = UUID_SIZE; +- if (copy_to_user(ufsuuid, &fsuuid, sizeof(fsuuid.fsu_len))) ++ if (copy_to_user(&ufsuuid->fsu_len, &fsuuid.fsu_len, ++ sizeof(fsuuid.fsu_len))) + return -EFAULT; +- return -EINVAL; ++ return 0; + } + + if (fsuuid.fsu_len < UUID_SIZE || fsuuid.fsu_flags != 0) diff --git a/queue-6.1/ext4-fix-bad-checksum-after-online-resize.patch b/queue-6.1/ext4-fix-bad-checksum-after-online-resize.patch new file mode 100644 index 00000000000..8ee1fa3bd5f --- /dev/null +++ b/queue-6.1/ext4-fix-bad-checksum-after-online-resize.patch @@ -0,0 +1,54 @@ +From a408f33e895e455f16cf964cb5cd4979b658db7b Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Thu, 17 Nov 2022 12:03:39 +0800 +Subject: ext4: fix bad checksum after online resize + +From: Baokun Li + +commit a408f33e895e455f16cf964cb5cd4979b658db7b upstream. + +When online resizing is performed twice consecutively, the error message +"Superblock checksum does not match superblock" is displayed for the +second time. Here's the reproducer: + + mkfs.ext4 -F /dev/sdb 100M + mount /dev/sdb /tmp/test + resize2fs /dev/sdb 5G + resize2fs /dev/sdb 6G + +To solve this issue, we moved the update of the checksum after the +es->s_overhead_clusters is updated. + +Fixes: 026d0d27c488 ("ext4: reduce computation of overhead during resize") +Fixes: de394a86658f ("ext4: update s_overhead_clusters in the superblock during an on-line resize") +Signed-off-by: Baokun Li +Reviewed-by: Darrick J. Wong +Reviewed-by: Jan Kara +Cc: stable@kernel.org +Link: https://lore.kernel.org/r/20221117040341.1380702-2-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/resize.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1476,8 +1476,6 @@ static void ext4_update_super(struct sup + * active. */ + ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) + + reserved_blocks); +- ext4_superblock_csum_set(sb); +- unlock_buffer(sbi->s_sbh); + + /* Update the free space counts */ + percpu_counter_add(&sbi->s_freeclusters_counter, +@@ -1513,6 +1511,8 @@ static void ext4_update_super(struct sup + ext4_calculate_overhead(sb); + es->s_overhead_clusters = cpu_to_le32(sbi->s_overhead); + ++ ext4_superblock_csum_set(sb); ++ unlock_buffer(sbi->s_sbh); + if (test_opt(sb, DEBUG)) + printk(KERN_DEBUG "EXT4-fs: added group %u:" + "%llu blocks(%llu free %llu reserved)\n", flex_gd->count, diff --git a/queue-6.1/ext4-fix-corrupt-backup-group-descriptors-after-online-resize.patch b/queue-6.1/ext4-fix-corrupt-backup-group-descriptors-after-online-resize.patch new file mode 100644 index 00000000000..f25e1b3fd50 --- /dev/null +++ b/queue-6.1/ext4-fix-corrupt-backup-group-descriptors-after-online-resize.patch @@ -0,0 +1,92 @@ +From 8f49ec603ae3e213bfab2799182724e3abac55a1 Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Thu, 17 Nov 2022 12:03:40 +0800 +Subject: ext4: fix corrupt backup group descriptors after online resize + +From: Baokun Li + +commit 8f49ec603ae3e213bfab2799182724e3abac55a1 upstream. + +In commit 9a8c5b0d0615 ("ext4: update the backup superblock's at the end +of the online resize"), it is assumed that update_backups() only updates +backup superblocks, so each b_data is treated as a backupsuper block to +update its s_block_group_nr and s_checksum. However, update_backups() +also updates the backup group descriptors, which causes the backup group +descriptors to be corrupted. + +The above commit fixes the problem of invalid checksum of the backup +superblock. The root cause of this problem is that the checksum of +ext4_update_super() is not set correctly. This problem has been fixed +in the previous patch ("ext4: fix bad checksum after online resize"). + +However, we do need to set block_group_nr for the backup superblock in +update_backups(). When a block is in a group that contains a backup +superblock, and the block is the first block in the group, the block is +definitely a superblock. We add a helper function that includes setting +s_block_group_nr and updating checksum, and then call it only when the +above conditions are met to prevent the backup group descriptors from +being incorrectly modified. + +Fixes: 9a8c5b0d0615 ("ext4: update the backup superblock's at the end of the online resize") +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Cc: stable@kernel.org +Link: https://lore.kernel.org/r/20221117040341.1380702-3-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/resize.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1110,6 +1110,16 @@ exit_free: + return err; + } + ++static inline void ext4_set_block_group_nr(struct super_block *sb, char *data, ++ ext4_group_t group) ++{ ++ struct ext4_super_block *es = (struct ext4_super_block *) data; ++ ++ es->s_block_group_nr = cpu_to_le16(group); ++ if (ext4_has_metadata_csum(sb)) ++ es->s_checksum = ext4_superblock_csum(sb, es); ++} ++ + /* + * Update the backup copies of the ext4 metadata. These don't need to be part + * of the main resize transaction, because e2fsck will re-write them if there +@@ -1158,7 +1168,8 @@ static void update_backups(struct super_ + while (group < sbi->s_groups_count) { + struct buffer_head *bh; + ext4_fsblk_t backup_block; +- struct ext4_super_block *es; ++ int has_super = ext4_bg_has_super(sb, group); ++ ext4_fsblk_t first_block = ext4_group_first_block_no(sb, group); + + /* Out of journal space, and can't get more - abort - so sad */ + err = ext4_resize_ensure_credits_batch(handle, 1); +@@ -1168,8 +1179,7 @@ static void update_backups(struct super_ + if (meta_bg == 0) + backup_block = ((ext4_fsblk_t)group) * bpg + blk_off; + else +- backup_block = (ext4_group_first_block_no(sb, group) + +- ext4_bg_has_super(sb, group)); ++ backup_block = first_block + has_super; + + bh = sb_getblk(sb, backup_block); + if (unlikely(!bh)) { +@@ -1187,10 +1197,8 @@ static void update_backups(struct super_ + memcpy(bh->b_data, data, size); + if (rest) + memset(bh->b_data + size, 0, rest); +- es = (struct ext4_super_block *) bh->b_data; +- es->s_block_group_nr = cpu_to_le16(group); +- if (ext4_has_metadata_csum(sb)) +- es->s_checksum = ext4_superblock_csum(sb, es); ++ if (has_super && (backup_block == first_block)) ++ ext4_set_block_group_nr(sb, bh->b_data, group); + set_buffer_uptodate(bh); + unlock_buffer(bh); + err = ext4_handle_dirty_metadata(handle, NULL, bh); diff --git a/queue-6.1/ext4-fix-corruption-when-online-resizing-a-1k-bigalloc-fs.patch b/queue-6.1/ext4-fix-corruption-when-online-resizing-a-1k-bigalloc-fs.patch new file mode 100644 index 00000000000..63986941453 --- /dev/null +++ b/queue-6.1/ext4-fix-corruption-when-online-resizing-a-1k-bigalloc-fs.patch @@ -0,0 +1,53 @@ +From 0aeaa2559d6d53358fca3e3fce73807367adca74 Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Thu, 17 Nov 2022 12:03:41 +0800 +Subject: ext4: fix corruption when online resizing a 1K bigalloc fs + +From: Baokun Li + +commit 0aeaa2559d6d53358fca3e3fce73807367adca74 upstream. + +When a backup superblock is updated in update_backups(), the primary +superblock's offset in the group (that is, sbi->s_sbh->b_blocknr) is used +as the backup superblock's offset in its group. However, when the block +size is 1K and bigalloc is enabled, the two offsets are not equal. This +causes the backup group descriptors to be overwritten by the superblock +in update_backups(). Moreover, if meta_bg is enabled, the file system will +be corrupted because this feature uses backup group descriptors. + +To solve this issue, we use a more accurate ext4_group_first_block_no() as +the offset of the backup superblock in its group. + +Fixes: d77147ff443b ("ext4: add support for online resizing with bigalloc") +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Cc: stable@kernel.org +Link: https://lore.kernel.org/r/20221117040341.1380702-4-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/resize.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1596,8 +1596,8 @@ exit_journal: + int meta_bg = ext4_has_feature_meta_bg(sb); + sector_t old_gdb = 0; + +- update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es, +- sizeof(struct ext4_super_block), 0); ++ update_backups(sb, ext4_group_first_block_no(sb, 0), ++ (char *)es, sizeof(struct ext4_super_block), 0); + for (; gdb_num <= gdb_num_end; gdb_num++) { + struct buffer_head *gdb_bh; + +@@ -1808,7 +1808,7 @@ errout: + if (test_opt(sb, DEBUG)) + printk(KERN_DEBUG "EXT4-fs: extended group to %llu " + "blocks\n", ext4_blocks_count(es)); +- update_backups(sb, EXT4_SB(sb)->s_sbh->b_blocknr, ++ update_backups(sb, ext4_group_first_block_no(sb, 0), + (char *)es, sizeof(struct ext4_super_block), 0); + } + return err; diff --git a/queue-6.1/ext4-fix-deadlock-due-to-mbcache-entry-corruption.patch b/queue-6.1/ext4-fix-deadlock-due-to-mbcache-entry-corruption.patch new file mode 100644 index 00000000000..d06f2c8b13b --- /dev/null +++ b/queue-6.1/ext4-fix-deadlock-due-to-mbcache-entry-corruption.patch @@ -0,0 +1,134 @@ +From a44e84a9b7764c72896f7241a0ec9ac7e7ef38dd Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 23 Nov 2022 20:39:50 +0100 +Subject: ext4: fix deadlock due to mbcache entry corruption + +From: Jan Kara + +commit a44e84a9b7764c72896f7241a0ec9ac7e7ef38dd upstream. + +When manipulating xattr blocks, we can deadlock infinitely looping +inside ext4_xattr_block_set() where we constantly keep finding xattr +block for reuse in mbcache but we are unable to reuse it because its +reference count is too big. This happens because cache entry for the +xattr block is marked as reusable (e_reusable set) although its +reference count is too big. When this inconsistency happens, this +inconsistent state is kept indefinitely and so ext4_xattr_block_set() +keeps retrying indefinitely. + +The inconsistent state is caused by non-atomic update of e_reusable bit. +e_reusable is part of a bitfield and e_reusable update can race with +update of e_referenced bit in the same bitfield resulting in loss of one +of the updates. Fix the problem by using atomic bitops instead. + +This bug has been around for many years, but it became *much* easier +to hit after commit 65f8b80053a1 ("ext4: fix race when reusing xattr +blocks"). + +Cc: stable@vger.kernel.org +Fixes: 6048c64b2609 ("mbcache: add reusable flag to cache entries") +Fixes: 65f8b80053a1 ("ext4: fix race when reusing xattr blocks") +Reported-and-tested-by: Jeremi Piotrowski +Reported-by: Thilo Fromm +Link: https://lore.kernel.org/r/c77bf00f-4618-7149-56f1-b8d1664b9d07@linux.microsoft.com/ +Signed-off-by: Jan Kara +Reviewed-by: Andreas Dilger +Link: https://lore.kernel.org/r/20221123193950.16758-1-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/xattr.c | 4 ++-- + fs/mbcache.c | 14 ++++++++------ + include/linux/mbcache.h | 9 +++++++-- + 3 files changed, 17 insertions(+), 10 deletions(-) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1281,7 +1281,7 @@ retry_ref: + ce = mb_cache_entry_get(ea_block_cache, hash, + bh->b_blocknr); + if (ce) { +- ce->e_reusable = 1; ++ set_bit(MBE_REUSABLE_B, &ce->e_flags); + mb_cache_entry_put(ea_block_cache, ce); + } + } +@@ -2042,7 +2042,7 @@ inserted: + } + BHDR(new_bh)->h_refcount = cpu_to_le32(ref); + if (ref == EXT4_XATTR_REFCOUNT_MAX) +- ce->e_reusable = 0; ++ clear_bit(MBE_REUSABLE_B, &ce->e_flags); + ea_bdebug(new_bh, "reusing; refcount now=%d", + ref); + ext4_xattr_block_csum_set(inode, new_bh); +--- a/fs/mbcache.c ++++ b/fs/mbcache.c +@@ -100,8 +100,9 @@ int mb_cache_entry_create(struct mb_cach + atomic_set(&entry->e_refcnt, 2); + entry->e_key = key; + entry->e_value = value; +- entry->e_reusable = reusable; +- entry->e_referenced = 0; ++ entry->e_flags = 0; ++ if (reusable) ++ set_bit(MBE_REUSABLE_B, &entry->e_flags); + head = mb_cache_entry_head(cache, key); + hlist_bl_lock(head); + hlist_bl_for_each_entry(dup, dup_node, head, e_hash_list) { +@@ -165,7 +166,8 @@ static struct mb_cache_entry *__entry_fi + while (node) { + entry = hlist_bl_entry(node, struct mb_cache_entry, + e_hash_list); +- if (entry->e_key == key && entry->e_reusable && ++ if (entry->e_key == key && ++ test_bit(MBE_REUSABLE_B, &entry->e_flags) && + atomic_inc_not_zero(&entry->e_refcnt)) + goto out; + node = node->next; +@@ -284,7 +286,7 @@ EXPORT_SYMBOL(mb_cache_entry_delete_or_g + void mb_cache_entry_touch(struct mb_cache *cache, + struct mb_cache_entry *entry) + { +- entry->e_referenced = 1; ++ set_bit(MBE_REFERENCED_B, &entry->e_flags); + } + EXPORT_SYMBOL(mb_cache_entry_touch); + +@@ -309,9 +311,9 @@ static unsigned long mb_cache_shrink(str + entry = list_first_entry(&cache->c_list, + struct mb_cache_entry, e_list); + /* Drop initial hash reference if there is no user */ +- if (entry->e_referenced || ++ if (test_bit(MBE_REFERENCED_B, &entry->e_flags) || + atomic_cmpxchg(&entry->e_refcnt, 1, 0) != 1) { +- entry->e_referenced = 0; ++ clear_bit(MBE_REFERENCED_B, &entry->e_flags); + list_move_tail(&entry->e_list, &cache->c_list); + continue; + } +--- a/include/linux/mbcache.h ++++ b/include/linux/mbcache.h +@@ -10,6 +10,12 @@ + + struct mb_cache; + ++/* Cache entry flags */ ++enum { ++ MBE_REFERENCED_B = 0, ++ MBE_REUSABLE_B ++}; ++ + struct mb_cache_entry { + /* List of entries in cache - protected by cache->c_list_lock */ + struct list_head e_list; +@@ -26,8 +32,7 @@ struct mb_cache_entry { + atomic_t e_refcnt; + /* Key in hash - stable during lifetime of the entry */ + u32 e_key; +- u32 e_referenced:1; +- u32 e_reusable:1; ++ unsigned long e_flags; + /* User provided value - stable during lifetime of the entry */ + u64 e_value; + }; diff --git a/queue-6.1/ext4-fix-delayed-allocation-bug-in-ext4_clu_mapped-for-bigalloc-inline.patch b/queue-6.1/ext4-fix-delayed-allocation-bug-in-ext4_clu_mapped-for-bigalloc-inline.patch new file mode 100644 index 00000000000..0ead59cf89c --- /dev/null +++ b/queue-6.1/ext4-fix-delayed-allocation-bug-in-ext4_clu_mapped-for-bigalloc-inline.patch @@ -0,0 +1,57 @@ +From 131294c35ed6f777bd4e79d42af13b5c41bf2775 Mon Sep 17 00:00:00 2001 +From: Eric Whitney +Date: Thu, 17 Nov 2022 10:22:07 -0500 +Subject: ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline + +From: Eric Whitney + +commit 131294c35ed6f777bd4e79d42af13b5c41bf2775 upstream. + +When converting files with inline data to extents, delayed allocations +made on a file system created with both the bigalloc and inline options +can result in invalid extent status cache content, incorrect reserved +cluster counts, kernel memory leaks, and potential kernel panics. + +With bigalloc, the code that determines whether a block must be +delayed allocated searches the extent tree to see if that block maps +to a previously allocated cluster. If not, the block is delayed +allocated, and otherwise, it isn't. However, if the inline option is +also used, and if the file containing the block is marked as able to +store data inline, there isn't a valid extent tree associated with +the file. The current code in ext4_clu_mapped() calls +ext4_find_extent() to search the non-existent tree for a previously +allocated cluster anyway, which typically finds nothing, as desired. +However, a side effect of the search can be to cache invalid content +from the non-existent tree (garbage) in the extent status tree, +including bogus entries in the pending reservation tree. + +To fix this, avoid searching the extent tree when allocating blocks +for bigalloc + inline files that are being converted from inline to +extent mapped. + +Signed-off-by: Eric Whitney +Link: https://lore.kernel.org/r/20221117152207.2424-1-enwlinux@gmail.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -5799,6 +5799,14 @@ int ext4_clu_mapped(struct inode *inode, + struct ext4_extent *extent; + ext4_lblk_t first_lblk, first_lclu, last_lclu; + ++ /* ++ * if data can be stored inline, the logical cluster isn't ++ * mapped - no physical clusters have been allocated, and the ++ * file has no extents ++ */ ++ if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) ++ return 0; ++ + /* search for the extent closest to the first block in the cluster */ + path = ext4_find_extent(inode, EXT4_C2B(sbi, lclu), NULL, 0); + if (IS_ERR(path)) { diff --git a/queue-6.1/ext4-fix-error-code-return-to-user-space-in-ext4_get_branch.patch b/queue-6.1/ext4-fix-error-code-return-to-user-space-in-ext4_get_branch.patch new file mode 100644 index 00000000000..7edcef03f65 --- /dev/null +++ b/queue-6.1/ext4-fix-error-code-return-to-user-space-in-ext4_get_branch.patch @@ -0,0 +1,51 @@ +From 26d75a16af285a70863ba6a81f85d81e7e65da50 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lu=C3=ADs=20Henriques?= +Date: Wed, 9 Nov 2022 18:14:45 +0000 +Subject: ext4: fix error code return to user-space in ext4_get_branch() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Luís Henriques + +commit 26d75a16af285a70863ba6a81f85d81e7e65da50 upstream. + +If a block is out of range in ext4_get_branch(), -ENOMEM will be returned +to user-space. Obviously, this error code isn't really useful. This +patch fixes it by making sure the right error code (-EFSCORRUPTED) is +propagated to user-space. EUCLEAN is more informative than ENOMEM. + +Signed-off-by: Luís Henriques +Link: https://lore.kernel.org/r/20221109181445.17843-1-lhenriques@suse.de +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/indirect.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -148,6 +148,7 @@ static Indirect *ext4_get_branch(struct + struct super_block *sb = inode->i_sb; + Indirect *p = chain; + struct buffer_head *bh; ++ unsigned int key; + int ret = -EIO; + + *err = 0; +@@ -156,7 +157,13 @@ static Indirect *ext4_get_branch(struct + if (!p->key) + goto no_block; + while (--depth) { +- bh = sb_getblk(sb, le32_to_cpu(p->key)); ++ key = le32_to_cpu(p->key); ++ if (key > ext4_blocks_count(EXT4_SB(sb)->s_es)) { ++ /* the block was out of range */ ++ ret = -EFSCORRUPTED; ++ goto failure; ++ } ++ bh = sb_getblk(sb, key); + if (unlikely(!bh)) { + ret = -ENOMEM; + goto failure; diff --git a/queue-6.1/ext4-fix-inode-leak-in-ext4_xattr_inode_create-on-an-error-path.patch b/queue-6.1/ext4-fix-inode-leak-in-ext4_xattr_inode_create-on-an-error-path.patch new file mode 100644 index 00000000000..71109063b08 --- /dev/null +++ b/queue-6.1/ext4-fix-inode-leak-in-ext4_xattr_inode_create-on-an-error-path.patch @@ -0,0 +1,53 @@ +From e4db04f7d3dbbe16680e0ded27ea2a65b10f766a Mon Sep 17 00:00:00 2001 +From: Ye Bin +Date: Thu, 8 Dec 2022 10:32:33 +0800 +Subject: ext4: fix inode leak in ext4_xattr_inode_create() on an error path + +From: Ye Bin + +commit e4db04f7d3dbbe16680e0ded27ea2a65b10f766a upstream. + +There is issue as follows when do setxattr with inject fault: + +[localhost]# fsck.ext4 -fn /dev/sda +e2fsck 1.46.6-rc1 (12-Sep-2022) +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Unattached zero-length inode 15. Clear? no + +Unattached inode 15 +Connect to /lost+found? no + +Pass 5: Checking group summary information + +/dev/sda: ********** WARNING: Filesystem still has errors ********** + +/dev/sda: 15/655360 files (0.0% non-contiguous), 66755/2621440 blocks + +This occurs in 'ext4_xattr_inode_create()'. If 'ext4_mark_inode_dirty()' +fails, dropping i_nlink of the inode is needed. Or will lead to inode leak. + +Signed-off-by: Ye Bin +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20221208023233.1231330-5-yebin@huaweicloud.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/xattr.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1441,6 +1441,9 @@ static struct inode *ext4_xattr_inode_cr + if (!err) + err = ext4_inode_attach_jinode(ea_inode); + if (err) { ++ if (ext4_xattr_inode_dec_ref(handle, ea_inode)) ++ ext4_warning_inode(ea_inode, ++ "cleanup dec ref error %d", err); + iput(ea_inode); + return ERR_PTR(err); + } diff --git a/queue-6.1/ext4-fix-kernel-bug-in-ext4_write_inline_data_end.patch b/queue-6.1/ext4-fix-kernel-bug-in-ext4_write_inline_data_end.patch new file mode 100644 index 00000000000..62553411bf6 --- /dev/null +++ b/queue-6.1/ext4-fix-kernel-bug-in-ext4_write_inline_data_end.patch @@ -0,0 +1,107 @@ +From 5c099c4fdc438014d5893629e70a8ba934433ee8 Mon Sep 17 00:00:00 2001 +From: Ye Bin +Date: Tue, 6 Dec 2022 22:41:34 +0800 +Subject: ext4: fix kernel BUG in 'ext4_write_inline_data_end()' + +From: Ye Bin + +commit 5c099c4fdc438014d5893629e70a8ba934433ee8 upstream. + +Syzbot report follow issue: +------------[ cut here ]------------ +kernel BUG at fs/ext4/inline.c:227! +invalid opcode: 0000 [#1] PREEMPT SMP KASAN +CPU: 1 PID: 3629 Comm: syz-executor212 Not tainted 6.1.0-rc5-syzkaller-00018-g59d0d52c30d4 #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 +RIP: 0010:ext4_write_inline_data+0x344/0x3e0 fs/ext4/inline.c:227 +RSP: 0018:ffffc90003b3f368 EFLAGS: 00010293 +RAX: 0000000000000000 RBX: ffff8880704e16c0 RCX: 0000000000000000 +RDX: ffff888021763a80 RSI: ffffffff821e31a4 RDI: 0000000000000006 +RBP: 000000000006818e R08: 0000000000000006 R09: 0000000000068199 +R10: 0000000000000079 R11: 0000000000000000 R12: 000000000000000b +R13: 0000000000068199 R14: ffffc90003b3f408 R15: ffff8880704e1c82 +FS: 000055555723e3c0(0000) GS:ffff8880b9b00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007fffe8ac9080 CR3: 0000000079f81000 CR4: 0000000000350ee0 +Call Trace: + + ext4_write_inline_data_end+0x2a3/0x12f0 fs/ext4/inline.c:768 + ext4_write_end+0x242/0xdd0 fs/ext4/inode.c:1313 + ext4_da_write_end+0x3ed/0xa30 fs/ext4/inode.c:3063 + generic_perform_write+0x316/0x570 mm/filemap.c:3764 + ext4_buffered_write_iter+0x15b/0x460 fs/ext4/file.c:285 + ext4_file_write_iter+0x8bc/0x16e0 fs/ext4/file.c:700 + call_write_iter include/linux/fs.h:2191 [inline] + do_iter_readv_writev+0x20b/0x3b0 fs/read_write.c:735 + do_iter_write+0x182/0x700 fs/read_write.c:861 + vfs_iter_write+0x74/0xa0 fs/read_write.c:902 + iter_file_splice_write+0x745/0xc90 fs/splice.c:686 + do_splice_from fs/splice.c:764 [inline] + direct_splice_actor+0x114/0x180 fs/splice.c:931 + splice_direct_to_actor+0x335/0x8a0 fs/splice.c:886 + do_splice_direct+0x1ab/0x280 fs/splice.c:974 + do_sendfile+0xb19/0x1270 fs/read_write.c:1255 + __do_sys_sendfile64 fs/read_write.c:1323 [inline] + __se_sys_sendfile64 fs/read_write.c:1309 [inline] + __x64_sys_sendfile64+0x1d0/0x210 fs/read_write.c:1309 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd +---[ end trace 0000000000000000 ]--- + +Above issue may happens as follows: +ext4_da_write_begin + ext4_da_write_inline_data_begin + ext4_da_convert_inline_data_to_extent + ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); +ext4_da_write_end + +ext4_run_li_request + ext4_mb_prefetch + ext4_read_block_bitmap_nowait + ext4_validate_block_bitmap + ext4_mark_group_bitmap_corrupted(sb, block_group, EXT4_GROUP_INFO_BBITMAP_CORRUPT) + percpu_counter_sub(&sbi->s_freeclusters_counter,grp->bb_free); + -> sbi->s_freeclusters_counter become zero +ext4_da_write_begin + if (ext4_nonda_switch(inode->i_sb)) -> As freeclusters_counter is zero will return true + *fsdata = (void *)FALL_BACK_TO_NONDELALLOC; + ext4_write_begin +ext4_da_write_end + if (write_mode == FALL_BACK_TO_NONDELALLOC) + ext4_write_end + if (inline_data) + ext4_write_inline_data_end + ext4_write_inline_data + BUG_ON(pos + len > EXT4_I(inode)->i_inline_size); + -> As inode is already convert to extent, so 'pos + len' > inline_size + -> then trigger BUG. + +To solve this issue, instead of checking ext4_has_inline_data() which +is only cleared after data has been written back, check the +EXT4_STATE_MAY_INLINE_DATA flag in ext4_write_end(). + +Fixes: f19d5870cbf7 ("ext4: add normal write support for inline data") +Reported-by: syzbot+4faa160fa96bfba639f8@syzkaller.appspotmail.com +Reported-by: Jun Nie +Signed-off-by: Ye Bin +Link: https://lore.kernel.org/r/20221206144134.1919987-1-yebin@huaweicloud.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/inode.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -1315,7 +1315,8 @@ static int ext4_write_end(struct file *f + + trace_ext4_write_end(inode, pos, len, copied); + +- if (ext4_has_inline_data(inode)) ++ if (ext4_has_inline_data(inode) && ++ ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) + return ext4_write_inline_data_end(inode, pos, len, copied, page); + + copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); diff --git a/queue-6.1/ext4-init-quota-for-old.inode-in-ext4_rename.patch b/queue-6.1/ext4-init-quota-for-old.inode-in-ext4_rename.patch new file mode 100644 index 00000000000..921ed3dda21 --- /dev/null +++ b/queue-6.1/ext4-init-quota-for-old.inode-in-ext4_rename.patch @@ -0,0 +1,77 @@ +From fae381a3d79bb94aa2eb752170d47458d778b797 Mon Sep 17 00:00:00 2001 +From: Ye Bin +Date: Mon, 7 Nov 2022 09:53:35 +0800 +Subject: ext4: init quota for 'old.inode' in 'ext4_rename' + +From: Ye Bin + +commit fae381a3d79bb94aa2eb752170d47458d778b797 upstream. + +Syzbot found the following issue: +ext4_parse_param: s_want_extra_isize=128 +ext4_inode_info_init: s_want_extra_isize=32 +ext4_rename: old.inode=ffff88823869a2c8 old.dir=ffff888238699828 new.inode=ffff88823869d7e8 new.dir=ffff888238699828 +__ext4_mark_inode_dirty: inode=ffff888238699828 ea_isize=32 want_ea_size=128 +__ext4_mark_inode_dirty: inode=ffff88823869a2c8 ea_isize=32 want_ea_size=128 +ext4_xattr_block_set: inode=ffff88823869a2c8 +------------[ cut here ]------------ +WARNING: CPU: 13 PID: 2234 at fs/ext4/xattr.c:2070 ext4_xattr_block_set.cold+0x22/0x980 +Modules linked in: +RIP: 0010:ext4_xattr_block_set.cold+0x22/0x980 +RSP: 0018:ffff888227d3f3b0 EFLAGS: 00010202 +RAX: 0000000000000001 RBX: ffff88823007a000 RCX: 0000000000000000 +RDX: 0000000000000a03 RSI: 0000000000000040 RDI: ffff888230078178 +RBP: 0000000000000000 R08: 000000000000002c R09: ffffed1075c7df8e +R10: ffff8883ae3efc6b R11: ffffed1075c7df8d R12: 0000000000000000 +R13: ffff88823869a2c8 R14: ffff8881012e0460 R15: dffffc0000000000 +FS: 00007f350ac1f740(0000) GS:ffff8883ae200000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f350a6ed6a0 CR3: 0000000237456000 CR4: 00000000000006e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + + ? ext4_xattr_set_entry+0x3b7/0x2320 + ? ext4_xattr_block_set+0x0/0x2020 + ? ext4_xattr_set_entry+0x0/0x2320 + ? ext4_xattr_check_entries+0x77/0x310 + ? ext4_xattr_ibody_set+0x23b/0x340 + ext4_xattr_move_to_block+0x594/0x720 + ext4_expand_extra_isize_ea+0x59a/0x10f0 + __ext4_expand_extra_isize+0x278/0x3f0 + __ext4_mark_inode_dirty.cold+0x347/0x410 + ext4_rename+0xed3/0x174f + vfs_rename+0x13a7/0x2510 + do_renameat2+0x55d/0x920 + __x64_sys_rename+0x7d/0xb0 + do_syscall_64+0x3b/0xa0 + entry_SYSCALL_64_after_hwframe+0x72/0xdc + +As 'ext4_rename' will modify 'old.inode' ctime and mark inode dirty, +which may trigger expand 'extra_isize' and allocate block. If inode +didn't init quota will lead to warning. To solve above issue, init +'old.inode' firstly in 'ext4_rename'. + +Reported-by: syzbot+98346927678ac3059c77@syzkaller.appspotmail.com +Signed-off-by: Ye Bin +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20221107015335.2524319-1-yebin@huaweicloud.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/namei.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -3798,6 +3798,9 @@ static int ext4_rename(struct user_names + retval = dquot_initialize(old.dir); + if (retval) + return retval; ++ retval = dquot_initialize(old.inode); ++ if (retval) ++ return retval; + retval = dquot_initialize(new.dir); + if (retval) + return retval; diff --git a/queue-6.1/ext4-initialize-quota-before-expanding-inode-in-setproject-ioctl.patch b/queue-6.1/ext4-initialize-quota-before-expanding-inode-in-setproject-ioctl.patch new file mode 100644 index 00000000000..912b196ed0b --- /dev/null +++ b/queue-6.1/ext4-initialize-quota-before-expanding-inode-in-setproject-ioctl.patch @@ -0,0 +1,47 @@ +From 1485f726c6dec1a1f85438f2962feaa3d585526f Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 7 Dec 2022 12:59:27 +0100 +Subject: ext4: initialize quota before expanding inode in setproject ioctl + +From: Jan Kara + +commit 1485f726c6dec1a1f85438f2962feaa3d585526f upstream. + +Make sure we initialize quotas before possibly expanding inode space +(and thus maybe needing to allocate external xattr block) in +ext4_ioctl_setproject(). This prevents not accounting the necessary +block allocation. + +Signed-off-by: Jan Kara +Cc: stable@kernel.org +Link: https://lore.kernel.org/r/20221207115937.26601-1-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ioctl.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -732,6 +732,10 @@ static int ext4_ioctl_setproject(struct + if (ext4_is_quota_file(inode)) + return err; + ++ err = dquot_initialize(inode); ++ if (err) ++ return err; ++ + err = ext4_get_inode_loc(inode, &iloc); + if (err) + return err; +@@ -747,10 +751,6 @@ static int ext4_ioctl_setproject(struct + brelse(iloc.bh); + } + +- err = dquot_initialize(inode); +- if (err) +- return err; +- + handle = ext4_journal_start(inode, EXT4_HT_QUOTA, + EXT4_QUOTA_INIT_BLOCKS(sb) + + EXT4_QUOTA_DEL_BLOCKS(sb) + 3); diff --git a/queue-6.1/series b/queue-6.1/series index 8415f2af442..16b9ffdab7a 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -180,3 +180,18 @@ ext4-add-missing-validation-of-fast-commit-record-lengths.patch ext4-fix-unaligned-memory-access-in-ext4_fc_reserve_space.patch ext4-fix-off-by-one-errors-in-fast-commit-block-filling.patch ext4-fix-uninititialized-value-in-ext4_evict_inode.patch +ext4-init-quota-for-old.inode-in-ext4_rename.patch +ext4-don-t-fail-getfsuuid-when-the-caller-provides-a-long-buffer.patch +ext4-fix-delayed-allocation-bug-in-ext4_clu_mapped-for-bigalloc-inline.patch +ext4-fix-corruption-when-online-resizing-a-1k-bigalloc-fs.patch +ext4-fix-error-code-return-to-user-space-in-ext4_get_branch.patch +ext4-fix-bad-checksum-after-online-resize.patch +ext4-dont-return-einval-from-getfsuuid-when-reporting-uuid-length.patch +ext4-fix-corrupt-backup-group-descriptors-after-online-resize.patch +ext4-avoid-bug_on-when-creating-xattrs.patch +ext4-fix-deadlock-due-to-mbcache-entry-corruption.patch +ext4-fix-kernel-bug-in-ext4_write_inline_data_end.patch +ext4-fix-inode-leak-in-ext4_xattr_inode_create-on-an-error-path.patch +ext4-initialize-quota-before-expanding-inode-in-setproject-ioctl.patch +ext4-avoid-unaccounted-block-allocation-when-expanding-inode.patch +ext4-allocate-extended-attribute-value-in-vmalloc-area.patch