Fix a number of bug fixes, including some regressions, the most

serious of which was one which would cause online resizes to fail with
 file systems with metadata checksums enabled.  Also fix a warning
 caused by the newly added fortify string checker, plus some bugs that
 were found using fuzzed file systems.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEK2m5VNv+CHkogTfJ8vlZVpUNgaMFAmNnSCYACgkQ8vlZVpUN
 gaNbBgf/QsOe7KCrr/X7mK7SFgbNY+jsmvagPV0SvAg9Uc0P3EkmXE0NcNcZOAUx
 mgNBYNNS+QGKtdqHBy8p1kNgcbFAR/OJZ7rFD3XUnB/N+XKZSgimhNUx+IaEX7Dx
 XidK5cPcKEZlbfuqxwkIfvaqC9v3XcpFpHicA/uDTPe4kZ8VhJQk294M5EuMA8lQ
 wumDFsf/1sN4osJH7eHMZk/e3iFN8fwrpCgvwJ56zzW7UWSl8jJrq9kxHo43iijY
 82DbRCdsVrdTPaD5gJSvcggLgMpUu+yoA1UbwiUlR1AtmaFfDg+rfIZs1ooyCdHl
 QLQ3RlXdkfHTwAYBFFApzR55MhPakQ==
 =zw2b
 -----END PGP SIGNATURE-----

Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 fixes from Ted Ts'o:
 "Fix a number of bugs, including some regressions, the most serious of
  which was one which would cause online resizes to fail with file
  systems with metadata checksums enabled.

  Also fix a warning caused by the newly added fortify string checker,
  plus some bugs that were found using fuzzed file systems"

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: fix fortify warning in fs/ext4/fast_commit.c:1551
  ext4: fix wrong return err in ext4_load_and_init_journal()
  ext4: fix warning in 'ext4_da_release_space'
  ext4: fix BUG_ON() when directory entry has invalid rec_len
  ext4: update the backup superblock's at the end of the online resize
This commit is contained in:
Linus Torvalds 2022-11-06 10:30:29 -08:00
commit 9761070d14
6 changed files with 21 additions and 7 deletions

View File

@ -1521,6 +1521,7 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl,
struct ext4_iloc iloc; struct ext4_iloc iloc;
int inode_len, ino, ret, tag = tl->fc_tag; int inode_len, ino, ret, tag = tl->fc_tag;
struct ext4_extent_header *eh; struct ext4_extent_header *eh;
size_t off_gen = offsetof(struct ext4_inode, i_generation);
memcpy(&fc_inode, val, sizeof(fc_inode)); memcpy(&fc_inode, val, sizeof(fc_inode));
@ -1548,8 +1549,8 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl,
raw_inode = ext4_raw_inode(&iloc); raw_inode = ext4_raw_inode(&iloc);
memcpy(raw_inode, raw_fc_inode, offsetof(struct ext4_inode, i_block)); memcpy(raw_inode, raw_fc_inode, offsetof(struct ext4_inode, i_block));
memcpy(&raw_inode->i_generation, &raw_fc_inode->i_generation, memcpy((u8 *)raw_inode + off_gen, (u8 *)raw_fc_inode + off_gen,
inode_len - offsetof(struct ext4_inode, i_generation)); inode_len - off_gen);
if (le32_to_cpu(raw_inode->i_flags) & EXT4_EXTENTS_FL) { if (le32_to_cpu(raw_inode->i_flags) & EXT4_EXTENTS_FL) {
eh = (struct ext4_extent_header *)(&raw_inode->i_block[0]); eh = (struct ext4_extent_header *)(&raw_inode->i_block[0]);
if (eh->eh_magic != EXT4_EXT_MAGIC) { if (eh->eh_magic != EXT4_EXT_MAGIC) {

View File

@ -145,9 +145,8 @@ static int ext4_update_backup_sb(struct super_block *sb,
if (ext4_has_metadata_csum(sb) && if (ext4_has_metadata_csum(sb) &&
es->s_checksum != ext4_superblock_csum(sb, es)) { es->s_checksum != ext4_superblock_csum(sb, es)) {
ext4_msg(sb, KERN_ERR, "Invalid checksum for backup " ext4_msg(sb, KERN_ERR, "Invalid checksum for backup "
"superblock %llu\n", sb_block); "superblock %llu", sb_block);
unlock_buffer(bh); unlock_buffer(bh);
err = -EFSBADCRC;
goto out_bh; goto out_bh;
} }
func(es, arg); func(es, arg);

View File

@ -424,7 +424,8 @@ int ext4_ext_migrate(struct inode *inode)
* already is extent-based, error out. * already is extent-based, error out.
*/ */
if (!ext4_has_feature_extents(inode->i_sb) || if (!ext4_has_feature_extents(inode->i_sb) ||
(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) ||
ext4_has_inline_data(inode))
return -EINVAL; return -EINVAL;
if (S_ISLNK(inode->i_mode) && inode->i_blocks == 0) if (S_ISLNK(inode->i_mode) && inode->i_blocks == 0)

View File

@ -2259,8 +2259,16 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
memset(de, 0, len); /* wipe old data */ memset(de, 0, len); /* wipe old data */
de = (struct ext4_dir_entry_2 *) data2; de = (struct ext4_dir_entry_2 *) data2;
top = data2 + len; top = data2 + len;
while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top) while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top) {
if (ext4_check_dir_entry(dir, NULL, de, bh2, data2, len,
(data2 + (blocksize - csum_size) -
(char *) de))) {
brelse(bh2);
brelse(bh);
return -EFSCORRUPTED;
}
de = de2; de = de2;
}
de->rec_len = ext4_rec_len_to_disk(data2 + (blocksize - csum_size) - de->rec_len = ext4_rec_len_to_disk(data2 + (blocksize - csum_size) -
(char *) de, blocksize); (char *) de, blocksize);

View File

@ -1158,6 +1158,7 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
while (group < sbi->s_groups_count) { while (group < sbi->s_groups_count) {
struct buffer_head *bh; struct buffer_head *bh;
ext4_fsblk_t backup_block; ext4_fsblk_t backup_block;
struct ext4_super_block *es;
/* Out of journal space, and can't get more - abort - so sad */ /* Out of journal space, and can't get more - abort - so sad */
err = ext4_resize_ensure_credits_batch(handle, 1); err = ext4_resize_ensure_credits_batch(handle, 1);
@ -1186,6 +1187,10 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
memcpy(bh->b_data, data, size); memcpy(bh->b_data, data, size);
if (rest) if (rest)
memset(bh->b_data + size, 0, 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);
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
unlock_buffer(bh); unlock_buffer(bh);
err = ext4_handle_dirty_metadata(handle, NULL, bh); err = ext4_handle_dirty_metadata(handle, NULL, bh);

View File

@ -4881,7 +4881,7 @@ out:
flush_work(&sbi->s_error_work); flush_work(&sbi->s_error_work);
jbd2_journal_destroy(sbi->s_journal); jbd2_journal_destroy(sbi->s_journal);
sbi->s_journal = NULL; sbi->s_journal = NULL;
return err; return -EINVAL;
} }
static int ext4_journal_data_mode_check(struct super_block *sb) static int ext4_journal_data_mode_check(struct super_block *sb)