Hi,

the howmany macro as used in param.h and select.h is prone to an integer
overflow.  It adds divisor-1 to the base value, which means that it
COULD overflow.

Most of the times, the howmany macro is used with file descriptors and
polling, would be hard to overflow it.  Especially due to C language
specifications and implicit casts.  But there are other use cases...

In setup.c of fsck_ffs, howmany is used to calculate the required size
to hold a block map for the file system to be checked:

bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t));
blockmap = calloc((unsigned)bmapsize, sizeof(char));

The value of maxfsblock is read from superblock and is 64 bit, adding 7
can let it overflow which means bmapsize becomes 0 and later access to
the blockmap will result in out of boundary access.  (FYI: fsck_ffs
would fail after calloc without bmapsize's overflow, map would be too
large for memory.)

I chose the fsck_ffs example because it's easier to modify a filesystem
to be "broken" compared to having a storage that is large enough. ;)

This diff only adjusts param.h and is merely an idea I would like to
discuss.  Using a modulo operation, the overflow can be prevented.
But I don't know how significant this operation will be when it comes
to performance.  Or if howmany should not be used for these operations
at all.

Thoughts, anyone?


Tobias

Index: param.h
===================================================================
RCS file: /cvs/src/sys/sys/param.h,v
retrieving revision 1.106
diff -u -p -r1.106 param.h
--- param.h     2 May 2014 19:03:06 -0000       1.106
+++ param.h     14 Jun 2014 10:33:06 -0000
@@ -207,9 +207,9 @@
 
 /* Macros for counting and rounding. */
 #ifndef howmany
-#define        howmany(x, y)   (((x)+((y)-1))/(y))
+#define        howmany(x, y)   ((x)/(y)+((x)%(y)?1:0)
 #endif
-#define        roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
+#define        roundup(x, y)   (howmany((x),(y))*(y))
 #define powerof2(x)    ((((x)-1)&(x))==0)
 
 /* Macros for min/max. */

Reply via email to