From: Alex Zhuravlev Date: Thu, 3 Jun 2010 05:01:14 +0000 (-0700) Subject: Stack overflow on 64-bit modulus operations on 32-bit architectures. X-Git-Tag: zfs-0.8.0-rc1~152^2~593 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1b4ad25e2f29172c86d3293b61f0c5232d4a2da8;p=zfs Stack overflow on 64-bit modulus operations on 32-bit architectures. Running 'zpool create' on a 32-bit machine with an SPL compiled with gcc 4.4.4 led to a stack overlow. This turned out to be due to some sort of 'optimization' by gcc: uint64_t __umoddi3(uint64_t dividend, uint64_t divisor) { return dividend - divisor * (dividend / divisor); } This code was supposed to be using __udivdi3 to implement /, but gcc instead implemented it via __umoddi3 itself. Signed-off-by: Brian Behlendorf --- diff --git a/module/spl/spl-generic.c b/module/spl/spl-generic.c index 29b698889..9916051de 100644 --- a/module/spl/spl-generic.c +++ b/module/spl/spl-generic.c @@ -96,7 +96,8 @@ EXPORT_SYMBOL(highbit); * Implementation of 64 bit division for 32-bit machines. */ #if BITS_PER_LONG == 32 -uint64_t __udivdi3(uint64_t dividend, uint64_t divisor) +uint64_t +__udivdi3(uint64_t dividend, uint64_t divisor) { #if defined(HAVE_DIV64_64) /* 2.6.22 - 2.6.25 API */ return div64_64(dividend, divisor); @@ -125,9 +126,10 @@ EXPORT_SYMBOL(__udivdi3); /* * Implementation of 64 bit modulo for 32-bit machines. */ -uint64_t __umoddi3(uint64_t dividend, uint64_t divisor) +uint64_t +__umoddi3(uint64_t dividend, uint64_t divisor) { - return dividend - divisor * (dividend / divisor); + return (dividend - (divisor * __udivdi3(dividend, divisor))); } EXPORT_SYMBOL(__umoddi3); #endif /* BITS_PER_LONG */