| From stable-bounces@linux.kernel.org Fri Jul 25 11:15:18 2008 |
| From: James Bottomley <jejb@kernel.org> |
| Date: Fri, 25 Jul 2008 18:15:11 GMT |
| Subject: isofs: fix minor filesystem corruption |
| To: jejb@kernel.org, stable@kernel.org |
| Message-ID: <200807251815.m6PIFBwR029783@hera.kernel.org> |
| |
| From: Adam Greenblatt <adam.greenblatt@gmail.com> |
| |
| commit c0a1633b6201ef79e31b7da464d44fdf5953054d upstream |
| |
| Some iso9660 images contain files with rockridge data that is either |
| incorrect or incompletely parsed. Prior to commit |
| f2966632a134e865db3c819346a1dc7d96e05309 ("[PATCH] rock: handle directory |
| overflows") (included with kernel 2.6.13) the kernel ignored the rockridge |
| data for these files, while still allowing the files to be accessed under |
| their non-rockridge names. That commit inadvertently changed things so |
| that files with invalid rockridge data could not be accessed at all. (I |
| ran across the problem when comparing some old CDs with hard disk copies I |
| had made long ago under kernel 2.4: a few of the files on the hard disk |
| copies were no longer visible on the CDs.) |
| |
| This change reverts to the pre-2.6.13 behavior. |
| |
| Signed-off-by: Adam Greenblatt <adam.greenblatt@gmail.com> |
| Reviewed-by: Pekka Enberg <penberg@cs.helsinki.fi> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/isofs/rock.c | 22 ++++++++++++++++++++-- |
| 1 file changed, 20 insertions(+), 2 deletions(-) |
| |
| --- a/fs/isofs/rock.c |
| +++ b/fs/isofs/rock.c |
| @@ -209,6 +209,11 @@ repeat: |
| |
| while (rs.len > 2) { /* There may be one byte for padding somewhere */ |
| rr = (struct rock_ridge *)rs.chr; |
| + /* |
| + * Ignore rock ridge info if rr->len is out of range, but |
| + * don't return -EIO because that would make the file |
| + * invisible. |
| + */ |
| if (rr->len < 3) |
| goto out; /* Something got screwed up here */ |
| sig = isonum_721(rs.chr); |
| @@ -216,8 +221,12 @@ repeat: |
| goto eio; |
| rs.chr += rr->len; |
| rs.len -= rr->len; |
| + /* |
| + * As above, just ignore the rock ridge info if rr->len |
| + * is bogus. |
| + */ |
| if (rs.len < 0) |
| - goto eio; /* corrupted isofs */ |
| + goto out; /* Something got screwed up here */ |
| |
| switch (sig) { |
| case SIG('R', 'R'): |
| @@ -307,6 +316,11 @@ parse_rock_ridge_inode_internal(struct i |
| repeat: |
| while (rs.len > 2) { /* There may be one byte for padding somewhere */ |
| rr = (struct rock_ridge *)rs.chr; |
| + /* |
| + * Ignore rock ridge info if rr->len is out of range, but |
| + * don't return -EIO because that would make the file |
| + * invisible. |
| + */ |
| if (rr->len < 3) |
| goto out; /* Something got screwed up here */ |
| sig = isonum_721(rs.chr); |
| @@ -314,8 +328,12 @@ repeat: |
| goto eio; |
| rs.chr += rr->len; |
| rs.len -= rr->len; |
| + /* |
| + * As above, just ignore the rock ridge info if rr->len |
| + * is bogus. |
| + */ |
| if (rs.len < 0) |
| - goto eio; /* corrupted isofs */ |
| + goto out; /* Something got screwed up here */ |
| |
| switch (sig) { |
| #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ |