Bug 215419 - CVE-2006-6054 ext2_check_page denial of service
CVE-2006-6054 ext2_check_page denial of service
Status: CLOSED CURRENTRELEASE
Product: Fedora
Classification: Fedora
Component: kernel (Show other bugs)
6
All Linux
medium Severity medium
: ---
: ---
Assigned To: Eric Sandeen
Brian Brock
http://kernelfun.blogspot.com/2006/11...
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2006-11-13 16:29 EST by Eric Sandeen
Modified: 2007-11-30 17:11 EST (History)
3 users (show)

See Also:
Fixed In Version: kernel-2.6.19-1.2895.fc6
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2007-01-25 10:45:52 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:


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

  None (edit)
Description Eric Sandeen 2006-11-13 16:29:33 EST
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 14:00:06 EST
Created attachment 144206 [details]
upstream patch sent to LKML today
Comment 2 Eric Sandeen 2007-01-15 12:24:30 EST
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 10:45:52 EST
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.