aboutsummaryrefslogtreecommitdiffstats
path: root/fs/isofs
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-12-15 08:22:46 -0500
committerJan Kara <jack@suse.cz>2014-12-15 09:53:26 -0500
commitf54e18f1b831c92f6512d2eedb224cd63d607d3d (patch)
tree5b24ced61a9bda1f5ae41196a39a96c88b19229b /fs/isofs
parentfa0c5540739320258c3e3a45aaae9dae467b2504 (diff)
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>
Diffstat (limited to 'fs/isofs')
-rw-r--r--fs/isofs/rock.c6
1 files changed, 6 insertions, 0 deletions
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 {
30 int cont_size; 30 int cont_size;
31 int cont_extent; 31 int cont_extent;
32 int cont_offset; 32 int cont_offset;
33 int cont_loops;
33 struct inode *inode; 34 struct inode *inode;
34}; 35};
35 36
@@ -73,6 +74,9 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode)
73 rs->inode = inode; 74 rs->inode = inode;
74} 75}
75 76
77/* Maximum number of Rock Ridge continuation entries */
78#define RR_MAX_CE_ENTRIES 32
79
76/* 80/*
77 * Returns 0 if the caller should continue scanning, 1 if the scan must end 81 * Returns 0 if the caller should continue scanning, 1 if the scan must end
78 * and -ve on error. 82 * and -ve on error.
@@ -105,6 +109,8 @@ static int rock_continue(struct rock_state *rs)
105 goto out; 109 goto out;
106 } 110 }
107 ret = -EIO; 111 ret = -EIO;
112 if (++rs->cont_loops >= RR_MAX_CE_ENTRIES)
113 goto out;
108 bh = sb_bread(rs->inode->i_sb, rs->cont_extent); 114 bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
109 if (bh) { 115 if (bh) {
110 memcpy(rs->buffer, bh->b_data + rs->cont_offset, 116 memcpy(rs->buffer, bh->b_data + rs->cont_offset,