diff options
author | Timo Warns <Warns@pre-sense.de> | 2011-04-14 18:21:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-14 19:06:54 -0400 |
commit | c340b1d640001c8c9ecff74f68fd90422ae2448a (patch) | |
tree | 2615bb9abb9fb956197c8f357dee388d15d82d81 /fs/partitions | |
parent | c344180c9e77145a9e7eab0050169c68afae04b2 (diff) |
fs/partitions/ldm.c: fix oops caused by corrupted partition table
The kernel automatically evaluates partition tables of storage devices.
The code for evaluating LDM partitions (in fs/partitions/ldm.c) contains
a bug that causes a kernel oops on certain corrupted LDM partitions.
A kernel subsystem seems to crash, because, after the oops, the kernel no
longer recognizes newly connected storage devices.
The patch validates the value of vblk_size.
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Timo Warns <warns@pre-sense.de>
Cc: Eugene Teo <eugeneteo@kernel.sg>
Cc: Harvey Harrison <harvey.harrison@gmail.com>
Cc: Richard Russon <rich@flatcap.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/partitions')
-rw-r--r-- | fs/partitions/ldm.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c index b10e3540d5b7..ce4f62440425 100644 --- a/fs/partitions/ldm.c +++ b/fs/partitions/ldm.c | |||
@@ -1299,6 +1299,11 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags) | |||
1299 | 1299 | ||
1300 | BUG_ON (!data || !frags); | 1300 | BUG_ON (!data || !frags); |
1301 | 1301 | ||
1302 | if (size < 2 * VBLK_SIZE_HEAD) { | ||
1303 | ldm_error("Value of size is to small."); | ||
1304 | return false; | ||
1305 | } | ||
1306 | |||
1302 | group = get_unaligned_be32(data + 0x08); | 1307 | group = get_unaligned_be32(data + 0x08); |
1303 | rec = get_unaligned_be16(data + 0x0C); | 1308 | rec = get_unaligned_be16(data + 0x0C); |
1304 | num = get_unaligned_be16(data + 0x0E); | 1309 | num = get_unaligned_be16(data + 0x0E); |
@@ -1306,6 +1311,10 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags) | |||
1306 | ldm_error ("A VBLK claims to have %d parts.", num); | 1311 | ldm_error ("A VBLK claims to have %d parts.", num); |
1307 | return false; | 1312 | return false; |
1308 | } | 1313 | } |
1314 | if (rec >= num) { | ||
1315 | ldm_error("REC value (%d) exceeds NUM value (%d)", rec, num); | ||
1316 | return false; | ||
1317 | } | ||
1309 | 1318 | ||
1310 | list_for_each (item, frags) { | 1319 | list_for_each (item, frags) { |
1311 | f = list_entry (item, struct frag, list); | 1320 | f = list_entry (item, struct frag, list); |
@@ -1334,10 +1343,9 @@ found: | |||
1334 | 1343 | ||
1335 | f->map |= (1 << rec); | 1344 | f->map |= (1 << rec); |
1336 | 1345 | ||
1337 | if (num > 0) { | 1346 | data += VBLK_SIZE_HEAD; |
1338 | data += VBLK_SIZE_HEAD; | 1347 | size -= VBLK_SIZE_HEAD; |
1339 | size -= VBLK_SIZE_HEAD; | 1348 | |
1340 | } | ||
1341 | memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size); | 1349 | memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size); |
1342 | 1350 | ||
1343 | return true; | 1351 | return true; |