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 --- fs/isofs/rock.c | 13 +++++++++++++ 1 files changed, 13 insertions(+) diff -puN fs/isofs/rock.c~rock-handle-corrupted-directories fs/isofs/rock.c --- 25/fs/isofs/rock.c~rock-handle-corrupted-directories 2005-04-26 19:27:18.001990024 -0700 +++ 25-akpm/fs/isofs/rock.c 2005-04-26 19:27:18.005989416 -0700 @@ -81,9 +81,22 @@ static void init_rock_state(struct rock_ static int rock_continue(struct rock_state *rs) { int ret = 1; + int blocksize = 1 << rs->inode->i_blkbits; + const int min_de_size = offsetof(struct rock_ridge, u); kfree(rs->buffer); 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) { struct buffer_head *bh; _