diff options
| -rw-r--r-- | fs/ext3/namei.c | 34 | ||||
| -rw-r--r-- | fs/ext4/namei.c | 34 |
2 files changed, 60 insertions, 8 deletions
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 1586807b8177..9d4a89820e1e 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
| @@ -379,13 +379,28 @@ dx_probe(struct dentry *dentry, struct inode *dir, | |||
| 379 | 379 | ||
| 380 | entries = (struct dx_entry *) (((char *)&root->info) + | 380 | entries = (struct dx_entry *) (((char *)&root->info) + |
| 381 | root->info.info_length); | 381 | root->info.info_length); |
| 382 | assert(dx_get_limit(entries) == dx_root_limit(dir, | 382 | |
| 383 | root->info.info_length)); | 383 | if (dx_get_limit(entries) != dx_root_limit(dir, |
| 384 | root->info.info_length)) { | ||
| 385 | ext3_warning(dir->i_sb, __FUNCTION__, | ||
| 386 | "dx entry: limit != root limit"); | ||
| 387 | brelse(bh); | ||
| 388 | *err = ERR_BAD_DX_DIR; | ||
| 389 | goto fail; | ||
| 390 | } | ||
| 391 | |||
| 384 | dxtrace (printk("Look up %x", hash)); | 392 | dxtrace (printk("Look up %x", hash)); |
| 385 | while (1) | 393 | while (1) |
| 386 | { | 394 | { |
| 387 | count = dx_get_count(entries); | 395 | count = dx_get_count(entries); |
| 388 | assert (count && count <= dx_get_limit(entries)); | 396 | if (!count || count > dx_get_limit(entries)) { |
| 397 | ext3_warning(dir->i_sb, __FUNCTION__, | ||
| 398 | "dx entry: no count or count > limit"); | ||
| 399 | brelse(bh); | ||
| 400 | *err = ERR_BAD_DX_DIR; | ||
| 401 | goto fail2; | ||
| 402 | } | ||
| 403 | |||
| 389 | p = entries + 1; | 404 | p = entries + 1; |
| 390 | q = entries + count - 1; | 405 | q = entries + count - 1; |
| 391 | while (p <= q) | 406 | while (p <= q) |
| @@ -423,8 +438,15 @@ dx_probe(struct dentry *dentry, struct inode *dir, | |||
| 423 | if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) | 438 | if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) |
| 424 | goto fail2; | 439 | goto fail2; |
| 425 | at = entries = ((struct dx_node *) bh->b_data)->entries; | 440 | at = entries = ((struct dx_node *) bh->b_data)->entries; |
| 426 | assert (dx_get_limit(entries) == dx_node_limit (dir)); | 441 | if (dx_get_limit(entries) != dx_node_limit (dir)) { |
| 442 | ext3_warning(dir->i_sb, __FUNCTION__, | ||
| 443 | "dx entry: limit != node limit"); | ||
| 444 | brelse(bh); | ||
| 445 | *err = ERR_BAD_DX_DIR; | ||
| 446 | goto fail2; | ||
| 447 | } | ||
| 427 | frame++; | 448 | frame++; |
| 449 | frame->bh = NULL; | ||
| 428 | } | 450 | } |
| 429 | fail2: | 451 | fail2: |
| 430 | while (frame >= frame_in) { | 452 | while (frame >= frame_in) { |
| @@ -432,6 +454,10 @@ fail2: | |||
| 432 | frame--; | 454 | frame--; |
| 433 | } | 455 | } |
| 434 | fail: | 456 | fail: |
| 457 | if (*err == ERR_BAD_DX_DIR) | ||
| 458 | ext3_warning(dir->i_sb, __FUNCTION__, | ||
| 459 | "Corrupt dir inode %ld, running e2fsck is " | ||
| 460 | "recommended.", dir->i_ino); | ||
| 435 | return NULL; | 461 | return NULL; |
| 436 | } | 462 | } |
| 437 | 463 | ||
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index da224974af78..9468289637a5 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
| @@ -379,13 +379,28 @@ dx_probe(struct dentry *dentry, struct inode *dir, | |||
| 379 | 379 | ||
| 380 | entries = (struct dx_entry *) (((char *)&root->info) + | 380 | entries = (struct dx_entry *) (((char *)&root->info) + |
| 381 | root->info.info_length); | 381 | root->info.info_length); |
| 382 | assert(dx_get_limit(entries) == dx_root_limit(dir, | 382 | |
| 383 | root->info.info_length)); | 383 | if (dx_get_limit(entries) != dx_root_limit(dir, |
| 384 | root->info.info_length)) { | ||
| 385 | ext4_warning(dir->i_sb, __FUNCTION__, | ||
| 386 | "dx entry: limit != root limit"); | ||
| 387 | brelse(bh); | ||
| 388 | *err = ERR_BAD_DX_DIR; | ||
| 389 | goto fail; | ||
| 390 | } | ||
| 391 | |||
| 384 | dxtrace (printk("Look up %x", hash)); | 392 | dxtrace (printk("Look up %x", hash)); |
| 385 | while (1) | 393 | while (1) |
| 386 | { | 394 | { |
| 387 | count = dx_get_count(entries); | 395 | count = dx_get_count(entries); |
| 388 | assert (count && count <= dx_get_limit(entries)); | 396 | if (!count || count > dx_get_limit(entries)) { |
| 397 | ext4_warning(dir->i_sb, __FUNCTION__, | ||
| 398 | "dx entry: no count or count > limit"); | ||
| 399 | brelse(bh); | ||
| 400 | *err = ERR_BAD_DX_DIR; | ||
| 401 | goto fail2; | ||
| 402 | } | ||
| 403 | |||
| 389 | p = entries + 1; | 404 | p = entries + 1; |
| 390 | q = entries + count - 1; | 405 | q = entries + count - 1; |
| 391 | while (p <= q) | 406 | while (p <= q) |
| @@ -423,8 +438,15 @@ dx_probe(struct dentry *dentry, struct inode *dir, | |||
| 423 | if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err))) | 438 | if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err))) |
| 424 | goto fail2; | 439 | goto fail2; |
| 425 | at = entries = ((struct dx_node *) bh->b_data)->entries; | 440 | at = entries = ((struct dx_node *) bh->b_data)->entries; |
| 426 | assert (dx_get_limit(entries) == dx_node_limit (dir)); | 441 | if (dx_get_limit(entries) != dx_node_limit (dir)) { |
| 442 | ext4_warning(dir->i_sb, __FUNCTION__, | ||
| 443 | "dx entry: limit != node limit"); | ||
| 444 | brelse(bh); | ||
| 445 | *err = ERR_BAD_DX_DIR; | ||
| 446 | goto fail2; | ||
| 447 | } | ||
| 427 | frame++; | 448 | frame++; |
| 449 | frame->bh = NULL; | ||
| 428 | } | 450 | } |
| 429 | fail2: | 451 | fail2: |
| 430 | while (frame >= frame_in) { | 452 | while (frame >= frame_in) { |
| @@ -432,6 +454,10 @@ fail2: | |||
| 432 | frame--; | 454 | frame--; |
| 433 | } | 455 | } |
| 434 | fail: | 456 | fail: |
| 457 | if (*err == ERR_BAD_DX_DIR) | ||
| 458 | ext4_warning(dir->i_sb, __FUNCTION__, | ||
| 459 | "Corrupt dir inode %ld, running e2fsck is " | ||
| 460 | "recommended.", dir->i_ino); | ||
| 435 | return NULL; | 461 | return NULL; |
| 436 | } | 462 | } |
| 437 | 463 | ||
