changeset 1874:559e02266deb draft

Avoid a potential malloc when handling signals.
author Roy Marples <roy@marples.name>
date Tue, 26 Mar 2013 08:51:34 +0000
parents daaec5a8be6b
children 7d432c417d3c
files dhcpcd.c eloop.c eloop.h
diffstat 3 files changed, 37 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/dhcpcd.c	Tue Mar 26 06:39:58 2013 +0000
+++ b/dhcpcd.c	Tue Mar 26 08:51:34 2013 +0000
@@ -666,6 +666,16 @@
 	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 @@
 		/* 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 @@
 		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");
--- a/eloop.c	Tue Mar 26 06:39:58 2013 +0000
+++ b/eloop.c	Tue Mar 26 08:51:34 2013 +0000
@@ -68,6 +68,9 @@
 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 @@
 	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 @@
 	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, >)) {
--- a/eloop.h	Tue Mar 26 06:39:58 2013 +0000
+++ b/eloop.h	Tue Mar 26 08:51:34 2013 +0000
@@ -49,6 +49,7 @@
 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);