Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] rock.c: handle corrupted directories

The bug in rock.c is that it's totally trusting of the contents of the
directories. If the directory says there's a continuation 10000 bytes into
this 4k block then we cheerily poke around in memory we don't own and oops.

So change rock_continue() to apply various sanity checks, at least ensuring
that the offset+length remain within the bounds for the header part of a
struct rock_ridge directory entry.

Note that the kernel can still overindex the buffer due to the variable size
of the rock-ridge directory entries. We cannot check that in rock_continue()
unless we go parse the directory entry's signature and work out its size.

Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Andrew Morton and committed by
Linus Torvalds
e595447e 9eb7f2c6

+13
+13
fs/isofs/rock.c
··· 81 81 static int rock_continue(struct rock_state *rs) 82 82 { 83 83 int ret = 1; 84 + int blocksize = 1 << rs->inode->i_blkbits; 85 + const int min_de_size = offsetof(struct rock_ridge, u); 84 86 85 87 kfree(rs->buffer); 86 88 rs->buffer = NULL; 89 + 90 + if ((unsigned)rs->cont_offset > blocksize - min_de_size || 91 + (unsigned)rs->cont_size > blocksize || 92 + (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) { 93 + printk(KERN_NOTICE "rock: corrupted directory entry. " 94 + "extent=%d, offset=%d, size=%d\n", 95 + rs->cont_extent, rs->cont_offset, rs->cont_size); 96 + ret = -EIO; 97 + goto out; 98 + } 99 + 87 100 if (rs->cont_extent) { 88 101 struct buffer_head *bh; 89 102