Commit c0a1633b authored by Adam Greenblatt's avatar Adam Greenblatt Committed by Linus Torvalds

isofs: fix minor filesystem corruption

Some iso9660 images contain files with rockridge data that is either
incorrect or incompletely parsed.  Prior to commit
f2966632 ("[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: default avatarAdam Greenblatt <adam.greenblatt@gmail.com>
Reviewed-by: default avatarPekka Enberg <penberg@cs.helsinki.fi>
Cc: <stable@kernel.org>		[2.6.25.x, 2.6.26.x]
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 275c0a8f
...@@ -209,6 +209,11 @@ int get_rock_ridge_filename(struct iso_directory_record *de, ...@@ -209,6 +209,11 @@ int get_rock_ridge_filename(struct iso_directory_record *de,
while (rs.len > 2) { /* There may be one byte for padding somewhere */ while (rs.len > 2) { /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *)rs.chr; 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) if (rr->len < 3)
goto out; /* Something got screwed up here */ goto out; /* Something got screwed up here */
sig = isonum_721(rs.chr); sig = isonum_721(rs.chr);
...@@ -216,8 +221,12 @@ int get_rock_ridge_filename(struct iso_directory_record *de, ...@@ -216,8 +221,12 @@ int get_rock_ridge_filename(struct iso_directory_record *de,
goto eio; goto eio;
rs.chr += rr->len; rs.chr += rr->len;
rs.len -= rr->len; rs.len -= rr->len;
/*
* As above, just ignore the rock ridge info if rr->len
* is bogus.
*/
if (rs.len < 0) if (rs.len < 0)
goto eio; /* corrupted isofs */ goto out; /* Something got screwed up here */
switch (sig) { switch (sig) {
case SIG('R', 'R'): case SIG('R', 'R'):
...@@ -307,6 +316,11 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de, ...@@ -307,6 +316,11 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de,
repeat: repeat:
while (rs.len > 2) { /* There may be one byte for padding somewhere */ while (rs.len > 2) { /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *)rs.chr; 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) if (rr->len < 3)
goto out; /* Something got screwed up here */ goto out; /* Something got screwed up here */
sig = isonum_721(rs.chr); sig = isonum_721(rs.chr);
...@@ -314,8 +328,12 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de, ...@@ -314,8 +328,12 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de,
goto eio; goto eio;
rs.chr += rr->len; rs.chr += rr->len;
rs.len -= rr->len; rs.len -= rr->len;
/*
* As above, just ignore the rock ridge info if rr->len
* is bogus.
*/
if (rs.len < 0) if (rs.len < 0)
goto eio; /* corrupted isofs */ goto out; /* Something got screwed up here */
switch (sig) { switch (sig) {
#ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment