From: torvalds@osdl.org Date: Sat, 26 Mar 2005 01:44:34 +0000 (-0800) Subject: [PATCH] isofs: Handle corupted rock-ridge info slightly better X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9e3f38e578c2ae67dd582c8583177c7bce41a86b;p=thirdparty%2Fkernel%2Fstable.git [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 --- diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 19d999fd450c2..1c8d997d44a71 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -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 @@ int get_rock_ridge_filename(struct iso_directory_record * de, 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 @@ int get_rock_ridge_filename(struct iso_directory_record * de, 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 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de, 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 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page) 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 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page) 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 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page) fail: brelse(bh); unlock_kernel(); + error: SetPageError(page); kunmap(page); unlock_page(page);