aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2005-06-21 20:16:50 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-21 22:07:38 -0400
commite595447e177b39aa6c96baaa57b30cde2d8b9df7 (patch)
tree7c6c1be2e623fc3cefb1a0afcb51247293a393eb
parent9eb7f2c67c41d2cd730aedcd23e5baca09211d03 (diff)
[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>
-rw-r--r--fs/isofs/rock.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 977dd7009c07..9a81830abff8 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -81,9 +81,22 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode)
81static int rock_continue(struct rock_state *rs) 81static int rock_continue(struct rock_state *rs)
82{ 82{
83 int ret = 1; 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 kfree(rs->buffer); 87 kfree(rs->buffer);
86 rs->buffer = NULL; 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 if (rs->cont_extent) { 100 if (rs->cont_extent) {
88 struct buffer_head *bh; 101 struct buffer_head *bh;
89 102