From: johann Date: Wed, 18 Jul 2007 07:43:12 +0000 (+0000) Subject: Branch b1_6 X-Git-Tag: v1_7_100~10 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=4b370bf613de63c1559940986b4dd2f53482cb54 Branch b1_6 b=12861 i=alex i=adilger i=kalpak Severity : major Bugzilla : 12861 Description: ldiskfs_ext_search_right: bad header in inode #3981353: unexpected eh_depth Details : a wrong check of extent headers in ldiskfs_ext_search_right() can cause the filesystem to be remounted read-only. --- diff --git a/ldiskfs/kernel_patches/patches/ext3-extents-sanity-checks.patch b/ldiskfs/kernel_patches/patches/ext3-extents-sanity-checks.patch index d06d54d..6c22585 100644 --- a/ldiskfs/kernel_patches/patches/ext3-extents-sanity-checks.patch +++ b/ldiskfs/kernel_patches/patches/ext3-extents-sanity-checks.patch @@ -1,8 +1,8 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c =================================================================== ---- linux-2.6.9-42.0.10.EL_lustre.1.4.10.orig/fs/ext3/extents.c 2007-06-14 11:42:34.000000000 +0200 -+++ linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c 2007-06-14 13:59:49.000000000 +0200 -@@ -44,26 +44,49 @@ +--- linux-2.6.9-42.0.10.EL_lustre.1.4.10.orig/fs/ext3/extents.c 2007-07-17 22:14:08.000000000 +0200 ++++ linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c 2007-07-17 22:40:57.000000000 +0200 +@@ -44,26 +44,56 @@ #include @@ -12,16 +12,6 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c - printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n", - (unsigned)eh->eh_magic); - return -EIO; -- } -- if (eh->eh_max == 0) { -- printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n", -- (unsigned)eh->eh_max); -- return -EIO; -- } -- if (eh->eh_entries > eh->eh_max) { -- printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n", -- (unsigned)eh->eh_entries); -- return -EIO; +static int __ext3_ext_check_header(const char *function, struct inode *inode, + struct ext3_extent_header *eh, int depth, + int max) @@ -39,7 +29,22 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c + if (unlikely(eh->eh_max == 0)) { + error_msg = "too small eh_max"; + goto corrupted; -+ } + } +- if (eh->eh_max == 0) { +- printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n", +- (unsigned)eh->eh_max); +- return -EIO; ++#ifdef AGRESSIVE_TEST ++ if (eh->eh_max > 3) { ++ /* inode probably got its extent without defining ++ * AGRESSIVE_TEST */ ++ max = eh->eh_max; + } +- if (eh->eh_entries > eh->eh_max) { +- printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n", +- (unsigned)eh->eh_entries); +- return -EIO; ++#endif + if (unlikely(eh->eh_max > max)) { + error_msg = "too large eh_max"; + goto corrupted; @@ -68,7 +73,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed) { int err; -@@ -227,6 +250,26 @@ static inline int ext3_ext_space_root_id +@@ -227,6 +257,26 @@ static inline int ext3_ext_space_root_id return size; } @@ -95,7 +100,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c static void ext3_ext_show_path(struct ext3_extents_tree *tree, struct ext3_ext_path *path) { -@@ -297,10 +340,6 @@ ext3_ext_binsearch_idx(struct ext3_exten +@@ -297,10 +347,6 @@ ext3_ext_binsearch_idx(struct ext3_exten struct ext3_extent_idx *ix; int l = 0, k, r; @@ -106,7 +111,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c ext_debug(tree, "binsearch for %d(idx): ", block); path->p_idx = ix = EXT_FIRST_INDEX(eh); -@@ -360,9 +399,6 @@ ext3_ext_binsearch(struct ext3_extents_t +@@ -360,9 +406,6 @@ ext3_ext_binsearch(struct ext3_extents_t struct ext3_extent *ex; int l = 0, k, r; @@ -116,7 +121,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c if (eh->eh_entries == 0) { /* * this leaf is empty yet: -@@ -437,6 +473,7 @@ ext3_ext_find_extent(struct ext3_extents +@@ -437,6 +480,7 @@ ext3_ext_find_extent(struct ext3_extents struct ext3_extent_header *eh; struct buffer_head *bh; int depth, i, ppos = 0; @@ -124,7 +129,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c EXT_ASSERT(tree); EXT_ASSERT(tree->inode); -@@ -444,17 +481,15 @@ ext3_ext_find_extent(struct ext3_extents +@@ -444,17 +488,15 @@ ext3_ext_find_extent(struct ext3_extents eh = EXT_ROOT_HDR(tree); EXT_ASSERT(eh); @@ -145,7 +150,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c /* account possible depth increase */ if (!path) { path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2), -@@ -485,7 +520,8 @@ ext3_ext_find_extent(struct ext3_extents +@@ -485,7 +527,8 @@ ext3_ext_find_extent(struct ext3_extents path[ppos].p_hdr = eh; i--; @@ -155,7 +160,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c goto err; } -@@ -494,9 +530,6 @@ ext3_ext_find_extent(struct ext3_extents +@@ -494,9 +537,6 @@ ext3_ext_find_extent(struct ext3_extents path[ppos].p_ext = NULL; path[ppos].p_idx = NULL; @@ -165,7 +170,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c /* find extent */ ext3_ext_binsearch(tree, path + ppos, block); -@@ -993,7 +1026,7 @@ ext3_ext_search_right(struct ext3_extent +@@ -993,7 +1033,7 @@ ext3_ext_search_right(struct ext3_extent struct ext3_extent_idx *ix; struct ext3_extent *ex; unsigned long block; @@ -174,27 +179,28 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c BUG_ON(path == NULL); depth = path->p_depth; -@@ -1051,7 +1084,8 @@ ext3_ext_search_right(struct ext3_extent +@@ -1051,7 +1091,9 @@ ext3_ext_search_right(struct ext3_extent if (bh == NULL) return -EIO; eh = EXT_BLOCK_HDR(bh); - if (ext3_ext_check_header(eh)) { + max = ext3_ext_max_entries(tree, 0, depth); -+ if (ext3_ext_check_header(tree->inode, eh, depth, max)) { ++ if (ext3_ext_check_header(tree->inode, eh, ++ path->p_depth - depth, max)) { brelse(bh); return -EIO; } -@@ -1064,7 +1098,8 @@ ext3_ext_search_right(struct ext3_extent +@@ -1064,7 +1106,8 @@ ext3_ext_search_right(struct ext3_extent if (bh == NULL) return -EIO; eh = EXT_BLOCK_HDR(bh); - if (ext3_ext_check_header(eh)) { + max = ext3_ext_max_entries(tree, 0, depth); -+ if (ext3_ext_check_header(tree->inode, eh, depth, max)) { ++ if (ext3_ext_check_header(tree->inode, eh, 0, max)) { brelse(bh); return -EIO; } -@@ -1694,6 +1729,8 @@ ext3_ext_rm_leaf(handle_t *handle, struc +@@ -1694,6 +1737,8 @@ ext3_ext_rm_leaf(handle_t *handle, struc ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end); if (!path[depth].p_hdr) path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh); @@ -203,7 +209,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c eh = path[depth].p_hdr; EXT_ASSERT(eh); EXT_ASSERT(eh->eh_entries <= eh->eh_max); -@@ -1856,7 +1893,7 @@ int ext3_ext_remove_space(struct ext3_ex +@@ -1856,7 +1901,7 @@ int ext3_ext_remove_space(struct ext3_ex int depth = EXT_DEPTH(tree); struct ext3_ext_path *path; handle_t *handle; @@ -212,7 +218,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c ext_debug(tree, "space to be removed: %lu:%lu\n", start, end); -@@ -1879,7 +1916,13 @@ int ext3_ext_remove_space(struct ext3_ex +@@ -1879,7 +1924,13 @@ int ext3_ext_remove_space(struct ext3_ex } memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1)); path[i].p_hdr = EXT_ROOT_HDR(tree); @@ -227,7 +233,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c while (i >= 0 && err == 0) { if (i == depth) { /* this is leaf block */ -@@ -1889,16 +1932,13 @@ int ext3_ext_remove_space(struct ext3_ex +@@ -1889,16 +1940,13 @@ int ext3_ext_remove_space(struct ext3_ex i--; continue; } @@ -245,7 +251,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c if (!path[i].p_idx) { /* this level hasn't touched yet */ path[i].p_idx = -@@ -1925,6 +1965,14 @@ int ext3_ext_remove_space(struct ext3_ex +@@ -1925,6 +1973,14 @@ int ext3_ext_remove_space(struct ext3_ex err = -EIO; break; } @@ -260,7 +266,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c /* put actual number of indexes to know is this * number got changed at the next iteration */ path[i].p_block = path[i].p_hdr->eh_entries; -@@ -1945,7 +1993,7 @@ int ext3_ext_remove_space(struct ext3_ex +@@ -1945,7 +2001,7 @@ int ext3_ext_remove_space(struct ext3_ex } /* TODO: flexible tree reduction should be here */ @@ -269,7 +275,7 @@ Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c /* * truncate to zero freed all the tree * so, we need to correct eh_depth -@@ -1959,6 +2007,7 @@ int ext3_ext_remove_space(struct ext3_ex +@@ -1959,6 +2015,7 @@ int ext3_ext_remove_space(struct ext3_ex } ext3_ext_tree_changed(tree);