aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2007-01-08 06:55:37 +0100
committerAdrian Bunk <bunk@stusta.de>2007-01-09 03:23:34 +0100
commitad3c43bb4a85be908332a2872b0ba9d368a7f329 (patch)
tree3b129cace0fdc3a014e6f6791c6c27fdada91581 /fs
parent6a4121f687fa1236f2414bcaf78917d5804be587 (diff)
downloadlinux-linaro-stable-ad3c43bb4a85be908332a2872b0ba9d368a7f329.tar.gz
hfs_fill_super returns success even if no root inode (CVE-2006-6056)
http://kernelfun.blogspot.com/2006/11/mokb-14-11-2006-linux-26x-selinux.html mount that image... fs: filesystem was not cleanly unmounted, running fsck.hfs is recommended. mounting read-only. hfs: get root inode failed. BUG: unable to handle kernel NULL pointer dereference at virtual address 00000018 printing eip ... EIP is at superblock_doinit+0x21/0x767 ... [] selinux_sb_kern_mount+0xc/0x4b [] vfs_kern_mount+0x99/0xf6 [] do_kern_mount+0x2d/0x3e [] do_mount+0x5fa/0x66d [] sys_mount+0x77/0xae [] syscall_call+0x7/0xb DWARF2 unwinder stuck at syscall_call+0x7/0xb hfs_fill_super() returns success even if root_inode = hfs_iget(sb, &fd.search_key->cat, &rec); or sb->s_root = d_alloc_root(root_inode); fails. This superblock finds its way to superblock_doinit() which does: struct dentry *root = sb->s_root; struct inode *inode = root->d_inode; and boom. Need to make sure the error cases return an error, I think. [akpm@osdl.org: return -ENOMEM on oom] Signed-off-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Adrian Bunk <bunk@stusta.de>
Diffstat (limited to 'fs')
-rw-r--r--fs/hfs/super.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 1181d116117d..2e1819b06295 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -390,11 +390,13 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
hfs_find_exit(&fd);
goto bail_no_root;
}
+ res = -EINVAL;
root_inode = hfs_iget(sb, &fd.search_key->cat, &rec);
hfs_find_exit(&fd);
if (!root_inode)
goto bail_no_root;
+ res = -ENOMEM;
sb->s_root = d_alloc_root(root_inode);
if (!sb->s_root)
goto bail_iput;