|
@@ -314,6 +314,65 @@ static void ocfs2_xattr_bucket_copy_data(struct ocfs2_xattr_bucket *dest,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int ocfs2_validate_xattr_block(struct super_block *sb,
|
|
|
|
+ struct buffer_head *bh)
|
|
|
|
+{
|
|
|
|
+ struct ocfs2_xattr_block *xb =
|
|
|
|
+ (struct ocfs2_xattr_block *)bh->b_data;
|
|
|
|
+
|
|
|
|
+ mlog(0, "Validating xattr block %llu\n",
|
|
|
|
+ (unsigned long long)bh->b_blocknr);
|
|
|
|
+
|
|
|
|
+ if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) {
|
|
|
|
+ ocfs2_error(sb,
|
|
|
|
+ "Extended attribute block #%llu has bad "
|
|
|
|
+ "signature %.*s",
|
|
|
|
+ (unsigned long long)bh->b_blocknr, 7,
|
|
|
|
+ xb->xb_signature);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (le64_to_cpu(xb->xb_blkno) != bh->b_blocknr) {
|
|
|
|
+ ocfs2_error(sb,
|
|
|
|
+ "Extended attribute block #%llu has an "
|
|
|
|
+ "invalid xb_blkno of %llu",
|
|
|
|
+ (unsigned long long)bh->b_blocknr,
|
|
|
|
+ (unsigned long long)le64_to_cpu(xb->xb_blkno));
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (le32_to_cpu(xb->xb_fs_generation) != OCFS2_SB(sb)->fs_generation) {
|
|
|
|
+ ocfs2_error(sb,
|
|
|
|
+ "Extended attribute block #%llu has an invalid "
|
|
|
|
+ "xb_fs_generation of #%u",
|
|
|
|
+ (unsigned long long)bh->b_blocknr,
|
|
|
|
+ le32_to_cpu(xb->xb_fs_generation));
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int ocfs2_read_xattr_block(struct inode *inode, u64 xb_blkno,
|
|
|
|
+ struct buffer_head **bh)
|
|
|
|
+{
|
|
|
|
+ int rc;
|
|
|
|
+ struct buffer_head *tmp = *bh;
|
|
|
|
+
|
|
|
|
+ rc = ocfs2_read_block(inode, xb_blkno, &tmp);
|
|
|
|
+ if (!rc) {
|
|
|
|
+ rc = ocfs2_validate_xattr_block(inode->i_sb, tmp);
|
|
|
|
+ if (rc)
|
|
|
|
+ brelse(tmp);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* If ocfs2_read_block() got us a new bh, pass it up. */
|
|
|
|
+ if (!rc && !*bh)
|
|
|
|
+ *bh = tmp;
|
|
|
|
+
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
static inline const char *ocfs2_xattr_prefix(int name_index)
|
|
static inline const char *ocfs2_xattr_prefix(int name_index)
|
|
{
|
|
{
|
|
struct xattr_handler *handler = NULL;
|
|
struct xattr_handler *handler = NULL;
|
|
@@ -739,18 +798,14 @@ static int ocfs2_xattr_block_list(struct inode *inode,
|
|
if (!di->i_xattr_loc)
|
|
if (!di->i_xattr_loc)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- ret = ocfs2_read_block(inode, le64_to_cpu(di->i_xattr_loc), &blk_bh);
|
|
|
|
|
|
+ ret = ocfs2_read_xattr_block(inode, le64_to_cpu(di->i_xattr_loc),
|
|
|
|
+ &blk_bh);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
mlog_errno(ret);
|
|
mlog_errno(ret);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
|
|
xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
|
|
- if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) {
|
|
|
|
- ret = -EIO;
|
|
|
|
- goto cleanup;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
|
|
if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
|
|
struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header;
|
|
struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header;
|
|
ret = ocfs2_xattr_list_entries(inode, header,
|
|
ret = ocfs2_xattr_list_entries(inode, header,
|
|
@@ -760,7 +815,7 @@ static int ocfs2_xattr_block_list(struct inode *inode,
|
|
ret = ocfs2_xattr_tree_list_index_block(inode, xt,
|
|
ret = ocfs2_xattr_tree_list_index_block(inode, xt,
|
|
buffer, buffer_size);
|
|
buffer, buffer_size);
|
|
}
|
|
}
|
|
-cleanup:
|
|
|
|
|
|
+
|
|
brelse(blk_bh);
|
|
brelse(blk_bh);
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
@@ -1693,24 +1748,19 @@ static int ocfs2_xattr_free_block(struct inode *inode,
|
|
u64 blk, bg_blkno;
|
|
u64 blk, bg_blkno;
|
|
u16 bit;
|
|
u16 bit;
|
|
|
|
|
|
- ret = ocfs2_read_block(inode, block, &blk_bh);
|
|
|
|
|
|
+ ret = ocfs2_read_xattr_block(inode, block, &blk_bh);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
mlog_errno(ret);
|
|
mlog_errno(ret);
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
|
|
|
|
- if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) {
|
|
|
|
- ret = -EIO;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
ret = ocfs2_xattr_block_remove(inode, blk_bh);
|
|
ret = ocfs2_xattr_block_remove(inode, blk_bh);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
mlog_errno(ret);
|
|
mlog_errno(ret);
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
|
|
blk = le64_to_cpu(xb->xb_blkno);
|
|
blk = le64_to_cpu(xb->xb_blkno);
|
|
bit = le16_to_cpu(xb->xb_suballoc_bit);
|
|
bit = le16_to_cpu(xb->xb_suballoc_bit);
|
|
bg_blkno = ocfs2_which_suballoc_group(blk, bit);
|
|
bg_blkno = ocfs2_which_suballoc_group(blk, bit);
|
|
@@ -1950,19 +2000,15 @@ static int ocfs2_xattr_block_find(struct inode *inode,
|
|
if (!di->i_xattr_loc)
|
|
if (!di->i_xattr_loc)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- ret = ocfs2_read_block(inode, le64_to_cpu(di->i_xattr_loc), &blk_bh);
|
|
|
|
|
|
+ ret = ocfs2_read_xattr_block(inode, le64_to_cpu(di->i_xattr_loc),
|
|
|
|
+ &blk_bh);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
mlog_errno(ret);
|
|
mlog_errno(ret);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
- xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
|
|
|
|
- if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) {
|
|
|
|
- ret = -EIO;
|
|
|
|
- goto cleanup;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
xs->xattr_bh = blk_bh;
|
|
xs->xattr_bh = blk_bh;
|
|
|
|
+ xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
|
|
|
|
|
|
if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
|
|
if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
|
|
xs->header = &xb->xb_attrs.xb_header;
|
|
xs->header = &xb->xb_attrs.xb_header;
|
|
@@ -2259,9 +2305,9 @@ meta_guess:
|
|
/* calculate metadata allocation. */
|
|
/* calculate metadata allocation. */
|
|
if (di->i_xattr_loc) {
|
|
if (di->i_xattr_loc) {
|
|
if (!xbs->xattr_bh) {
|
|
if (!xbs->xattr_bh) {
|
|
- ret = ocfs2_read_block(inode,
|
|
|
|
- le64_to_cpu(di->i_xattr_loc),
|
|
|
|
- &bh);
|
|
|
|
|
|
+ ret = ocfs2_read_xattr_block(inode,
|
|
|
|
+ le64_to_cpu(di->i_xattr_loc),
|
|
|
|
+ &bh);
|
|
if (ret) {
|
|
if (ret) {
|
|
mlog_errno(ret);
|
|
mlog_errno(ret);
|
|
goto out;
|
|
goto out;
|