a98a8d
From: Jan Kara <jack@suse.cz>
a98a8d
Date: Mon, 15 Dec 2014 14:22:46 +0100
a98a8d
Subject: [PATCH] isofs: Fix infinite looping over CE entries
a98a8d
a98a8d
Rock Ridge extensions define so called Continuation Entries (CE) which
a98a8d
define where is further space with Rock Ridge data. Corrupted isofs
a98a8d
image can contain arbitrarily long chain of these, including a one
a98a8d
containing loop and thus causing kernel to end in an infinite loop when
a98a8d
traversing these entries.
a98a8d
a98a8d
Limit the traversal to 32 entries which should be more than enough space
a98a8d
to store all the Rock Ridge data.
a98a8d
a98a8d
Reported-by: P J P <ppandit@redhat.com>
a98a8d
CC: stable@vger.kernel.org
a98a8d
Signed-off-by: Jan Kara <jack@suse.cz>
a98a8d
---
a98a8d
 fs/isofs/rock.c | 6 ++++++
a98a8d
 1 file changed, 6 insertions(+)
a98a8d
a98a8d
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
a98a8d
index f488bbae541a..bb63254ed848 100644
a98a8d
--- a/fs/isofs/rock.c
a98a8d
+++ b/fs/isofs/rock.c
a98a8d
@@ -30,6 +30,7 @@ struct rock_state {
a98a8d
 	int cont_size;
a98a8d
 	int cont_extent;
a98a8d
 	int cont_offset;
a98a8d
+	int cont_loops;
a98a8d
 	struct inode *inode;
a98a8d
 };
a98a8d
 
a98a8d
@@ -73,6 +74,9 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode)
a98a8d
 	rs->inode = inode;
a98a8d
 }
a98a8d
 
a98a8d
+/* Maximum number of Rock Ridge continuation entries */
a98a8d
+#define RR_MAX_CE_ENTRIES 32
a98a8d
+
a98a8d
 /*
a98a8d
  * Returns 0 if the caller should continue scanning, 1 if the scan must end
a98a8d
  * and -ve on error.
a98a8d
@@ -105,6 +109,8 @@ static int rock_continue(struct rock_state *rs)
a98a8d
 			goto out;
a98a8d
 		}
a98a8d
 		ret = -EIO;
a98a8d
+		if (++rs->cont_loops >= RR_MAX_CE_ENTRIES)
a98a8d
+			goto out;
a98a8d
 		bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
a98a8d
 		if (bh) {
a98a8d
 			memcpy(rs->buffer, bh->b_data + rs->cont_offset,
a98a8d
-- 
a98a8d
2.1.0
a98a8d