summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-12-19 14:27:55 +0100
committerJiri Slaby <jslaby@suse.cz>2015-02-16 16:10:56 +0100
commitc94011ac6ae0bbfc8966ec256ad7b1bf30feaeec (patch)
tree47768c3a148fc64650554dd4ab2cfc6fa4b223eb
parentebfce5ccba81292a5e34710a602117769118fa9a (diff)
downloadlwn-c94011ac6ae0bbfc8966ec256ad7b1bf30feaeec.tar.gz
lwn-c94011ac6ae0bbfc8966ec256ad7b1bf30feaeec.zip
udf: Check component length before reading it
commit e237ec37ec154564f8690c5bd1795339955eeef9 upstream. Check that length specified in a component of a symlink fits in the input buffer we are reading. Also properly ignore component length for component types that do not use it. Otherwise we read memory after end of buffer for corrupted udf image. Reported-by: Carl Henrik Lunde <chlunde@ping.uio.no> CC: stable@vger.kernel.org Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
-rw-r--r--fs/udf/symlink.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index 2d0c3720e9af..0422b7b8369f 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -42,14 +42,17 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
tolen--;
while (elen < fromlen) {
pc = (struct pathComponent *)(from + elen);
+ elen += sizeof(struct pathComponent);
switch (pc->componentType) {
case 1:
/*
* Symlink points to some place which should be agreed
* upon between originator and receiver of the media. Ignore.
*/
- if (pc->lengthComponentIdent > 0)
+ if (pc->lengthComponentIdent > 0) {
+ elen += pc->lengthComponentIdent;
break;
+ }
/* Fall through */
case 2:
if (tolen == 0)
@@ -74,6 +77,9 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
/* that would be . - just ignore */
break;
case 5:
+ elen += pc->lengthComponentIdent;
+ if (elen > fromlen)
+ return -EIO;
comp_len = udf_get_filename(sb, pc->componentIdent,
pc->lengthComponentIdent,
p, tolen);
@@ -85,7 +91,6 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
tolen--;
break;
}
- elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
}
if (p > to + 1)
p[-1] = '\0';