diff options
author | Denys Vlasenko | 2018-03-11 11:34:44 +0100 |
---|---|---|
committer | Denys Vlasenko | 2018-03-11 23:04:05 +0100 |
commit | 62b7083c13a9afc16b872367db93f8a775164343 (patch) | |
tree | 424d38263edf14ca4f2b46057be7ff3761851919 | |
parent | 39bf15ba3e5d5a0f04eab05d4675241961bb333d (diff) | |
download | busybox-62b7083c13a9afc16b872367db93f8a775164343.zip busybox-62b7083c13a9afc16b872367db93f8a775164343.tar.gz |
udhcpd: clamp down huge auto_times to ~2M seconds, better EINTR poll handling
EINTR _should_ only happen on two signals we trap, and safe_poll
_should_ work here just fine, but there were kernel bugs where spurious EINTRs
happen (e.g. on ptrace attach). Be safe.
function old new delta
udhcpd_main 1437 1468 +31
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/udhcp/dhcpd.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index f1368cc..cfa9947 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -853,6 +853,9 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) /* Would rather not do read_config before daemonization - * otherwise NOMMU machines will parse config twice */ read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); + /* prevent poll timeout overflow */ + if (server_config.auto_time > INT_MAX / 1000) + server_config.auto_time = INT_MAX / 1000; /* Make sure fd 0,1,2 are open */ bb_sanitize_stdio(); @@ -914,14 +917,26 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) } udhcp_sp_fd_set(pfds, server_socket); - tv = timeout_end - monotonic_sec(); - /* Block here waiting for either signal or packet */ - retval = safe_poll(pfds, 2, server_config.auto_time ? tv * 1000 : -1); - if (retval <= 0) { - if (retval == 0) { + + new_tv: + tv = -1; + if (server_config.auto_time) { + tv = timeout_end - monotonic_sec(); + if (tv <= 0) { + write_leases: write_leases(); goto continue_with_autotime; } + tv *= 1000; + } + + /* Block here waiting for either signal or packet */ + retval = poll(pfds, 2, tv); + if (retval <= 0) { + if (retval == 0) + goto write_leases; + if (errno == EINTR) + goto new_tv; /* < 0 and not EINTR: should not happen */ bb_perror_msg_and_die("poll"); } |