From: Roy Marples Date: Tue, 26 Mar 2013 08:51:34 +0000 (+0000) Subject: Avoid a potential malloc when handling signals. X-Git-Tag: v5.99.6~43 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=51a9a124191ca4c2f7db248942c6981465d9ada9;p=thirdparty%2Fdhcpcd.git Avoid a potential malloc when handling signals. --- diff --git a/dhcpcd.c b/dhcpcd.c index b4724c20..f7f782d3 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -666,6 +666,16 @@ sig_reboot(_unused void *arg) reconf_reboot(1, ifc, ifv, 0); } +static void +sig_reconf(_unused void *arg) +{ + struct interface *ifp; + + TAILQ_FOREACH(ifp, ifaces, next) { + ipv4_applyaddr(ifp); + } +} + void handle_signal(int sig) { @@ -685,7 +695,7 @@ handle_signal(int sig) /* We shouldn't modify any variables in the signal * handler, so simply add reboot function to the queue * for an immediate callout. */ - eloop_timeout_add_sec(0, sig_reboot, NULL); + eloop_timeout_add_now(sig_reboot, NULL); return; case SIGHUP: syslog(LOG_INFO, "received SIGHUP, releasing"); @@ -693,9 +703,7 @@ handle_signal(int sig) break; case SIGUSR1: syslog(LOG_INFO, "received SIGUSR, reconfiguring"); - TAILQ_FOREACH(ifp, ifaces, next) { - ipv4_applyaddr(ifp); - } + eloop_timeout_add_now(sig_reconf, NULL); return; case SIGPIPE: syslog(LOG_WARNING, "received SIGPIPE"); diff --git a/eloop.c b/eloop.c index 7b911d9d..0c220533 100644 --- a/eloop.c +++ b/eloop.c @@ -68,6 +68,9 @@ static TAILQ_HEAD (timeout_head, timeout) timeouts static struct timeout_head free_timeouts = TAILQ_HEAD_INITIALIZER(free_timeouts); +static void (*volatile timeout0)(void *); +static void *volatile timeout0_arg; + static struct pollfd *fds; static size_t fds_len; @@ -215,6 +218,20 @@ eloop_q_timeout_add_sec(int queue, time_t when, return eloop_q_timeout_add_tv(queue, &tv, callback, arg); } +int +eloop_timeout_add_now(void (*callback)(void *), void *arg) +{ + + if (timeout0 != NULL) { + syslog(LOG_WARNING, "%s: timeout0 already set", __func__); + return eloop_q_timeout_add_sec(0, 0, callback, arg); + } + + timeout0 = callback; + timeout0_arg = arg; + return 0; +} + /* This deletes all timeouts for the interface EXCEPT for ones with the * callbacks given. Handy for deleting everything apart from the expire * timeout. */ @@ -314,9 +331,16 @@ eloop_start(const sigset_t *sigmask) struct timeout *t; struct timeval tv; struct timespec ts, *tsp; + void (*t0)(void *); for (;;) { /* Run all timeouts first */ + if (timeout0) { + t0 = timeout0; + timeout0 = NULL; + t0(timeout0_arg); + continue; + } if ((t = TAILQ_FIRST(&timeouts))) { get_monotonic(&now); if (timercmp(&now, &t->when, >)) { diff --git a/eloop.h b/eloop.h index e0cb0e44..8a18d9c5 100644 --- a/eloop.h +++ b/eloop.h @@ -49,6 +49,7 @@ void eloop_event_delete(int fd); int eloop_q_timeout_add_sec(int queue, time_t, void (*)(void *), void *); int eloop_q_timeout_add_tv(int queue, const struct timeval *, void (*)(void *), void *); +int eloop_timeout_add_now(void (*)(void *), void *); void eloop_q_timeout_delete(int, void (*)(void *), void *); void eloop_q_timeouts_delete(int, void *, void (*)(void *), ...); void eloop_init(void);