diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-03-11 11:34:44 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-03-11 11:39:05 +0100 |
commit | 3d306bffc5981b083ebb365c51e93c2231ff9b22 (patch) | |
tree | c47a63aca8a473ae610ffb5aa2d8b8e9584e06fc | |
parent | 39dfb4de38fc5b31ca4472dbf45bcde3bb0d6e77 (diff) | |
download | busybox-3d306bffc5981b083ebb365c51e93c2231ff9b22.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 db3ab4f00..19f94a2d7 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"); } |