📄 ext3-extents-sanity-checks.patch
字号:
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-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 <asm/uaccess.h> -static inline int ext3_ext_check_header(struct ext3_extent_header *eh)-{- if (eh->eh_magic != EXT3_EXT_MAGIC) {- printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",- (unsigned)eh->eh_magic);- return -EIO;+static int __ext3_ext_check_header(const char *function, struct inode *inode,+ struct ext3_extent_header *eh, int depth,+ int max)+{+ const char *error_msg = NULL;++ if (unlikely(eh->eh_magic != EXT3_EXT_MAGIC)) {+ error_msg = "invalid magic";+ goto corrupted;+ }+ if (unlikely(eh->eh_depth != depth)) {+ error_msg = "unexpected eh_depth";+ goto corrupted;+ }+ 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;+ }+ if (unlikely(eh->eh_entries > eh->eh_max)) {+ error_msg = "invalid eh_entries";+ goto corrupted; } return 0;++corrupted:+ ext3_error(inode->i_sb, function,+ "bad header in inode #%lu: %s - magic %x, "+ "entries %u, max %u(%u), depth %u(%u)",+ inode->i_ino, error_msg, eh->eh_magic,+ eh->eh_entries, eh->eh_max, max,+ eh->eh_depth, depth);++ return -EIO; } +#define ext3_ext_check_header(inode,eh,depth,max) \+ __ext3_ext_check_header(__FUNCTION__,inode,eh,depth,max)++ static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed) { int err;@@ -227,6 +257,26 @@ static inline int ext3_ext_space_root_id return size; } +static inline int+ext3_ext_max_entries(struct ext3_extents_tree *tree, int root, int depth)+{+ int max;++ if (root) {+ if (depth == 0)+ max = ext3_ext_space_root(tree);+ else+ max = ext3_ext_space_root_idx(tree);+ } else {+ if (depth == 0)+ max = ext3_ext_space_block(tree);+ else+ max = ext3_ext_space_block_idx(tree);+ }++ return max;+}+ static void ext3_ext_show_path(struct ext3_extents_tree *tree, struct ext3_ext_path *path) {@@ -297,10 +347,6 @@ ext3_ext_binsearch_idx(struct ext3_exten struct ext3_extent_idx *ix; int l = 0, k, r; - EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);- EXT_ASSERT(eh->eh_entries <= eh->eh_max);- EXT_ASSERT(eh->eh_entries > 0);- ext_debug(tree, "binsearch for %d(idx): ", block); path->p_idx = ix = EXT_FIRST_INDEX(eh);@@ -360,9 +406,6 @@ ext3_ext_binsearch(struct ext3_extents_t struct ext3_extent *ex; int l = 0, k, r; - EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);- EXT_ASSERT(eh->eh_entries <= eh->eh_max);- if (eh->eh_entries == 0) { /* * this leaf is empty yet:@@ -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;+ int max; EXT_ASSERT(tree); EXT_ASSERT(tree->inode);@@ -444,17 +488,15 @@ ext3_ext_find_extent(struct ext3_extents eh = EXT_ROOT_HDR(tree); EXT_ASSERT(eh);- if (ext3_ext_check_header(eh)) {+ i = depth = EXT_DEPTH(tree);+ max = ext3_ext_max_entries(tree, 1, i);+ if (ext3_ext_check_header(tree->inode, eh, i, max)) { /* don't free previously allocated path * -- caller should take care */ path = NULL; goto err; } - i = depth = EXT_DEPTH(tree);- EXT_ASSERT(eh->eh_max);- EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);- /* account possible depth increase */ if (!path) { path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),@@ -485,7 +527,8 @@ ext3_ext_find_extent(struct ext3_extents path[ppos].p_hdr = eh; i--; - if (ext3_ext_check_header(eh))+ max = ext3_ext_max_entries(tree, 0, i);+ if (ext3_ext_check_header(tree->inode, eh, i, max)) goto err; } @@ -494,9 +537,6 @@ ext3_ext_find_extent(struct ext3_extents path[ppos].p_ext = NULL; path[ppos].p_idx = NULL; - if (ext3_ext_check_header(eh))- goto err;- /* find extent */ ext3_ext_binsearch(tree, path + ppos, block); @@ -993,7 +1033,7 @@ ext3_ext_search_right(struct ext3_extent struct ext3_extent_idx *ix; struct ext3_extent *ex; unsigned long block;- int depth;+ int depth, max; BUG_ON(path == NULL); depth = path->p_depth;@@ -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,+ path->p_depth - depth, max)) { brelse(bh); return -EIO; }@@ -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, 0, max)) { brelse(bh); return -EIO; }@@ -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);++ /* the header must be checked already in ext3_ext_remove_space() */ eh = path[depth].p_hdr; EXT_ASSERT(eh); EXT_ASSERT(eh->eh_entries <= eh->eh_max);@@ -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;- int i = 0, err = 0;+ int i = 0, err = 0, max; ext_debug(tree, "space to be removed: %lu:%lu\n", start, end); @@ -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);- ++ max = ext3_ext_max_entries(tree, 1, depth);+ if (ext3_ext_check_header(inode, path[i].p_hdr, depth, max)) {+ err = -EIO;+ goto out;+ }+ while (i >= 0 && err == 0) { if (i == depth) { /* this is leaf block */@@ -1889,16 +1940,13 @@ int ext3_ext_remove_space(struct ext3_ex i--; continue; }- + /* this is index block */ if (!path[i].p_hdr) { ext_debug(tree, "initialize header\n"); path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh); } - EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);- EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);- if (!path[i].p_idx) { /* this level hasn't touched yet */ path[i].p_idx =@@ -1925,6 +1973,14 @@ int ext3_ext_remove_space(struct ext3_ex err = -EIO; break; }+ BUG_ON(i + 1 > depth);+ max = ext3_ext_max_entries(tree, 0, depth - i - 1);+ if (ext3_ext_check_header(inode,+ EXT_BLOCK_HDR(path[i+1].p_bh),+ depth - i - 1, max)) {+ err = -EIO;+ break;+ } /* 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 +2001,7 @@ int ext3_ext_remove_space(struct ext3_ex } /* TODO: flexible tree reduction should be here */- if (path->p_hdr->eh_entries == 0) {+ if (err == 0 && path->p_hdr->eh_entries == 0) { /* * truncate to zero freed all the tree * so, we need to correct eh_depth@@ -1959,6 +2015,7 @@ int ext3_ext_remove_space(struct ext3_ex } ext3_ext_tree_changed(tree); +out: kfree(path); ext3_journal_stop(handle);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -