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