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.
This commit is contained in:
parent
ba875d4b2e
commit
abb1b54bfe
11
src/ndhc.c
11
src/ndhc.c
@ -394,19 +394,22 @@ static void do_ndhc_work(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int prev_timeout = timeout;
|
int prev_timeout = timeout;
|
||||||
|
long long tt;
|
||||||
|
|
||||||
arp_wake_ts = arp_get_wake_ts();
|
arp_wake_ts = arp_get_wake_ts();
|
||||||
if (arp_wake_ts < 0 && cs.dhcp_wake_ts < 0) {
|
if (arp_wake_ts < 0 && cs.dhcp_wake_ts < 0) {
|
||||||
timeout = -1;
|
timeout = -1;
|
||||||
continue;
|
continue;
|
||||||
} else if (arp_wake_ts < 0) {
|
} 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) {
|
} else if (cs.dhcp_wake_ts < 0) {
|
||||||
timeout = arp_wake_ts - nowts;
|
tt = arp_wake_ts - nowts;
|
||||||
} else {
|
} else {
|
||||||
timeout = (arp_wake_ts < cs.dhcp_wake_ts ?
|
tt = (arp_wake_ts < cs.dhcp_wake_ts ?
|
||||||
arp_wake_ts : cs.dhcp_wake_ts) - nowts;
|
arp_wake_ts : cs.dhcp_wake_ts) - nowts;
|
||||||
}
|
}
|
||||||
|
if (tt > INT_MAX) tt = INT_MAX;
|
||||||
|
timeout = tt;
|
||||||
if (timeout < 0)
|
if (timeout < 0)
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user