aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/xattr.c')
-rw-r--r--fs/ext4/xattr.c44
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
192static int 190static int
193ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end) 191ext4_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. */