Bug 215419 - CVE-2006-6054 ext2_check_page denial of service
Summary: CVE-2006-6054 ext2_check_page denial of service
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Fedora
Classification: Fedora
Component: kernel
Version: 6
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Eric Sandeen
QA Contact: Brian Brock
URL: http://kernelfun.blogspot.com/2006/11...
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2006-11-13 21:29 UTC by Eric Sandeen
Modified: 2007-11-30 22:11 UTC (History)
3 users (show)

Fixed In Version: kernel-2.6.19-1.2895.fc6
Clone Of:
Environment:
Last Closed: 2007-01-25 15:45:52 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)
upstream patch sent to LKML today (610 bytes, patch)
2006-12-21 19:00 UTC, Eric Sandeen
no flags Details | Diff

Description Eric Sandeen 2006-11-13 21:29:33 UTC
The image present at
http://kernelfun.blogspot.com/2006/11/mokb-09-11-2006-linux-26x-ext2checkpage.html
contains a root directory which has a corrupt i_size, which is extremely large.

This causes 

ext2_lookup
	ext2_inode_by_name
		ext2_find_entry

to go off and try to check every page <= i_size (via ext2_check_page()), and of
course each one fails, but there is a huge number to check.  These failures
cause a storm of printk's which could in theory result in a DoS, esp. if you
have only one cpu to work with.

A quick fix for this corruption case would be to simply check the directory size
vs. block count; ext2 directories cannot be sparse so if this fails, we can
abort the operation early:

--- linux-2.6.18.orig/fs/ext2/namei.c
+++ linux-2.6.18/fs/ext2/namei.c
@@ -60,6 +60,12 @@ static struct dentry *ext2_lookup(struct
        if (dentry->d_name.len > EXT2_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
 
+       if (dir->i_size > dir->i_blocks << 9) {
+               printk("corrupted dir #%lu (sparse) len %llu blocks %llu\n",
+                       dir->i_ino, dir->i_size, dir->i_blocks);
+               return ERR_PTR(-EIO);
+       }
+
        ino = ext2_inode_by_name(dir, dentry);
        inode = NULL;
        if (ino) {

This results in an error such as:

EXT2-fs error (device loop0): ext2_readdir: bad page in #2
corrupted dir #2 (sparse) len 3238004736 blocks 4

when we try to look up files in the directory:

[root@bear-04 ~]# cat mnt/*
cat: mnt/*: Input/output error

If the corruption were more intentional, and a very large i_size and i_blocks
correlate, then additional checking might be needed to address this; perhaps
something like keeping a count of the number of bad pages found, and aborting
the operation if it exceeds a threshold...

Alternately, I notice that ext2_readdir aborts on the first bad page it finds,
while ext2_lookup tries to soldier on, page after page.  Seems like maybe these
should be consistent; if so just bailing on the first bad page we find would
catch all cases.

I'll bring this up on the ext4 list.

Comment 1 Eric Sandeen 2006-12-21 19:00:06 UTC
Created attachment 144206 [details]
upstream patch sent to LKML today

Comment 2 Eric Sandeen 2007-01-15 17:24:30 UTC
This fix is now in 2.6.19.2, so when FC6 rebases to that or higher this bug
will be resolved.  Dave, if you want a patch for 2.6.18 FC6 kernels please let
me know.

Comment 3 Eric Sandeen 2007-01-25 15:45:52 UTC
kernel-2.6.19-1.2895.fc6 from fc6 updates has this fixed now.

Thanks,
-Eric


Note You need to log in before you can comment on or make changes to this bug.