| From 336a0809e583bf31353800b9c9221627302025b2 Mon Sep 17 00:00:00 2001 |
| From: Timo Warns <Warns@pre-sense.de> |
| Date: Mon, 14 Mar 2011 14:59:33 +0100 |
| Subject: [PATCH] Fix corrupted OSF partition table parsing |
| |
| commit 1eafbfeb7bdf59cfe173304c76188f3fd5f1fd05 upstream. |
| |
| The kernel automatically evaluates partition tables of storage devices. |
| The code for evaluating OSF partitions contains a bug that leaks data |
| from kernel heap memory to userspace for certain corrupted OSF |
| partitions. |
| |
| In more detail: |
| |
| for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) { |
| |
| iterates from 0 to d_npartitions - 1, where d_npartitions is read from |
| the partition table without validation and partition is a pointer to an |
| array of at most 8 d_partitions. |
| |
| Add the proper and obvious validation. |
| |
| Signed-off-by: Timo Warns <warns@pre-sense.de> |
| [ Changed the patch trivially to not repeat the whole le16_to_cpu() |
| thing, and to use an explicit constant for the magic value '8' ] |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c |
| index c05c17bc..6e0825e 100644 |
| --- a/fs/partitions/osf.c |
| +++ b/fs/partitions/osf.c |
| @@ -10,10 +10,13 @@ |
| #include "check.h" |
| #include "osf.h" |
| |
| +#define MAX_OSF_PARTITIONS 8 |
| + |
| int osf_partition(struct parsed_partitions *state, struct block_device *bdev) |
| { |
| int i; |
| int slot = 1; |
| + unsigned int npartitions; |
| Sector sect; |
| unsigned char *data; |
| struct disklabel { |
| @@ -45,7 +48,7 @@ int osf_partition(struct parsed_partitions *state, struct block_device *bdev) |
| u8 p_fstype; |
| u8 p_frag; |
| __le16 p_cpg; |
| - } d_partitions[8]; |
| + } d_partitions[MAX_OSF_PARTITIONS]; |
| } * label; |
| struct d_partition * partition; |
| |
| @@ -63,7 +66,12 @@ int osf_partition(struct parsed_partitions *state, struct block_device *bdev) |
| put_dev_sector(sect); |
| return 0; |
| } |
| - for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) { |
| + npartitions = le16_to_cpu(label->d_npartitions); |
| + if (npartitions > MAX_OSF_PARTITIONS) { |
| + put_dev_sector(sect); |
| + return 0; |
| + } |
| + for (i = 0 ; i < npartitions; i++, partition++) { |
| if (slot == state->limit) |
| break; |
| if (le32_to_cpu(partition->p_size)) |
| -- |
| 1.7.7 |
| |