Skip to contentSkip to conversation

Bug in mtd_speedtest?

DISCUSSION David Lambert 3 participants 5 messages Mar 3, 2011 – Mar 7, 2011 Memory technology devices (MTD)

lore
Share & tools
lore
#0 lore raw

I think I may have found an overflow condition in the speed calculation of mtd_speedtest on some platforms with larger flash partitions:

Consider for example if goodebcnt = 15000, and mtd->erasesize = 256*1024, then there is an intermediate product of 3932160000 which results in the sign bit being set on a 32 bit integer. Maybe k should be an unsigned long long?

.....
static long calc_speed(void)

{
    long ms, k, speed;

    ms = (finish.tv_sec - start.tv_sec) * 1000 +
         (finish.tv_usec - start.tv_usec) / 1000;
    k = goodebcnt * mtd->erasesize / 1024;
    speed = (k * 1000) / ms;
    return speed;
}

.....

#1 lore raw
Quoted 7 lines · David Lambert

I think I may have found an overflow condition in the speed calculation of mtd_speedtest on some platforms with larger flash partitions:

Consider for example if goodebcnt = 15000, and mtd->erasesize = 256*1024, then there is an intermediate product of 3932160000 which results in the sign bit being set on a 32 bit integer. Maybe k should be an unsigned long long?

Please, just send a patch :-)

Signature · 2 lines
Best Regards,
Artem Bityutskiy (Артём Битюцкий)
#2 lore raw

Artem,
Please find attached patch.

Regards,

Dave.

Quoted 10 lines · Artem Bityutskiy
Quoted 7 lines · David Lambert

I think I may have found an overflow condition in the speed calculation of mtd_speedtest on some platforms with larger flash partitions:

Consider for example if goodebcnt = 15000, and mtd->erasesize = 256*1024, then there is an intermediate product of 3932160000 which results in the sign bit being set on a 32 bit integer. Maybe k should be an unsigned long long?

Please, just send a patch :-)

Index: mtd_speedtest.c
===================================================================
RCS file: /home/cvsroot/ECMB/src/snapgear/linux-2.6.30.1.x/drivers/mtd/tests/mtd_speedtest.c,v retrieving revision 1.1.1.1

mtd_speedtest.c +7 -6
diff -u -r1.1.1.1 mtd_speedtest.c
@@ -281,13 +281,14 @@
 
 static long calc_speed(void)
 {
-	long ms, k, speed;
+	uint64_t k;
+	long ms;
 
-	ms = (finish.tv_sec - start.tv_sec) * 1000 +
-	     (finish.tv_usec - start.tv_usec) / 1000;
-	k = goodebcnt * mtd->erasesize / 1024;
-	speed = (k * 1000) / ms;
-	return speed;
+	ms = (finish.tv_sec - start.tv_sec) * 1000 + /* Time in milli-seconds from start to ...*/
+	     (finish.tv_usec - start.tv_usec) / 1000;	  /* finish */
+	k = (goodebcnt * (mtd->erasesize / 1024) * 1000); /* Number of kBytes transferred * 1000 */
+	do_div(k, ms);	  /* k now contains number of kBytes/second */
+	return k;
 }
 
 static int scan_for_bad_eraseblocks(void)
#3 lore raw
Quoted 2 lines · [email protected] wrote:

Artem,
Please find attached patch.

The comments make lines over 80 chars and are not needed, it is clear enough from the code what it does.

--
Jon Povey
[email protected]

Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB .

The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network

#4 lore raw
In reply to David Lambert
Quoted 2 lines · David Lambert

Artem,
Please find attached patch.

Thank you, but you made pretty good job to prevent me from applying it! :-)

Quoted 6 lines

Index: mtd_speedtest.c
===================================================================
RCS
file: /home/cvsroot/ECMB/src/snapgear/linux-2.6.30.1.x/drivers/mtd/tests/mtd_speedtest.c,v retrieving revision 1.1.1.1
diff -u -r1.1.1.1 mtd_speedtest.c

