summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2008-08-15 00:40:46 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-08-15 08:35:44 -0700
commitc963343a1150106819773e828c9b237ed977615b (patch)
treeabfcd2e27cb436315f835cd746c45e56c5397080 /fs
parentbe4de35263f59ca1f4740edfffbfb02cc3f2189e (diff)
downloadlinux-stable-c963343a1150106819773e828c9b237ed977615b.tar.gz
linux-stable-c963343a1150106819773e828c9b237ed977615b.tar.bz2
linux-stable-c963343a1150106819773e828c9b237ed977615b.zip
omfs: fix potential oops when directory size is corrupted
Testing with a modified fsfuzzer reveals a couple of locations in omfs where filesystem variables are ultimately used as loop counters with insufficient sanity checking. In this case, dir->i_size is used to compute the number of buckets in the directory hash. If too large, readdir will overrun a buffer. Since it's an invariant that dir->i_size is equal to the sysblock size, and we already sanity check that, just use that value instead. This fixes the following oops: BUG: unable to handle kernel paging request at c978e004 IP: [<c032298e>] omfs_readdir+0x18e/0x32f Oops: 0000 [#1] PREEMPT DEBUG_PAGEALLOC Modules linked in: Pid: 4796, comm: ls Not tainted (2.6.27-rc2 #12) EIP: 0060:[<c032298e>] EFLAGS: 00010287 CPU: 0 EIP is at omfs_readdir+0x18e/0x32f EAX: c978d000 EBX: 00000000 ECX: cbfcfaf8 EDX: cb2cf100 ESI: 00001000 EDI: 00000800 EBP: cb2d3f68 ESP: cb2d3f0c DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068 Process ls (pid: 4796, ti=cb2d3000 task=cb175f40 task.ti=cb2d3000) Stack: 00000002 00000000 00000000 c018a820 cb2d3f94 cb2cf100 cbfb0000 ffffff10 cbfb3b80 cbfcfaf8 000001c9 00000a09 00000000 00000000 00000000 cbfcfbc8 c9697000 cbfb3b80 22222222 00001000 c08e6cd0 cb2cf100 cbfb3b80 cb2d3f88 Call Trace: [<c018a820>] ? filldir64+0x0/0xcd [<c018a9f2>] ? vfs_readdir+0x56/0x82 [<c018a820>] ? filldir64+0x0/0xcd [<c018aa7c>] ? sys_getdents64+0x5e/0xa0 [<c01038bd>] ? sysenter_do_call+0x12/0x31 ======================= Code: 00 89 f0 89 f3 0f ac f8 14 81 e3 ff ff 0f 00 48 8d 14 c5 b8 01 00 00 89 45 cc 89 55 f0 e9 8c 01 00 00 8b 4d c8 8b 75 f0 8b 41 18 <8b> 54 30 04 8b 04 30 31 f6 89 5d dc 89 d1 8b 55 b8 0f c8 0f c9 Reported-by: Eric Sesterhenn <snakebyte@gmx.de> Signed-off-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/omfs/inode.c3
1 files changed, 1 insertions, 2 deletions
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
index a95fe5984f4b..d29047b1b9b0 100644
--- a/fs/omfs/inode.c
+++ b/fs/omfs/inode.c
@@ -232,8 +232,7 @@ struct inode *omfs_iget(struct super_block *sb, ino_t ino)
inode->i_mode = S_IFDIR | (S_IRWXUGO & ~sbi->s_dmask);
inode->i_op = &omfs_dir_inops;
inode->i_fop = &omfs_dir_operations;
- inode->i_size = be32_to_cpu(oi->i_head.h_body_size) +
- sizeof(struct omfs_header);
+ inode->i_size = sbi->s_sys_blocksize;
inc_nlink(inode);
break;
case OMFS_FILE: