summaryrefslogtreecommitdiff
path: root/super-intel.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2014-07-10 16:09:28 +1000
committerNeilBrown <neilb@suse.de>2014-07-10 16:10:23 +1000
commit095b8088fa99ad1195d1aba03af2aa561b4a6379 (patch)
tree9095185e6bb780a229c049593bda0039c0bfb2dd /super-intel.c
parent1f17f96b538793a0e665e471f602c6fa490ec167 (diff)
IMSM: validate metadata_update size before using it.
Every case in prepare_update check that the size message size is sufficient, so process_update doesn't need to check anything. Reported-by: Vincent Berg <vberg@ioactive.com> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'super-intel.c')
-rw-r--r--super-intel.c44
1 files changed, 41 insertions, 3 deletions
diff --git a/super-intel.c b/super-intel.c
index 2547b4a4..b4efa72b 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -8587,7 +8587,7 @@ static void imsm_process_update(struct supertype *st,
}
case update_add_remove_disk: {
/* we may be able to repair some arrays if disks are
- * being added, check teh status of add_remove_disk
+ * being added, check the status of add_remove_disk
* if discs has been added.
*/
if (add_remove_disk_update(super)) {
@@ -8617,19 +8617,28 @@ static int imsm_prepare_update(struct supertype *st,
* integrated by the monitor thread without worrying about live pointers
* in the manager thread.
*/
- enum imsm_update_type type = *(enum imsm_update_type *) update->buf;
+ enum imsm_update_type type;
struct intel_super *super = st->sb;
struct imsm_super *mpb = super->anchor;
size_t buf_len;
size_t len = 0;
+ if (update->len < (int)sizeof(type))
+ return 0;
+
+ type = *(enum imsm_update_type *) update->buf;
+
switch (type) {
case update_general_migration_checkpoint:
+ if (update->len < (int)sizeof(struct imsm_update_general_migration_checkpoint))
+ return 0;
dprintf("imsm: prepare_update() "
"for update_general_migration_checkpoint called\n");
break;
case update_takeover: {
struct imsm_update_takeover *u = (void *)update->buf;
+ if (update->len < (int)sizeof(*u))
+ return 0;
if (u->direction == R0_TO_R10) {
void **tail = (void **)&update->space_list;
struct imsm_dev *dev = get_imsm_dev(super, u->subarray);
@@ -8670,6 +8679,9 @@ static int imsm_prepare_update(struct supertype *st,
struct intel_dev *dl;
void **space_tail = (void**)&update->space_list;
+ if (update->len < (int)sizeof(*u))
+ return 0;
+
dprintf("imsm: imsm_prepare_update() for update_reshape\n");
for (dl = super->devlist; dl; dl = dl->next) {
@@ -8702,6 +8714,9 @@ static int imsm_prepare_update(struct supertype *st,
void *s;
int current_level = -1;
+ if (update->len < (int)sizeof(*u))
+ return 0;
+
dprintf("imsm: imsm_prepare_update() for update_reshape\n");
/* add space for bigger array in update
@@ -8769,6 +8784,13 @@ static int imsm_prepare_update(struct supertype *st,
break;
}
case update_size_change: {
+ if (update->len < (int)sizeof(struct imsm_update_size_change))
+ return 0;
+ break;
+ }
+ case update_activate_spare: {
+ if (update->len < (int)sizeof(struct imsm_update_activate_spare))
+ return 0;
break;
}
case update_create_array: {
@@ -8781,6 +8803,9 @@ static int imsm_prepare_update(struct supertype *st,
int i;
int activate = 0;
+ if (update->len < (int)sizeof(*u))
+ return 0;
+
inf = get_disk_info(u);
len = sizeof_imsm_dev(dev, 1);
/* allocate a new super->devlist entry */
@@ -8802,9 +8827,22 @@ static int imsm_prepare_update(struct supertype *st,
}
len += activate * sizeof(struct imsm_disk);
break;
- default:
+ }
+ case update_kill_array: {
+ if (update->len < (int)sizeof(struct imsm_update_kill_array))
+ return 0;
break;
}
+ case update_rename_array: {
+ if (update->len < (int)sizeof(struct imsm_update_rename_array))
+ return 0;
+ break;
+ }
+ case update_add_remove_disk:
+ /* no update->len needed */
+ break;
+ default:
+ return 0;
}
/* check if we need a larger metadata buffer */