From 3d306bffc5981b083ebb365c51e93c2231ff9b22 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Mar 2018 11:34:44 +0100 Subject: 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 --- networking/udhcp/dhcpd.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'networking/udhcp/dhcpd.c') 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"); } -- cgit v1.2.3