aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/xattr.c92
1 files changed, 77 insertions, 15 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index e88748e55c0f..e56c9ed7d6e3 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -122,6 +122,58 @@ const struct xattr_handler *ext4_xattr_handlers[] = {
122 NULL 122 NULL
123}; 123};
124 124
125static __le32 ext4_xattr_block_csum(struct inode *inode,
126 sector_t block_nr,
127 struct ext4_xattr_header *hdr)
128{
129 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
130 struct ext4_inode_info *ei = EXT4_I(inode);
131 __u32 csum, old;
132
133 old = hdr->h_checksum;
134 hdr->h_checksum = 0;
135 if (le32_to_cpu(hdr->h_refcount) != 1) {
136 block_nr = cpu_to_le64(block_nr);
137 csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&block_nr,
138 sizeof(block_nr));
139 } else
140 csum = ei->i_csum_seed;
141 csum = ext4_chksum(sbi, csum, (__u8 *)hdr,
142 EXT4_BLOCK_SIZE(inode->i_sb));
143 hdr->h_checksum = old;
144 return cpu_to_le32(csum);
145}
146
147static int ext4_xattr_block_csum_verify(struct inode *inode,
148 sector_t block_nr,
149 struct ext4_xattr_header *hdr)
150{
151 if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
152 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
153 (hdr->h_checksum != ext4_xattr_block_csum(inode, block_nr, hdr)))
154 return 0;
155 return 1;
156}
157
158static void ext4_xattr_block_csum_set(struct inode *inode,
159 sector_t block_nr,
160 struct ext4_xattr_header *hdr)
161{
162 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
163 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
164 return;
165
166 hdr->h_checksum = ext4_xattr_block_csum(inode, block_nr, hdr);
167}
168
169static inline int ext4_handle_dirty_xattr_block(handle_t *handle,
170 struct inode *inode,
171 struct buffer_head *bh)
172{
173 ext4_xattr_block_csum_set(inode, bh->b_blocknr, BHDR(bh));
174 return ext4_handle_dirty_metadata(handle, inode, bh);
175}
176
125static inline const struct xattr_handler * 177static inline const struct xattr_handler *
126ext4_xattr_handler(int name_index) 178ext4_xattr_handler(int name_index)
127{ 179{
@@ -156,12 +208,22 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end)
156} 208}
157 209
158static inline int 210static inline int
159ext4_xattr_check_block(struct buffer_head *bh) 211ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh)
160{ 212{
213 int error;
214
215 if (buffer_verified(bh))
216 return 0;
217
161 if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || 218 if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
162 BHDR(bh)->h_blocks != cpu_to_le32(1)) 219 BHDR(bh)->h_blocks != cpu_to_le32(1))
163 return -EIO; 220 return -EIO;
164 return ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size); 221 if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh)))
222 return -EIO;
223 error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size);
224 if (!error)
225 set_buffer_verified(bh);
226 return error;
165} 227}
166 228
167static inline int 229static inline int
@@ -224,7 +286,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
224 goto cleanup; 286 goto cleanup;
225 ea_bdebug(bh, "b_count=%d, refcount=%d", 287 ea_bdebug(bh, "b_count=%d, refcount=%d",
226 atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount)); 288 atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
227 if (ext4_xattr_check_block(bh)) { 289 if (ext4_xattr_check_block(inode, bh)) {
228bad_block: 290bad_block:
229 EXT4_ERROR_INODE(inode, "bad block %llu", 291 EXT4_ERROR_INODE(inode, "bad block %llu",
230 EXT4_I(inode)->i_file_acl); 292 EXT4_I(inode)->i_file_acl);
@@ -369,7 +431,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
369 goto cleanup; 431 goto cleanup;
370 ea_bdebug(bh, "b_count=%d, refcount=%d", 432 ea_bdebug(bh, "b_count=%d, refcount=%d",
371 atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount)); 433 atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
372 if (ext4_xattr_check_block(bh)) { 434 if (ext4_xattr_check_block(inode, bh)) {
373 EXT4_ERROR_INODE(inode, "bad block %llu", 435 EXT4_ERROR_INODE(inode, "bad block %llu",
374 EXT4_I(inode)->i_file_acl); 436 EXT4_I(inode)->i_file_acl);
375 error = -EIO; 437 error = -EIO;
@@ -492,7 +554,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
492 if (ce) 554 if (ce)
493 mb_cache_entry_release(ce); 555 mb_cache_entry_release(ce);
494 unlock_buffer(bh); 556 unlock_buffer(bh);
495 error = ext4_handle_dirty_metadata(handle, inode, bh); 557 error = ext4_handle_dirty_xattr_block(handle, inode, bh);
496 if (IS_SYNC(inode)) 558 if (IS_SYNC(inode))
497 ext4_handle_sync(handle); 559 ext4_handle_sync(handle);
498 dquot_free_block(inode, 1); 560 dquot_free_block(inode, 1);
@@ -662,7 +724,7 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
662 ea_bdebug(bs->bh, "b_count=%d, refcount=%d", 724 ea_bdebug(bs->bh, "b_count=%d, refcount=%d",
663 atomic_read(&(bs->bh->b_count)), 725 atomic_read(&(bs->bh->b_count)),
664 le32_to_cpu(BHDR(bs->bh)->h_refcount)); 726 le32_to_cpu(BHDR(bs->bh)->h_refcount));
665 if (ext4_xattr_check_block(bs->bh)) { 727 if (ext4_xattr_check_block(inode, bs->bh)) {
666 EXT4_ERROR_INODE(inode, "bad block %llu", 728 EXT4_ERROR_INODE(inode, "bad block %llu",
667 EXT4_I(inode)->i_file_acl); 729 EXT4_I(inode)->i_file_acl);
668 error = -EIO; 730 error = -EIO;
@@ -725,9 +787,9 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
725 if (error == -EIO) 787 if (error == -EIO)
726 goto bad_block; 788 goto bad_block;
727 if (!error) 789 if (!error)
728 error = ext4_handle_dirty_metadata(handle, 790 error = ext4_handle_dirty_xattr_block(handle,
729 inode, 791 inode,
730 bs->bh); 792 bs->bh);
731 if (error) 793 if (error)
732 goto cleanup; 794 goto cleanup;
733 goto inserted; 795 goto inserted;
@@ -796,9 +858,9 @@ inserted:
796 ea_bdebug(new_bh, "reusing; refcount now=%d", 858 ea_bdebug(new_bh, "reusing; refcount now=%d",
797 le32_to_cpu(BHDR(new_bh)->h_refcount)); 859 le32_to_cpu(BHDR(new_bh)->h_refcount));
798 unlock_buffer(new_bh); 860 unlock_buffer(new_bh);
799 error = ext4_handle_dirty_metadata(handle, 861 error = ext4_handle_dirty_xattr_block(handle,
800 inode, 862 inode,
801 new_bh); 863 new_bh);
802 if (error) 864 if (error)
803 goto cleanup_dquot; 865 goto cleanup_dquot;
804 } 866 }
@@ -855,8 +917,8 @@ getblk_failed:
855 set_buffer_uptodate(new_bh); 917 set_buffer_uptodate(new_bh);
856 unlock_buffer(new_bh); 918 unlock_buffer(new_bh);
857 ext4_xattr_cache_insert(new_bh); 919 ext4_xattr_cache_insert(new_bh);
858 error = ext4_handle_dirty_metadata(handle, 920 error = ext4_handle_dirty_xattr_block(handle,
859 inode, new_bh); 921 inode, new_bh);
860 if (error) 922 if (error)
861 goto cleanup; 923 goto cleanup;
862 } 924 }
@@ -1193,7 +1255,7 @@ retry:
1193 error = -EIO; 1255 error = -EIO;
1194 if (!bh) 1256 if (!bh)
1195 goto cleanup; 1257 goto cleanup;
1196 if (ext4_xattr_check_block(bh)) { 1258 if (ext4_xattr_check_block(inode, bh)) {
1197 EXT4_ERROR_INODE(inode, "bad block %llu", 1259 EXT4_ERROR_INODE(inode, "bad block %llu",
1198 EXT4_I(inode)->i_file_acl); 1260 EXT4_I(inode)->i_file_acl);
1199 error = -EIO; 1261 error = -EIO;