diff options
| -rw-r--r-- | fs/ext4/xattr.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index da4df703c211..42823ab3718c 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
| @@ -190,14 +190,28 @@ ext4_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | static int | 192 | static int |
| 193 | ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end) | 193 | ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end, |
| 194 | void *value_start) | ||
| 194 | { | 195 | { |
| 195 | while (!IS_LAST_ENTRY(entry)) { | 196 | struct ext4_xattr_entry *e = entry; |
| 196 | struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(entry); | 197 | |
| 198 | while (!IS_LAST_ENTRY(e)) { | ||
| 199 | struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e); | ||
| 197 | if ((void *)next >= end) | 200 | if ((void *)next >= end) |
| 198 | return -EIO; | 201 | return -EIO; |
| 199 | entry = next; | 202 | e = next; |
| 200 | } | 203 | } |
| 204 | |||
| 205 | while (!IS_LAST_ENTRY(entry)) { | ||
| 206 | if (entry->e_value_size != 0 && | ||
| 207 | (value_start + le16_to_cpu(entry->e_value_offs) < | ||
| 208 | (void *)e + sizeof(__u32) || | ||
| 209 | value_start + le16_to_cpu(entry->e_value_offs) + | ||
| 210 | le32_to_cpu(entry->e_value_size) > end)) | ||
| 211 | return -EIO; | ||
| 212 | entry = EXT4_XATTR_NEXT(entry); | ||
| 213 | } | ||
| 214 | |||
| 201 | return 0; | 215 | return 0; |
| 202 | } | 216 | } |
| 203 | 217 | ||
| @@ -214,7 +228,8 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) | |||
| 214 | return -EIO; | 228 | return -EIO; |
| 215 | if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) | 229 | if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) |
| 216 | return -EIO; | 230 | return -EIO; |
| 217 | error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size); | 231 | error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, |
| 232 | bh->b_data); | ||
| 218 | if (!error) | 233 | if (!error) |
| 219 | set_buffer_verified(bh); | 234 | set_buffer_verified(bh); |
| 220 | return error; | 235 | return error; |
| @@ -331,7 +346,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, | |||
| 331 | header = IHDR(inode, raw_inode); | 346 | header = IHDR(inode, raw_inode); |
| 332 | entry = IFIRST(header); | 347 | entry = IFIRST(header); |
| 333 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; | 348 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
| 334 | error = ext4_xattr_check_names(entry, end); | 349 | error = ext4_xattr_check_names(entry, end, entry); |
| 335 | if (error) | 350 | if (error) |
| 336 | goto cleanup; | 351 | goto cleanup; |
| 337 | error = ext4_xattr_find_entry(&entry, name_index, name, | 352 | error = ext4_xattr_find_entry(&entry, name_index, name, |
| @@ -463,7 +478,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
| 463 | raw_inode = ext4_raw_inode(&iloc); | 478 | raw_inode = ext4_raw_inode(&iloc); |
| 464 | header = IHDR(inode, raw_inode); | 479 | header = IHDR(inode, raw_inode); |
| 465 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; | 480 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
| 466 | error = ext4_xattr_check_names(IFIRST(header), end); | 481 | error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header)); |
| 467 | if (error) | 482 | if (error) |
| 468 | goto cleanup; | 483 | goto cleanup; |
| 469 | error = ext4_xattr_list_entries(dentry, IFIRST(header), | 484 | error = ext4_xattr_list_entries(dentry, IFIRST(header), |
| @@ -980,7 +995,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, | |||
| 980 | is->s.here = is->s.first; | 995 | is->s.here = is->s.first; |
| 981 | is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; | 996 | is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
| 982 | if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { | 997 | if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { |
| 983 | error = ext4_xattr_check_names(IFIRST(header), is->s.end); | 998 | error = ext4_xattr_check_names(IFIRST(header), is->s.end, |
| 999 | IFIRST(header)); | ||
| 984 | if (error) | 1000 | if (error) |
| 985 | return error; | 1001 | return error; |
| 986 | /* Find the named attribute. */ | 1002 | /* Find the named attribute. */ |
