From: David Schweikert Date: Sun, 17 Aug 2025 20:42:45 +0000 (+0200) Subject: Safe memory allocation for event storage. X-Git-Tag: v5.4~3 X-Git-Url: https://git.gsnw.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=59df0372fa0c1137a28bb80cb3e0425be2981143;p=fping.git Safe memory allocation for event storage. - Check calloc return value. - Make sure that the per-host interval can't be unreasonably low (making the event storage allocation very large). The issue was reported by David.A. --- diff --git a/ci/test-03-forbidden.pl b/ci/test-03-forbidden.pl index d2db133..97962c1 100755 --- a/ci/test-03-forbidden.pl +++ b/ci/test-03-forbidden.pl @@ -7,8 +7,7 @@ my $cmd1 = Test::Command->new(cmd => "fping -i 0 -T10 -g 127.0.0.1/29"); $cmd1->exit_is_num(1); $cmd1->stdout_is_eq(""); $cmd1->stderr_is_eq(<= 1 and -p >= 10 +fping: -i must be >= 1 END # fping -p 9 @@ -16,8 +15,7 @@ my $cmd2 = Test::Command->new(cmd => "fping -c3 -p 9 127.0.0.1"); $cmd2->exit_is_num(1); $cmd2->stdout_is_eq(""); $cmd2->stderr_is_eq(<= 1 and -p >= 10 +fping: -p must be >= 10 END # fping -H 300 diff --git a/src/fping.c b/src/fping.c index 5e059d0..6779175 100644 --- a/src/fping.c +++ b/src/fping.c @@ -147,13 +147,16 @@ extern int h_errno; /* ICMP Timestamp has a fixed payload size of 12 bytes */ #define ICMP_TIMESTAMP_DATA_SIZE 12 -/* maxima and minima */ #ifdef FPING_SAFE_LIMITS -#define MIN_INTERVAL 1 /* in millisec */ -#define MIN_PERHOST_INTERVAL 10 /* in millisec */ +#define MIN_INTERVAL_MS 1 /* in millisec */ +#define MIN_PERHOST_INTERVAL_MS 10 /* in millisec */ #else -#define MIN_INTERVAL 0 -#define MIN_PERHOST_INTERVAL 0 +#define MIN_INTERVAL_MS 0 +/* Set a very low limit for the per-host interval, even if safe limits are + * disabled, so that the memory allocation of the event storage is not + * unreasonably high. 0.001 ms would mean in theory at least 592 mbps of data + * sent to a single host, which probably doesn't make sense in any scenario. */ +#define MIN_PERHOST_INTERVAL_MS 0.001 #endif /* response time array flags */ @@ -962,15 +965,15 @@ int main(int argc, char **argv) exit(1); } -#ifdef FPING_SAFE_LIMITS - if ((interval < (int64_t)MIN_INTERVAL * 1000000 || perhost_interval < (int64_t)MIN_PERHOST_INTERVAL * 1000000) - && getuid()) { - fprintf(stderr, "%s: these options are too risky for mere mortals.\n", prog); - fprintf(stderr, "%s: You need -i >= %u and -p >= %u\n", - prog, MIN_INTERVAL, MIN_PERHOST_INTERVAL); + if (interval < (float)MIN_INTERVAL_MS * 1000000 && getuid()) { + fprintf(stderr, "%s: -i must be >= %g\n", prog, (float)MIN_INTERVAL_MS); + exit(1); + } + + if (perhost_interval < (float)MIN_PERHOST_INTERVAL_MS * 1000000 && getuid()) { + fprintf(stderr, "%s: -p must be >= %g\n", prog, (float)MIN_PERHOST_INTERVAL_MS); exit(1); } -#endif if (ping_data_size > MAX_PING_DATA) { fprintf(stderr, "%s: data size %u not valid, must not be larger than %u\n", @@ -2806,7 +2809,13 @@ void add_addr(char *name, char *host, struct sockaddr *ipaddr, socklen_t ipaddr_ /* allocate event storage */ p->event_storage_ping = (struct event *)calloc(event_storage_count, sizeof(struct event)); + if (!p->event_storage_ping) { + errno_crash_and_burn("can't allocate event_storage_ping"); + } p->event_storage_timeout = (struct event *)calloc(event_storage_count, sizeof(struct event)); + if (!p->event_storage_timeout) { + errno_crash_and_burn("can't allocate event_storage_timeout"); + } /* schedule first ping */ host_add_ping_event(p, 0, current_time_ns);