diff options
Diffstat (limited to 'fs/ext4/xattr.c')
-rw-r--r-- | fs/ext4/xattr.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index e7387337060c..1e09fc77395c 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -142,8 +142,7 @@ static int ext4_xattr_block_csum_verify(struct inode *inode, | |||
142 | sector_t block_nr, | 142 | sector_t block_nr, |
143 | struct ext4_xattr_header *hdr) | 143 | struct ext4_xattr_header *hdr) |
144 | { | 144 | { |
145 | if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 145 | if (ext4_has_metadata_csum(inode->i_sb) && |
146 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && | ||
147 | (hdr->h_checksum != ext4_xattr_block_csum(inode, block_nr, hdr))) | 146 | (hdr->h_checksum != ext4_xattr_block_csum(inode, block_nr, hdr))) |
148 | return 0; | 147 | return 0; |
149 | return 1; | 148 | return 1; |
@@ -153,8 +152,7 @@ static void ext4_xattr_block_csum_set(struct inode *inode, | |||
153 | sector_t block_nr, | 152 | sector_t block_nr, |
154 | struct ext4_xattr_header *hdr) | 153 | struct ext4_xattr_header *hdr) |
155 | { | 154 | { |
156 | if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 155 | if (!ext4_has_metadata_csum(inode->i_sb)) |
157 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
158 | return; | 156 | return; |
159 | 157 | ||
160 | hdr->h_checksum = ext4_xattr_block_csum(inode, block_nr, hdr); | 158 | hdr->h_checksum = ext4_xattr_block_csum(inode, block_nr, hdr); |
@@ -190,14 +188,28 @@ ext4_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
190 | } | 188 | } |
191 | 189 | ||
192 | static int | 190 | static int |
193 | ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end) | 191 | ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end, |
192 | void *value_start) | ||
194 | { | 193 | { |
195 | while (!IS_LAST_ENTRY(entry)) { | 194 | struct ext4_xattr_entry *e = entry; |
196 | struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(entry); | 195 | |
196 | while (!IS_LAST_ENTRY(e)) { | ||
197 | struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e); | ||
197 | if ((void *)next >= end) | 198 | if ((void *)next >= end) |
198 | return -EIO; | 199 | return -EIO; |
199 | entry = next; | 200 | e = next; |
200 | } | 201 | } |
202 | |||
203 | while (!IS_LAST_ENTRY(entry)) { | ||
204 | if (entry->e_value_size != 0 && | ||
205 | (value_start + le16_to_cpu(entry->e_value_offs) < | ||
206 | (void *)e + sizeof(__u32) || | ||
207 | value_start + le16_to_cpu(entry->e_value_offs) + | ||
208 | le32_to_cpu(entry->e_value_size) > end)) | ||
209 | return -EIO; | ||
210 | entry = EXT4_XATTR_NEXT(entry); | ||
211 | } | ||
212 | |||
201 | return 0; | 213 | return 0; |
202 | } | 214 | } |
203 | 215 | ||
@@ -214,7 +226,8 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) | |||
214 | return -EIO; | 226 | return -EIO; |
215 | if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) | 227 | if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) |
216 | return -EIO; | 228 | return -EIO; |
217 | error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size); | 229 | error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, |
230 | bh->b_data); | ||
218 | if (!error) | 231 | if (!error) |
219 | set_buffer_verified(bh); | 232 | set_buffer_verified(bh); |
220 | return error; | 233 | return error; |
@@ -331,7 +344,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, | |||
331 | header = IHDR(inode, raw_inode); | 344 | header = IHDR(inode, raw_inode); |
332 | entry = IFIRST(header); | 345 | entry = IFIRST(header); |
333 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; | 346 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
334 | error = ext4_xattr_check_names(entry, end); | 347 | error = ext4_xattr_check_names(entry, end, entry); |
335 | if (error) | 348 | if (error) |
336 | goto cleanup; | 349 | goto cleanup; |
337 | error = ext4_xattr_find_entry(&entry, name_index, name, | 350 | error = ext4_xattr_find_entry(&entry, name_index, name, |
@@ -463,7 +476,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
463 | raw_inode = ext4_raw_inode(&iloc); | 476 | raw_inode = ext4_raw_inode(&iloc); |
464 | header = IHDR(inode, raw_inode); | 477 | header = IHDR(inode, raw_inode); |
465 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; | 478 | end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
466 | error = ext4_xattr_check_names(IFIRST(header), end); | 479 | error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header)); |
467 | if (error) | 480 | if (error) |
468 | goto cleanup; | 481 | goto cleanup; |
469 | error = ext4_xattr_list_entries(dentry, IFIRST(header), | 482 | error = ext4_xattr_list_entries(dentry, IFIRST(header), |
@@ -899,14 +912,8 @@ inserted: | |||
899 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) | 912 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
900 | goal = goal & EXT4_MAX_BLOCK_FILE_PHYS; | 913 | goal = goal & EXT4_MAX_BLOCK_FILE_PHYS; |
901 | 914 | ||
902 | /* | ||
903 | * take i_data_sem because we will test | ||
904 | * i_delalloc_reserved_flag in ext4_mb_new_blocks | ||
905 | */ | ||
906 | down_read(&EXT4_I(inode)->i_data_sem); | ||
907 | block = ext4_new_meta_blocks(handle, inode, goal, 0, | 915 | block = ext4_new_meta_blocks(handle, inode, goal, 0, |
908 | NULL, &error); | 916 | NULL, &error); |
909 | up_read((&EXT4_I(inode)->i_data_sem)); | ||
910 | if (error) | 917 | if (error) |
911 | goto cleanup; | 918 | goto cleanup; |
912 | 919 | ||
@@ -986,7 +993,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, | |||
986 | is->s.here = is->s.first; | 993 | is->s.here = is->s.first; |
987 | is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; | 994 | is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; |
988 | if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { | 995 | if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { |
989 | error = ext4_xattr_check_names(IFIRST(header), is->s.end); | 996 | error = ext4_xattr_check_names(IFIRST(header), is->s.end, |
997 | IFIRST(header)); | ||
990 | if (error) | 998 | if (error) |
991 | return error; | 999 | return error; |
992 | /* Find the named attribute. */ | 1000 | /* Find the named attribute. */ |