From abb1b54bfe7660e66d184eea000d89f9e47c060c Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Wed, 27 May 2015 12:58:42 -0400 Subject: [PATCH] Fix an overflow that can cause spuriously short epoll timeouts. Lease times and arp timeouts are all calculated using long long, but epoll takes its timeout argument as an int. Guard against timeouts > INT_MAX but < UINT_MAX wrapping and causing spuriously short timeouts when converted to a signed int. This problem has been observed in the wild. Thanks to thypon for a detailed strace that pointed me towards this issue. --- src/ndhc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ndhc.c b/src/ndhc.c index ce51c1d..f0623e2 100644 --- a/src/ndhc.c +++ b/src/ndhc.c @@ -394,19 +394,22 @@ static void do_ndhc_work(void) } int prev_timeout = timeout; + long long tt; arp_wake_ts = arp_get_wake_ts(); if (arp_wake_ts < 0 && cs.dhcp_wake_ts < 0) { timeout = -1; continue; } else if (arp_wake_ts < 0) { - timeout = cs.dhcp_wake_ts - nowts; + tt = cs.dhcp_wake_ts - nowts; } else if (cs.dhcp_wake_ts < 0) { - timeout = arp_wake_ts - nowts; + tt = arp_wake_ts - nowts; } else { - timeout = (arp_wake_ts < cs.dhcp_wake_ts ? - arp_wake_ts : cs.dhcp_wake_ts) - nowts; + tt = (arp_wake_ts < cs.dhcp_wake_ts ? + arp_wake_ts : cs.dhcp_wake_ts) - nowts; } + if (tt > INT_MAX) tt = INT_MAX; + timeout = tt; if (timeout < 0) timeout = 0;