Yidi Lin has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/78888?usp=email )
Change subject: libpayload/libc/time: Fix possible overflow in multiplication ......................................................................
libpayload/libc/time: Fix possible overflow in multiplication
The value from raw_read_cntfrq_el0() could be large enough to cause overflow when multiplied by 1000000. To prevent this, both 1000000 and hz can be reduced by dividing them by their GCD.
BUG=b:307790895 TEST=boot to kernel and check the timestamps from `cbmem`
Change-Id: Ia55532490651fcf47128b83a8554751f050bcc89 Signed-off-by: Yidi Lin yidilin@chromium.org --- M payloads/libpayload/libc/time.c 1 file changed, 12 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/88/78888/1
diff --git a/payloads/libpayload/libc/time.c b/payloads/libpayload/libc/time.c index 6780008..b6be116 100644 --- a/payloads/libpayload/libc/time.c +++ b/payloads/libpayload/libc/time.c @@ -33,6 +33,7 @@
#define __STDC_FORMAT_MACROS
+#include <commonlib/bsd/gcd.h> #include <libpayload-config.h> #include <libpayload.h> #if CONFIG(LP_ARCH_X86) && CONFIG(LP_NVRAM) @@ -171,6 +172,8 @@ u64 timer_us(u64 base) { static u64 hz; + static u32 mult; + u32 div;
// Only check timer_hz once. Assume it doesn't change. if (hz == 0) { @@ -180,7 +183,15 @@ "must be at least 1MHz.\n", hz); halt(); } + mult = 1000000; + /* + * Bits[63:32] of CNTFRQ_EL0 are reserved. So it is safe to cast + * hz to uint32_t. + */ + div = gcd32(hz, mult); + hz /= div; + mult /= div; }
- return (1000000 * timer_raw_value()) / hz - base; + return (mult * timer_raw_value()) / hz - base; }