aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-12-19 14:27:55 +0100
committerMister Oyster <oysterized@gmail.com>2017-04-29 21:25:19 +0200
commit15d43156a77210e34316e9b48f74ea1d5b8b4bf0 (patch)
tree84dd2990591324acb13c3ff07cb7cc9e919bbbce
parent81e2f2306b07bd1cc8d9a715df0b4dc0588c0eba (diff)
downloadandroid_kernel_m2note-15d43156a77210e34316e9b48f74ea1d5b8b4bf0.tar.gz
BACKPORT: [UPSTREAM] udf: Check component length before reading it
(Cherry-pick from commit e237ec37ec154564f8690c5bd1795339955eeef9) 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> Bug: 35808154 Change-Id: I1bb9856ab8ae5164291b82065160e17817328c0b
-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 2d0c3720e..0422b7b83 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';