UBI: fix overflow bug
authorVinit Agnihotri <vinit.agnihotri@gmail.com>
Tue, 10 Jul 2007 10:04:59 +0000 (13:04 +0300)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Wed, 18 Jul 2007 13:58:12 +0000 (16:58 +0300)
I was experiencing overflows in multiplications for
volume->used_bytes in vmt.c & vtbl.c, while creating & resizing large volumes.

vol->used_bytes is long long however its 2 operands vol->used_ebs &
vol->usable_leb_size
are int. So their multiplication for larger values causes integer overflows.
Typecasting them solves the problem.

My machine & flash details:

64Bit dual-core AMD opteron, 1 GB RAM, linux 2.6.18.3.
mtd size = 6GB, volume size= 5GB, peb_size = 4MB.

heres patch which does the fix.

Signed-off-by: Vinit Agnihotri <vinit.agnihotri@gmail.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
drivers/mtd/ubi/vmt.c
drivers/mtd/ubi/vtbl.c

index d62dac90e1087409faa00f094a3e5b3f935e9c0b..ea0d5c825ab41034b5dd4b91cfba6ce587680fbe 100644 (file)
@@ -280,7 +280,8 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
        if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
                vol->used_ebs = vol->reserved_pebs;
                vol->last_eb_bytes = vol->usable_leb_size;
-               vol->used_bytes = vol->used_ebs * vol->usable_leb_size;
+               vol->used_bytes =
+                       (long long)vol->used_ebs * vol->usable_leb_size;
        } else {
                bytes = vol->used_bytes;
                vol->last_eb_bytes = do_div(bytes, vol->usable_leb_size);
@@ -538,7 +539,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
        if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
                vol->used_ebs = reserved_pebs;
                vol->last_eb_bytes = vol->usable_leb_size;
-               vol->used_bytes = vol->used_ebs * vol->usable_leb_size;
+               vol->used_bytes =
+                       (long long)vol->used_ebs * vol->usable_leb_size;
        }
 
        paranoid_check_volumes(ubi);
@@ -739,7 +741,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
                goto fail;
        }
 
-       n = vol->used_ebs * vol->usable_leb_size;
+       n = (long long)vol->used_ebs * vol->usable_leb_size;
        if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
                if (vol->corrupted != 0) {
                        ubi_err("corrupted dynamic volume");
index 1f48c76cf6fe1a9dd37988a1ba78b07394b2b043..bc5df50813d67cc2cbd8bd635dbd8e11657cbb8c 100644 (file)
@@ -531,7 +531,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
                if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
                        vol->used_ebs = vol->reserved_pebs;
                        vol->last_eb_bytes = vol->usable_leb_size;
-                       vol->used_bytes = vol->used_ebs * vol->usable_leb_size;
+                       vol->used_bytes =
+                               (long long)vol->used_ebs * vol->usable_leb_size;
                        continue;
                }
 
@@ -561,7 +562,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
                }
 
                vol->used_ebs = sv->used_ebs;
-               vol->used_bytes = (vol->used_ebs - 1) * vol->usable_leb_size;
+               vol->used_bytes =
+                       (long long)(vol->used_ebs - 1) * vol->usable_leb_size;
                vol->used_bytes += sv->last_data_size;
                vol->last_eb_bytes = sv->last_data_size;
        }
@@ -578,7 +580,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
        vol->usable_leb_size = ubi->leb_size;
        vol->used_ebs = vol->reserved_pebs;
        vol->last_eb_bytes = vol->reserved_pebs;
-       vol->used_bytes = vol->used_ebs * (ubi->leb_size - vol->data_pad);
+       vol->used_bytes =
+               (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad);
        vol->vol_id = UBI_LAYOUT_VOL_ID;
 
        ubi_assert(!ubi->volumes[i]);