diff options
author | Jeff Mahoney <jeffm@suse.com> | 2010-10-14 09:53:37 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2010-10-14 09:53:37 -0400 |
commit | ee52716245877b821f5ddbb3ace85b73084fb450 (patch) | |
tree | 3d85d8fce3bde7b1601878074cdec622705d1af2 /fs/hfsplus | |
parent | 40de9a7cebc4e0b23cd6863c84c2279f0ccadebb (diff) |
hfsplus: fix oops on mount with corrupted btree extent records
A particular fsfuzzer run caused an hfs file system to crash on mount. This
is due to a corrupted MDB extent record causing a miscalculation of
HFSPLUS_I(inode)->first_blocks for the extent tree. If the extent records
are zereod out, then it won't trigger the first_blocks special case and
instead falls through to the extent code, which we're in the middle
of initializing.
This patch catches the 0 size extent records, reports the corruption,
and fails the mount.
[hch: ported of commit 47f365eb575735c6b2edf5d08e0d16d26a9c23bd from hfs]
Reported-by: Ramon de Carvalho Valle <rcvalle@linux.vnet.ibm.com>
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
Diffstat (limited to 'fs/hfsplus')
-rw-r--r-- | fs/hfsplus/btree.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index 8306479f6b3a..d4bd864ce108 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c | |||
@@ -39,10 +39,16 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
39 | goto free_tree; | 39 | goto free_tree; |
40 | tree->inode = inode; | 40 | tree->inode = inode; |
41 | 41 | ||
42 | if (!HFSPLUS_I(tree->inode)->first_blocks) { | ||
43 | printk(KERN_ERR | ||
44 | "hfs: invalid btree extent records (0 size).\n"); | ||
45 | goto free_inode; | ||
46 | } | ||
47 | |||
42 | mapping = tree->inode->i_mapping; | 48 | mapping = tree->inode->i_mapping; |
43 | page = read_mapping_page(mapping, 0, NULL); | 49 | page = read_mapping_page(mapping, 0, NULL); |
44 | if (IS_ERR(page)) | 50 | if (IS_ERR(page)) |
45 | goto free_tree; | 51 | goto free_inode; |
46 | 52 | ||
47 | /* Load the header */ | 53 | /* Load the header */ |
48 | head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc)); | 54 | head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc)); |
@@ -89,8 +95,9 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
89 | fail_page: | 95 | fail_page: |
90 | tree->inode->i_mapping->a_ops = &hfsplus_aops; | 96 | tree->inode->i_mapping->a_ops = &hfsplus_aops; |
91 | page_cache_release(page); | 97 | page_cache_release(page); |
92 | free_tree: | 98 | free_inode: |
93 | iput(tree->inode); | 99 | iput(tree->inode); |
100 | free_tree: | ||
94 | kfree(tree); | 101 | kfree(tree); |
95 | return NULL; | 102 | return NULL; |
96 | } | 103 | } |