[PATCH 4/6] alfred: reject invalid synchronization periods
Sven Eckelmann <[email protected]> Thu, 30 Jul 2026 21:31:58 +0200
| Newsgroups | org.open-mesh.lists.batman |
|---|---|
| Message-ID | <[email protected]> |
The -p option argument was parsed with strtod() without any validation. An unparsable argument yields 0.0 and a zero it_value disarms a timerfd instead of arming it. 'alfred -p 0' or a mistyped period therefore started a daemon whose periodic timer never fired - no primary announcements, no data synchronization and no purging of stale data - while everything looked fine at startup. Reject non-finite, zero and negative synchronization periods. And also reject parse errors. Signed-off-by: Sven Eckelmann <[email protected]> --- Makefile | 2 +- main.c | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d71f41f..66b3a10 100755 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ MANPAGE = man/alfred.8 # alfred flags and options CFLAGS += -pedantic -Wall -W -std=gnu99 -fno-strict-aliasing -MD -MP CPPFLAGS += -D_GNU_SOURCE -LDLIBS += -lrt +LDLIBS += -lrt -lm # Turn on alfred capability dropping by default - set this to n if you don't want/need it export CONFIG_ALFRED_CAPABILITIES=y diff --git a/main.c b/main.c index baedbd2..6372ec8 100644 --- a/main.c +++ b/main.c @@ -7,7 +7,10 @@ */ #include <arpa/inet.h> +#include <errno.h> #include <getopt.h> +#include <limits.h> +#include <math.h> #include <signal.h> #include <stdbool.h> #include <stdio.h> @@ -172,6 +175,7 @@ static struct globals *alfred_init(int argc, char *argv[]) }; double sync_period = 0.0; struct globals *globals; + char *endptr; int opt_ind; int opt; int ret; @@ -298,9 +302,28 @@ static struct globals *alfred_init(int argc, char *argv[]) printf("A.L.F.R.E.D. - Almighty Lightweight Remote Fact Exchange Daemon\n"); return NULL; case 'p': - sync_period = strtod(optarg, NULL); + errno = 0; + sync_period = strtod(optarg, &endptr); + if (errno || *endptr != '\0' || endptr == optarg || + !isfinite(sync_period) || sync_period <= 0 || + sync_period > (double)INT_MAX) { + fprintf(stderr, "bad sync period argument\n"); + return NULL; + } + globals->sync_period.tv_sec = (int)sync_period; globals->sync_period.tv_nsec = (double)(sync_period - (int)sync_period) * 1e9; + + /* a period which rounds down to an all zero timespec + * would disarm the timer in timerfd_settime() instead + * of triggering it + */ + if (globals->sync_period.tv_sec == 0 && + globals->sync_period.tv_nsec == 0) { + fprintf(stderr, "sync period argument too small\n"); + return NULL; + } + printf(" ** Setting sync interval to: %.9f seconds (%lld.%09u)\n", sync_period, (long long)globals->sync_period.tv_sec, (unsigned int)globals->sync_period.tv_nsec); -- 2.47.3