diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-11-13 17:49:18 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:36:53 -0500 |
commit | 4ae1d69bedc8d174cb8a558694607e013157cde1 (patch) | |
tree | ce5c599415435d24ddc5cae88207f5f26c0a18b4 /fs/ocfs2/xattr.c | |
parent | a22305cc693254a2aa651e797875669112ef8635 (diff) |
ocfs2: Wrap xattr block reads in a dedicated function
We weren't consistently checking xattr blocks after we read them.
Most places checked the signature, but none checked xb_blkno or
xb_fs_signature. Create a toplevel ocfs2_read_xattr_block() that does
the read and the validation.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 94 |
1 files changed, 70 insertions, 24 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 3cc8385f9738..ef4aa5482d01 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -314,6 +314,65 @@ static void ocfs2_xattr_bucket_copy_data(struct ocfs2_xattr_bucket *dest, | |||
314 | } | 314 | } |
315 | } | 315 | } |
316 | 316 | ||
317 | static int ocfs2_validate_xattr_block(struct super_block *sb, | ||
318 | struct buffer_head *bh) | ||
319 | { | ||
320 | struct ocfs2_xattr_block *xb = | ||
321 | (struct ocfs2_xattr_block *)bh->b_data; | ||
322 | |||
323 | mlog(0, "Validating xattr block %llu\n", | ||
324 | (unsigned long long)bh->b_blocknr); | ||
325 | |||
326 | if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) { | ||
327 | ocfs2_error(sb, | ||
328 | "Extended attribute block #%llu has bad " | ||
329 | "signature %.*s", | ||
330 | (unsigned long long)bh->b_blocknr, 7, | ||
331 | xb->xb_signature); | ||
332 | return -EINVAL; | ||
333 | } | ||
334 | |||
335 | if (le64_to_cpu(xb->xb_blkno) != bh->b_blocknr) { | ||
336 | ocfs2_error(sb, | ||
337 | "Extended attribute block #%llu has an " | ||
338 | "invalid xb_blkno of %llu", | ||
339 | (unsigned long long)bh->b_blocknr, | ||
340 | (unsigned long long)le64_to_cpu(xb->xb_blkno)); | ||
341 | return -EINVAL; | ||
342 | } | ||
343 | |||
344 | if (le32_to_cpu(xb->xb_fs_generation) != OCFS2_SB(sb)->fs_generation) { | ||
345 | ocfs2_error(sb, | ||
346 | "Extended attribute block #%llu has an invalid " | ||
347 | "xb_fs_generation of #%u", | ||
348 | (unsigned long long)bh->b_blocknr, | ||
349 | le32_to_cpu(xb->xb_fs_generation)); | ||
350 | return -EINVAL; | ||
351 | } | ||
352 | |||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | static int ocfs2_read_xattr_block(struct inode *inode, u64 xb_blkno, | ||
357 | struct buffer_head **bh) | ||
358 | { | ||
359 | int rc; | ||
360 | struct buffer_head *tmp = *bh; | ||
361 | |||
362 | rc = ocfs2_read_block(inode, xb_blkno, &tmp); | ||
363 | if (!rc) { | ||
364 | rc = ocfs2_validate_xattr_block(inode->i_sb, tmp); | ||
365 | if (rc) | ||
366 | brelse(tmp); | ||
367 | } | ||
368 | |||
369 | /* If ocfs2_read_block() got us a new bh, pass it up. */ | ||
370 | if (!rc && !*bh) | ||
371 | *bh = tmp; | ||
372 | |||
373 | return rc; | ||
374 | } | ||
375 | |||
317 | static inline const char *ocfs2_xattr_prefix(int name_index) | 376 | static inline const char *ocfs2_xattr_prefix(int name_index) |
318 | { | 377 | { |
319 | struct xattr_handler *handler = NULL; | 378 | struct xattr_handler *handler = NULL; |
@@ -739,18 +798,14 @@ static int ocfs2_xattr_block_list(struct inode *inode, | |||
739 | if (!di->i_xattr_loc) | 798 | if (!di->i_xattr_loc) |
740 | return ret; | 799 | return ret; |
741 | 800 | ||
742 | ret = ocfs2_read_block(inode, le64_to_cpu(di->i_xattr_loc), &blk_bh); | 801 | ret = ocfs2_read_xattr_block(inode, le64_to_cpu(di->i_xattr_loc), |
802 | &blk_bh); | ||
743 | if (ret < 0) { | 803 | if (ret < 0) { |
744 | mlog_errno(ret); | 804 | mlog_errno(ret); |
745 | return ret; | 805 | return ret; |
746 | } | 806 | } |
747 | 807 | ||
748 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; | 808 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; |
749 | if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) { | ||
750 | ret = -EIO; | ||
751 | goto cleanup; | ||
752 | } | ||
753 | |||
754 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { | 809 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { |
755 | struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header; | 810 | struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header; |
756 | ret = ocfs2_xattr_list_entries(inode, header, | 811 | ret = ocfs2_xattr_list_entries(inode, header, |
@@ -760,7 +815,7 @@ static int ocfs2_xattr_block_list(struct inode *inode, | |||
760 | ret = ocfs2_xattr_tree_list_index_block(inode, xt, | 815 | ret = ocfs2_xattr_tree_list_index_block(inode, xt, |
761 | buffer, buffer_size); | 816 | buffer, buffer_size); |
762 | } | 817 | } |
763 | cleanup: | 818 | |
764 | brelse(blk_bh); | 819 | brelse(blk_bh); |
765 | 820 | ||
766 | return ret; | 821 | return ret; |
@@ -1693,24 +1748,19 @@ static int ocfs2_xattr_free_block(struct inode *inode, | |||
1693 | u64 blk, bg_blkno; | 1748 | u64 blk, bg_blkno; |
1694 | u16 bit; | 1749 | u16 bit; |
1695 | 1750 | ||
1696 | ret = ocfs2_read_block(inode, block, &blk_bh); | 1751 | ret = ocfs2_read_xattr_block(inode, block, &blk_bh); |
1697 | if (ret < 0) { | 1752 | if (ret < 0) { |
1698 | mlog_errno(ret); | 1753 | mlog_errno(ret); |
1699 | goto out; | 1754 | goto out; |
1700 | } | 1755 | } |
1701 | 1756 | ||
1702 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; | ||
1703 | if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) { | ||
1704 | ret = -EIO; | ||
1705 | goto out; | ||
1706 | } | ||
1707 | |||
1708 | ret = ocfs2_xattr_block_remove(inode, blk_bh); | 1757 | ret = ocfs2_xattr_block_remove(inode, blk_bh); |
1709 | if (ret < 0) { | 1758 | if (ret < 0) { |
1710 | mlog_errno(ret); | 1759 | mlog_errno(ret); |
1711 | goto out; | 1760 | goto out; |
1712 | } | 1761 | } |
1713 | 1762 | ||
1763 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; | ||
1714 | blk = le64_to_cpu(xb->xb_blkno); | 1764 | blk = le64_to_cpu(xb->xb_blkno); |
1715 | bit = le16_to_cpu(xb->xb_suballoc_bit); | 1765 | bit = le16_to_cpu(xb->xb_suballoc_bit); |
1716 | bg_blkno = ocfs2_which_suballoc_group(blk, bit); | 1766 | bg_blkno = ocfs2_which_suballoc_group(blk, bit); |
@@ -1950,19 +2000,15 @@ static int ocfs2_xattr_block_find(struct inode *inode, | |||
1950 | if (!di->i_xattr_loc) | 2000 | if (!di->i_xattr_loc) |
1951 | return ret; | 2001 | return ret; |
1952 | 2002 | ||
1953 | ret = ocfs2_read_block(inode, le64_to_cpu(di->i_xattr_loc), &blk_bh); | 2003 | ret = ocfs2_read_xattr_block(inode, le64_to_cpu(di->i_xattr_loc), |
2004 | &blk_bh); | ||
1954 | if (ret < 0) { | 2005 | if (ret < 0) { |
1955 | mlog_errno(ret); | 2006 | mlog_errno(ret); |
1956 | return ret; | 2007 | return ret; |
1957 | } | 2008 | } |
1958 | 2009 | ||
1959 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; | ||
1960 | if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) { | ||
1961 | ret = -EIO; | ||
1962 | goto cleanup; | ||
1963 | } | ||
1964 | |||
1965 | xs->xattr_bh = blk_bh; | 2010 | xs->xattr_bh = blk_bh; |
2011 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; | ||
1966 | 2012 | ||
1967 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { | 2013 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { |
1968 | xs->header = &xb->xb_attrs.xb_header; | 2014 | xs->header = &xb->xb_attrs.xb_header; |
@@ -2259,9 +2305,9 @@ meta_guess: | |||
2259 | /* calculate metadata allocation. */ | 2305 | /* calculate metadata allocation. */ |
2260 | if (di->i_xattr_loc) { | 2306 | if (di->i_xattr_loc) { |
2261 | if (!xbs->xattr_bh) { | 2307 | if (!xbs->xattr_bh) { |
2262 | ret = ocfs2_read_block(inode, | 2308 | ret = ocfs2_read_xattr_block(inode, |
2263 | le64_to_cpu(di->i_xattr_loc), | 2309 | le64_to_cpu(di->i_xattr_loc), |
2264 | &bh); | 2310 | &bh); |
2265 | if (ret) { | 2311 | if (ret) { |
2266 | mlog_errno(ret); | 2312 | mlog_errno(ret); |
2267 | goto out; | 2313 | goto out; |