[PATCH] isofs: Handle corupted rock-ridge info slightly better Michal Zalewski discovers range checking flaws in iso9660 filesystem. http://marc.theaimsgroup.com/?l=bugtraq&m=111110067304783&w=2 CAN-2005-0815 is assigned to this issue. From: Linus Torvalds isofs: Handle corupted rock-ridge info slightly better. Keyword here being 'slightly'. The code is a mess. Signed-off-by: Chris Wright rock.c | 21 ++++++++++++++------- 1 files changed, 14 insertions(+), 7 deletions(-) diff -Nru a/fs/isofs/rock.c b/fs/isofs/rock.c --- a/fs/isofs/rock.c 2005-03-26 11:29:07 -08:00 +++ b/fs/isofs/rock.c 2005-03-26 11:29:07 -08:00 @@ -53,6 +53,7 @@ if(LEN & 1) LEN++; \ CHR = ((unsigned char *) DE) + LEN; \ LEN = *((unsigned char *) DE) - LEN; \ + if (LEN<0) LEN=0; \ if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1) \ { \ LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset; \ @@ -103,12 +104,13 @@ struct rock_ridge * rr; int sig; - while (len > 1){ /* There may be one byte for padding somewhere */ + while (len > 2){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; - if (rr->len == 0) goto out; /* Something got screwed up here */ + if (rr->len < 3) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; + if (len < 0) goto out; /* corrupted isofs */ switch(sig){ case SIG('R','R'): @@ -122,6 +124,7 @@ break; case SIG('N','M'): if (truncate) break; + if (rr->len < 5) break; /* * If the flags are 2 or 4, this indicates '.' or '..'. * We don't want to do anything with this, because it @@ -186,12 +189,13 @@ struct rock_ridge * rr; int rootflag; - while (len > 1){ /* There may be one byte for padding somewhere */ + while (len > 2){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; - if (rr->len == 0) goto out; /* Something got screwed up here */ + if (rr->len < 3) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; + if (len < 0) goto out; /* corrupted isofs */ switch(sig){ #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ @@ -462,7 +466,7 @@ struct rock_ridge *rr; if (!ISOFS_SB(inode->i_sb)->s_rock) - panic ("Cannot have symlink with high sierra variant of iso filesystem\n"); + goto error; block = ei->i_iget5_block; lock_kernel(); @@ -487,13 +491,15 @@ SETUP_ROCK_RIDGE(raw_inode, chr, len); repeat: - while (len > 1) { /* There may be one byte for padding somewhere */ + while (len > 2) { /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; - if (rr->len == 0) + if (rr->len < 3) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; + if (len < 0) + goto out; /* corrupted isofs */ switch (sig) { case SIG('R', 'R'): @@ -543,6 +549,7 @@ fail: brelse(bh); unlock_kernel(); + error: SetPageError(page); kunmap(page); unlock_page(page);