Module Name: src Committed By: dholland Date: Sun Dec 18 00:21:33 UTC 2016
Modified Files: src/sbin/ping: ping.c Log Message: PR bin/36997 Zafer Aydogan: ping doesn't validate numeric inputs enough. Check for values between INT_MAX and LONG_MAX (if they're different) when using strtol to get an int. This applies to the -c and -l options; the other uses were already checked. Also limit the inter-packet interval given with -i to values that don't cause integer overflow calling poll() with milliseconds. Really large intervals (the number is read as floating point) can produce positive poll() values but negative integers when converted to struct timespec; this produces behavior akin to using -l at first and could be construed as a local DoS vulnerability. To generate a diff of this commit: cvs rdiff -u -r1.112 -r1.113 src/sbin/ping/ping.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sbin/ping/ping.c diff -u src/sbin/ping/ping.c:1.112 src/sbin/ping/ping.c:1.113 --- src/sbin/ping/ping.c:1.112 Fri Oct 7 22:31:05 2016 +++ src/sbin/ping/ping.c Sun Dec 18 00:21:33 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ping.c,v 1.112 2016/10/07 22:31:05 joerg Exp $ */ +/* $NetBSD: ping.c,v 1.113 2016/12/18 00:21:33 dholland Exp $ */ /* * Copyright (c) 1989, 1993 @@ -58,7 +58,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: ping.c,v 1.112 2016/10/07 22:31:05 joerg Exp $"); +__RCSID("$NetBSD: ping.c,v 1.113 2016/12/18 00:21:33 dholland Exp $"); #endif #include <stdio.h> @@ -295,11 +295,17 @@ main(int argc, char *argv[]) compat = 1; break; case 'c': - npackets = strtol(optarg, &p, 0); - if (*p != '\0' || npackets <= 0) + l = strtol(optarg, &p, 0); + if (*p != '\0' || l <= 0) errx(EXIT_FAILURE, "Bad/invalid number of packets: %s", optarg); +#if INT_MAX < LONG_MAX + if (l > INT_MAX) + errx(EXIT_FAILURE, + "Too many packets to count: %ld", l); +#endif + npackets = l; break; case 'D': pingflags |= F_DF; @@ -318,12 +324,27 @@ main(int argc, char *argv[]) if (*p != '\0' || interval <= 0) errx(EXIT_FAILURE, "Bad/invalid interval: %s", optarg); + /* + * In order to avoid overflowing the microseconds + * argument of poll() the interval must be less than + * INT_MAX/1000. Limit it to one second less than + * that to be safe. + */ + if (interval >= INT_MAX/1000.0 - 1.0) + errx(EXIT_FAILURE, + "Timing interval %g too large", interval); break; case 'l': - preload = strtol(optarg, &p, 0); - if (*p != '\0' || preload < 0) + l = strtol(optarg, &p, 0); + if (*p != '\0' || l < 0) errx(EXIT_FAILURE, "Bad/invalid preload value: " "%s", optarg); +#if INT_MAX < LONG_MAX + if (l > INT_MAX) + errx(EXIT_FAILURE, + "Too many preload packets: %ld", l); +#endif + preload = l; break; case 'n': pingflags |= F_NUMERIC;