Commit e595447e authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 9eb7f2c6
...@@ -81,9 +81,22 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode) ...@@ -81,9 +81,22 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode)
static int rock_continue(struct rock_state *rs) static int rock_continue(struct rock_state *rs)
{ {
int ret = 1; int ret = 1;
int blocksize = 1 << rs->inode->i_blkbits;
const int min_de_size = offsetof(struct rock_ridge, u);
kfree(rs->buffer); kfree(rs->buffer);
rs->buffer = NULL; rs->buffer = NULL;
if ((unsigned)rs->cont_offset > blocksize - min_de_size ||
(unsigned)rs->cont_size > blocksize ||
(unsigned)(rs->cont_offset + rs->cont_size) > blocksize) {
printk(KERN_NOTICE "rock: corrupted directory entry. "
"extent=%d, offset=%d, size=%d\n",
rs->cont_extent, rs->cont_offset, rs->cont_size);
ret = -EIO;
goto out;
}
if (rs->cont_extent) { if (rs->cont_extent) {
struct buffer_head *bh; struct buffer_head *bh;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment