FAILED: patch "[PATCH] ext4: add bounds checking to ext4_xattr_find_entry()" failed to apply to 4.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.4-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]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
9496005d6ca4cf8f5ee8f828165a8956872dc59dMon Sep 17 00:00:00 2001
From: Theodore Ts'o <[email protected]>
Date: Fri, 30 Mar 2018 20:00:56 -0400
Subject: [PATCH] ext4: add bounds checking to ext4_xattr_find_entry()
Add some paranoia checks to make sure we don't stray beyond the end of the valid memory region containing ext4 xattr entries while we are scanning for a match.
Also rename the function to xattr_find_entry() since it is static and thus only used in fs/ext4/xattr.c
fs/ext4/xattr.c +17 -11
@@ -276,18 +276,22 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header, __xattr_check_inode((inode), (header), (end), __func__, __LINE__)static int -ext4_xattr_find_entry (struct ext4_xattr_entry **pentry,int name_index, -const char *name,int sorted) +xattr_find_entry (struct inode *inode,struct ext4_xattr_entry **pentry, +void *end,int name_index,const char *name,int sorted) { -struct ext4_xattr_entry *entry; +struct ext4_xattr_entry *entry, *next;size_t name_len;int cmp =1 ;if (name ==NULL )return -EINVAL ; name_len =strlen (name); - entry = *pentry; -for (; !IS_LAST_ENTRY (entry); entry =EXT4_XATTR_NEXT (entry)) { +for (entry = *pentry; !IS_LAST_ENTRY (entry); entry = next) { + next =EXT4_XATTR_NEXT (entry); +if ((void *) next >= end) { +EXT4_ERROR_INODE (inode,"corrupted xattr entries" ); +return -EFSCORRUPTED ; + } cmp = name_index - entry->e_name_index;if (!cmp) cmp = name_len - entry->e_name_len;
@@ -509,6 +513,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,struct buffer_head *bh =NULL ;struct ext4_xattr_entry *entry;size_t size; +void *end;int error;struct mb_cache *ea_block_cache =EA_BLOCK_CACHE (inode);
@@ -530,7 +535,8 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name, goto cleanup;ext4_xattr_block_cache_insert (ea_block_cache, bh); entry =BFIRST (bh); - error =ext4_xattr_find_entry (&entry, name_index, name,1 ); + end = bh->b_data + bh->b_size; + error =xattr_find_entry (inode, &entry, end, name_index, name,1 );if (error) goto cleanup; size =le32_to_cpu (entry->e_value_size);
@@ -579,7 +585,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,if (error) goto cleanup; entry =IFIRST (header); - error =ext4_xattr_find_entry (&entry, name_index, name,0 ); + error =xattr_find_entry (inode, &entry, end, name_index, name,0 );if (error) goto cleanup; size =le32_to_cpu (entry->e_value_size);
@@ -1808,8 +1814,8 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i, bs->s.first =BFIRST (bs->bh); bs->s.end = bs->bh->b_data + bs->bh->b_size; bs->s.here = bs->s.first; - error =ext4_xattr_find_entry (&bs->s.here, i->name_index, - i->name,1 ); + error =xattr_find_entry (inode, &bs->s.here, bs->s.end, + i->name_index, i->name,1 );if (error && error != -ENODATA ) goto cleanup; bs->s.not_found = error;
@@ -2168,8 +2174,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,if (error)return error;/* Find the named attribute. */ - error =ext4_xattr_find_entry (&is->s.here, i->name_index, - i->name,0 ); + error =xattr_find_entry (inode, &is->s.here, is->s.end, + i->name_index, i->name,0 );if (error && error != -ENODATA )return error; is->s.not_found = error;