This means git am won't work... neither patch -p1 ...
Also, not author name (From:), not commit message, not Signed-off-by...

Quoted 7 lines
mtd_speedtest.c 4 Mar 2011 17:51:23 -0000 renamed from mtd_speedtest.c 10 Aug 2009 19:42:00 -0000 1.1.1.1 +0 -1
@@ -281,13 +281,14 @@
 
 static long calc_speed(void)
 {
-       long ms, k, speed;

mtd_speedtest.c 4 Mar 2011 17:51:23 -0000 line 288

Quoted 10 lines
mtd_speedtest.c 4 Mar 2011 17:51:23 -0000 renamed from mtd_speedtest.c 10 Aug 2009 19:42:00 -0000 1.1.1.1 +4 -5
+       uint64_t k;
+       long ms;
 
-       ms = (finish.tv_sec - start.tv_sec) * 1000 +
-            (finish.tv_usec - start.tv_usec) / 1000;
-       k = goodebcnt * mtd->erasesize / 1024;
-       speed = (k * 1000) / ms;
-       return speed;
+       ms = (finish.tv_sec - start.tv_sec) * 1000 + /* Time in milli-seconds from start to ...*/
+            (finish.tv_usec - start.tv_usec) / 1000;     /* finish */

This would not pass scripts/checkpatch.pl. Please, kill the comments. Also, I you use spaces instead of tabs...

mtd_speedtest.c 4 Mar 2011 17:51:23 -0000 line 290

Quoted 2 lines
mtd_speedtest.c 4 Mar 2011 17:51:23 -0000 renamed from mtd_speedtest.c 10 Aug 2009 19:42:00 -0000 1.1.1.1 +2 -0
+       k = (goodebcnt * (mtd->erasesize / 1024) * 1000); /* Number of kBytes transferred * 1000 */
+       do_div(k, ms);    /* k now contains number of kBytes/second */

The old code had a check against ms == 0, you removed it, why?

mtd_speedtest.c 4 Mar 2011 17:51:23 -0000 line 291

Quoted 1 line
mtd_speedtest.c 4 Mar 2011 17:51:23 -0000 renamed from mtd_speedtest.c 10 Aug 2009 19:42:00 -0000 1.1.1.1 +1 -0
+       return k;

Anyway, since I anyway spent 20 minutes with this patch, here is what I ended up. I've pushed it to my l2 tree. If I made a mistake or you are unhappy about it, please, send your *properly formatted* version instead.

Thanks!

Quoted 1 line

From 008cfa97a772a83407a7e2657c0c5bfe36c7fc7f Mon Sep 17 00:00:00 2001

From: David Lambert <[email protected]>
Date: Mon, 7 Mar 2011 12:00:46 +0200
Subject: [PATCH] mtd: speedtest: fix integer overflow

32-bit integers used in 'calc_speed()' may overflow and lead to incorrect results. Use 64-bit integers instead.

---
 drivers/mtd/tests/mtd_speedtest.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)
drivers/mtd/tests/mtd_speedtest.c +7 -7
index 3ce6fce..22b51c1 100644
@@ -314,16 +314,16 @@ static inline void stop_timing(void)
 
 static long calc_speed(void)
 {
-	long ms, k, speed;
+       uint64_t k;
+       long ms;
 
 	ms = (finish.tv_sec - start.tv_sec) * 1000 +
 	     (finish.tv_usec - start.tv_usec) / 1000;
-	k = goodebcnt * mtd->erasesize / 1024;
-	if (ms)
-		speed = (k * 1000) / ms;
-	else
-		speed = 0;
-	return speed;
+	if (ms == 0)
+		return 0;
+	k = goodebcnt * (mtd->erasesize / 1024) * 1000;
+	do_div(k, ms);
+	return k;
 }
 
 static int scan_for_bad_eraseblocks(void)
Signature · 5 lines
1.7.2.3

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)