FAILED: patch "[PATCH] ext4: add missing validation of fast-commit record lengths" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
Possible dependencies:
64b4a25c3de8 ("ext4: add missing validation of fast-commit record lengths") 1b45cc5c7b92 ("ext4: fix potential out of bound read in ext4_fc_replay_scan()") dcc5827484d6 ("ext4: factor out ext4_fc_get_tl()")fdc2a3c75dd8 ("ext4: introduce EXT4_FC_TAG_BASE_LEN helper") ccbf8eeb39f2 ("ext4: fix miss release buffer head in ext4_fc_write_inode") 4978c659e7b5 ("ext4: use ext4_debug() instead of jbd_debug()") d9bf099cb980 ("ext4: add commit_tid info in jbd debug log") 0915e464cb27 ("ext4: simplify updating of fast commit stats") 7bbbe241ec7c ("ext4: drop ineligible txn start stop APIs")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 64b4a25c3de81a69724e888ec2db3533b43816e2 Mon Sep 17 00:00:00 2001
From: Eric Biggers <[email protected]>
Date: Sun, 6 Nov 2022 14:48:38 -0800
Subject: [PATCH] ext4: add missing validation of fast-commit record lengths
Validate the inode and filename lengths in fast-commit journal records so that a malicious fast-commit journal cannot cause a crash by having invalid values for these. Also validate EXT4_FC_TAG_DEL_RANGE.
fs/ext4/fast_commit.c +19 -19
@@ -1991,32 +1991,31 @@ void ext4_fc_replay_cleanup(struct super_block *sb)kfree (sbi->s_fc_replay_state.fc_modified_inodes); } -static inline bool ext4_fc_tag_len_isvalid (struct ext4_fc_tl *tl, -u8 *val,u8 *end) +static bool ext4_fc_value_len_isvalid (struct ext4_sb_info *sbi, +int tag,int len) { -if (val + tl->fc_len > end) -return false; - -/* Here only check ADD_RANGE/TAIL/HEAD which will read data when do -* journal rescan before do CRC check. Other tags length check will -* rely on CRC check. -*/ -switch (tl->fc_tag) { +switch (tag) {case EXT4_FC_TAG_ADD_RANGE : -return (sizeof (struct ext4_fc_add_range ) == tl->fc_len); -case EXT4_FC_TAG_TAIL : -return (sizeof (struct ext4_fc_tail ) <= tl->fc_len); -case EXT4_FC_TAG_HEAD : -return (sizeof (struct ext4_fc_head ) == tl->fc_len); +return len ==sizeof (struct ext4_fc_add_range );case EXT4_FC_TAG_DEL_RANGE : +return len ==sizeof (struct ext4_fc_del_range ); +case EXT4_FC_TAG_CREAT :case EXT4_FC_TAG_LINK :case EXT4_FC_TAG_UNLINK : -case EXT4_FC_TAG_CREAT : + len -=sizeof (struct ext4_fc_dentry_info ); +return len >=1 && len <=EXT4_NAME_LEN ;case EXT4_FC_TAG_INODE : + len -=sizeof (struct ext4_fc_inode ); +return len >=EXT4_GOOD_OLD_INODE_SIZE && + len <= sbi->s_inode_size;case EXT4_FC_TAG_PAD : -default : -return true; +return true;/* padding can have any length */ +case EXT4_FC_TAG_TAIL : +return len >=sizeof (struct ext4_fc_tail ); +case EXT4_FC_TAG_HEAD : +return len ==sizeof (struct ext4_fc_head ); } +return false; }/*
@@ -2079,7 +2078,8 @@ static int ext4_fc_replay_scan(journal_t *journal, cur = cur + EXT4_FC_TAG_BASE_LEN + tl.fc_len) {ext4_fc_get_tl (&tl, cur); val = cur +EXT4_FC_TAG_BASE_LEN ; -if (!ext4_fc_tag_len_isvalid (&tl, val, end)) { +if (tl.fc_len > end - val || + !ext4_fc_value_len_isvalid (sbi, tl.fc_tag, tl.fc_len)) { ret = state->fc_replay_num_tags ?JBD2_FC_REPLAY_STOP : -ECANCELED ; goto out_err;
fs/ext4/fast_commit.h +1 -1
@@ -58,7 +58,7 @@ struct ext4_fc_dentry_info {__u8 fc_dname[]; }; -/* Value structure for EXT4_FC_TAG_INODE and EXT4_FC_TAG_INODE_PARTIAL. */ +/* Value structure for EXT4_FC_TAG_INODE. */ struct ext4_fc_inode {__le32 fc_ino;__u8 fc_raw_inode[];