[PATCH] isofs: Handle corupted rock-ridge info slightly better.
Linux Kernel Mailing List <[email protected]> Fri, 25 Mar 2005 23:50:06 +0000
| Newsgroups | gmane.linux.kernel.commits.2-4 |
|---|---|
| Message-ID | <[email protected]> |
ChangeSet 1.1483, 2005/03/25 20:50:06-03:00, [email protected] [PATCH] isofs: Handle corupted rock-ridge info slightly better. Michal Zalewski <[email protected]> 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 <[email protected]> isofs: Handle corupted rock-ridge info slightly better. Keyword here being 'slightly'. The code is a mess. Signed-off-by: Chris Wright <[email protected]> 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 13:02:48 -08:00 +++ b/fs/isofs/rock.c 2005-03-26 13:02:48 -08:00 @@ -52,6 +52,7 @@ if(LEN & 1) LEN++; \ CHR = ((unsigned char *) DE) + LEN; \ LEN = *((unsigned char *) DE) - LEN; \ + if (LEN<0) LEN=0; \ if (inode->i_sb->u.isofs_sb.s_rock_offset!=-1) \ { \ LEN-=inode->i_sb->u.isofs_sb.s_rock_offset; \ @@ -172,12 +173,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'): @@ -191,6 +193,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 @@ -252,12 +255,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 */ @@ -523,7 +527,7 @@ struct rock_ridge *rr; if (!inode->i_sb->u.isofs_sb.s_rock) - panic ("Cannot have symlink with high sierra variant of iso filesystem\n"); + goto error; block = inode->i_ino >> bufbits; lock_kernel(); @@ -547,13 +551,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'): @@ -601,6 +607,7 @@ fail: brelse(bh); unlock_kernel(); + error: SetPageError(page); kunmap(page); UnlockPage(page);