diff options
author | Jan Kara <jack@suse.cz> | 2014-12-19 08:27:55 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2014-12-21 16:42:19 -0500 |
commit | e237ec37ec154564f8690c5bd1795339955eeef9 (patch) | |
tree | 33e14928a5c2fdee03df67e2e1e4f9991e056fc7 /fs/udf/symlink.c | |
parent | 0e5cc9a40ada6046e6bc3bdfcd0c0d7e4b706b14 (diff) |
udf: Check component length before reading it
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>
Diffstat (limited to 'fs/udf/symlink.c')
-rw-r--r-- | fs/udf/symlink.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 0f1b3a2654b9..ac10ca939f26 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, | |||
42 | tolen--; | 42 | tolen--; |
43 | while (elen < fromlen) { | 43 | while (elen < fromlen) { |
44 | pc = (struct pathComponent *)(from + elen); | 44 | pc = (struct pathComponent *)(from + elen); |
45 | elen += sizeof(struct pathComponent); | ||
45 | switch (pc->componentType) { | 46 | switch (pc->componentType) { |
46 | case 1: | 47 | case 1: |
47 | /* | 48 | /* |
48 | * Symlink points to some place which should be agreed | 49 | * Symlink points to some place which should be agreed |
49 | * upon between originator and receiver of the media. Ignore. | 50 | * upon between originator and receiver of the media. Ignore. |
50 | */ | 51 | */ |
51 | if (pc->lengthComponentIdent > 0) | 52 | if (pc->lengthComponentIdent > 0) { |
53 | elen += pc->lengthComponentIdent; | ||
52 | break; | 54 | break; |
55 | } | ||
53 | /* Fall through */ | 56 | /* Fall through */ |
54 | case 2: | 57 | case 2: |
55 | if (tolen == 0) | 58 | if (tolen == 0) |
@@ -74,6 +77,9 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from, | |||
74 | /* that would be . - just ignore */ | 77 | /* that would be . - just ignore */ |
75 | break; | 78 | break; |
76 | case 5: | 79 | case 5: |
80 | elen += pc->lengthComponentIdent; | ||
81 | if (elen > fromlen) | ||
82 | return -EIO; | ||
77 | comp_len = udf_get_filename(sb, pc->componentIdent, | 83 | comp_len = udf_get_filename(sb, pc->componentIdent, |
78 | pc->lengthComponentIdent, | 84 | pc->lengthComponentIdent, |
79 | p, tolen); | 85 | p, tolen); |
@@ -85,7 +91,6 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from, | |||
85 | tolen--; | 91 | tolen--; |
86 | break; | 92 | break; |
87 | } | 93 | } |
88 | elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; | ||
89 | } | 94 | } |
90 | if (p > to + 1) | 95 | if (p > to + 1) |
91 | p[-1] = '\0'; | 96 | p[-1] = '\0'; |