diff options
Diffstat (limited to 'fs/ext4/xattr.c')
-rw-r--r-- | fs/ext4/xattr.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 0441e055c8e8..e79bd32b9b79 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -230,6 +230,27 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) | |||
230 | return error; | 230 | return error; |
231 | } | 231 | } |
232 | 232 | ||
233 | static int | ||
234 | __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header, | ||
235 | void *end, const char *function, unsigned int line) | ||
236 | { | ||
237 | struct ext4_xattr_entry *entry = IFIRST(header); | ||
238 | int error = -EFSCORRUPTED; | ||
239 | |||
240 | if (((void *) header >= end) || | ||
241 | (header->h_magic != le32_to_cpu(EXT4_XATTR_MAGIC))) | ||
242 | goto errout; | ||
243 | error = ext4_xattr_check_names(entry, end, entry); | ||
244 | errout: | ||
245 | if (error) | ||
246 | __ext4_error_inode(inode, function, line, 0, | ||
247 | "corrupted in-inode xattr"); | ||
248 | return error; | ||
249 | } | ||
250 | |||
251 | #define xattr_check_inode(inode, header, end) \ | ||
252 | __xattr_check_inode((inode), (header), (end), __func__, __LINE__) | ||
253 | |||
233 | static inline int | 254 | static inline int |
234 | ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size) | 255 | ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size) |
235 | { | 256 | { |
@@ -341,7 +362,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, | |||
341 | header = IHDR(inode, raw_inode); | 362 | header = IHDR(inode, raw_inode); |
342 | entry = IFIRST(header); | 363 | entry = IFIRST(header); |
343 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; | 364 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
344 | error = ext4_xattr_check_names(entry, end, entry); | 365 | error = xattr_check_inode(inode, header, end); |
345 | if (error) | 366 | if (error) |
346 | goto cleanup; | 367 | goto cleanup; |
347 | error = ext4_xattr_find_entry(&entry, name_index, name, | 368 | error = ext4_xattr_find_entry(&entry, name_index, name, |
@@ -477,7 +498,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
477 | raw_inode = ext4_raw_inode(&iloc); | 498 | raw_inode = ext4_raw_inode(&iloc); |
478 | header = IHDR(inode, raw_inode); | 499 | header = IHDR(inode, raw_inode); |
479 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; | 500 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
480 | error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header)); | 501 | error = xattr_check_inode(inode, header, end); |
481 | if (error) | 502 | if (error) |
482 | goto cleanup; | 503 | goto cleanup; |
483 | error = ext4_xattr_list_entries(dentry, IFIRST(header), | 504 | error = ext4_xattr_list_entries(dentry, IFIRST(header), |
@@ -1040,8 +1061,7 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, | |||
1040 | is->s.here = is->s.first; | 1061 | is->s.here = is->s.first; |
1041 | is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; | 1062 | is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
1042 | if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { | 1063 | if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { |
1043 | error = ext4_xattr_check_names(IFIRST(header), is->s.end, | 1064 | error = xattr_check_inode(inode, header, is->s.end); |
1044 | IFIRST(header)); | ||
1045 | if (error) | 1065 | if (error) |
1046 | return error; | 1066 | return error; |
1047 | /* Find the named attribute. */ | 1067 | /* Find the named attribute. */ |
@@ -1356,6 +1376,10 @@ retry: | |||
1356 | last = entry; | 1376 | last = entry; |
1357 | total_ino = sizeof(struct ext4_xattr_ibody_header); | 1377 | total_ino = sizeof(struct ext4_xattr_ibody_header); |
1358 | 1378 | ||
1379 | error = xattr_check_inode(inode, header, end); | ||
1380 | if (error) | ||
1381 | goto cleanup; | ||
1382 | |||
1359 | free = ext4_xattr_free_space(last, &min_offs, base, &total_ino); | 1383 | free = ext4_xattr_free_space(last, &min_offs, base, &total_ino); |
1360 | if (free >= new_extra_isize) { | 1384 | if (free >= new_extra_isize) { |
1361 | entry = IFIRST(header); | 1385 | entry = IFIRST(header); |