ping(8): improve diagnostics in case of wrong arguments.

For example, in case of super-user:
$ sudo ping -s -64 127.0.0.1
PING 127.0.0.1 (127.0.0.1): -64 data bytes
ping: sendto: Invalid argument

For unprivileged user:
$ ping -s -64 127.0.0.1
ping: packet size too large: 18446744073709551552 > 56: Operation not permitted

Fix this by switching from strtoul() to strtol() for integer arguments
and adding explicit checks for negative values.

MFC after:	1 month
This commit is contained in:
Eugene Grosbein 2018-11-08 09:45:13 +00:00
parent 0a9fcf3237
commit c0a3773ad2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=340245

View File

@ -242,7 +242,8 @@ main(int argc, char *const *argv)
#endif #endif
struct sockaddr_in *to; struct sockaddr_in *to;
double t; double t;
u_long alarmtimeout, ultmp; u_long alarmtimeout;
long ltmp;
int almost_done, ch, df, hold, i, icmp_len, mib[4], preload; int almost_done, ch, df, hold, i, icmp_len, mib[4], preload;
int ssend_errno, srecv_errno, tos, ttl; int ssend_errno, srecv_errno, tos, ttl;
char ctrl[CMSG_SPACE(sizeof(struct timeval))]; char ctrl[CMSG_SPACE(sizeof(struct timeval))];
@ -311,12 +312,12 @@ main(int argc, char *const *argv)
options |= F_AUDIBLE; options |= F_AUDIBLE;
break; break;
case 'c': case 'c':
ultmp = strtoul(optarg, &ep, 0); ltmp = strtol(optarg, &ep, 0);
if (*ep || ep == optarg || ultmp > LONG_MAX || !ultmp) if (*ep || ep == optarg || ltmp > LONG_MAX || ltmp <=0)
errx(EX_USAGE, errx(EX_USAGE,
"invalid count of packets to transmit: `%s'", "invalid count of packets to transmit: `%s'",
optarg); optarg);
npackets = ultmp; npackets = ltmp;
break; break;
case 'D': case 'D':
options |= F_HDRINCL; options |= F_HDRINCL;
@ -334,46 +335,46 @@ main(int argc, char *const *argv)
setbuf(stdout, (char *)NULL); setbuf(stdout, (char *)NULL);
break; break;
case 'G': /* Maximum packet size for ping sweep */ case 'G': /* Maximum packet size for ping sweep */
ultmp = strtoul(optarg, &ep, 0); ltmp = strtol(optarg, &ep, 0);
if (*ep || ep == optarg) if (*ep || ep == optarg || ltmp <= 0)
errx(EX_USAGE, "invalid packet size: `%s'", errx(EX_USAGE, "invalid packet size: `%s'",
optarg); optarg);
if (uid != 0 && ultmp > DEFDATALEN) { if (uid != 0 && ltmp > DEFDATALEN) {
errno = EPERM; errno = EPERM;
err(EX_NOPERM, err(EX_NOPERM,
"packet size too large: %lu > %u", "packet size too large: %ld > %u",
ultmp, DEFDATALEN); ltmp, DEFDATALEN);
} }
options |= F_SWEEP; options |= F_SWEEP;
sweepmax = ultmp; sweepmax = ltmp;
break; break;
case 'g': /* Minimum packet size for ping sweep */ case 'g': /* Minimum packet size for ping sweep */
ultmp = strtoul(optarg, &ep, 0); ltmp = strtol(optarg, &ep, 0);
if (*ep || ep == optarg) if (*ep || ep == optarg || ltmp <= 0)
errx(EX_USAGE, "invalid packet size: `%s'", errx(EX_USAGE, "invalid packet size: `%s'",
optarg); optarg);
if (uid != 0 && ultmp > DEFDATALEN) { if (uid != 0 && ltmp > DEFDATALEN) {
errno = EPERM; errno = EPERM;
err(EX_NOPERM, err(EX_NOPERM,
"packet size too large: %lu > %u", "packet size too large: %ld > %u",
ultmp, DEFDATALEN); ltmp, DEFDATALEN);
} }
options |= F_SWEEP; options |= F_SWEEP;
sweepmin = ultmp; sweepmin = ltmp;
break; break;
case 'h': /* Packet size increment for ping sweep */ case 'h': /* Packet size increment for ping sweep */
ultmp = strtoul(optarg, &ep, 0); ltmp = strtol(optarg, &ep, 0);
if (*ep || ep == optarg || ultmp < 1) if (*ep || ep == optarg || ltmp < 1)
errx(EX_USAGE, "invalid increment size: `%s'", errx(EX_USAGE, "invalid increment size: `%s'",
optarg); optarg);
if (uid != 0 && ultmp > DEFDATALEN) { if (uid != 0 && ltmp > DEFDATALEN) {
errno = EPERM; errno = EPERM;
err(EX_NOPERM, err(EX_NOPERM,
"packet size too large: %lu > %u", "packet size too large: %ld > %u",
ultmp, DEFDATALEN); ltmp, DEFDATALEN);
} }
options |= F_SWEEP; options |= F_SWEEP;
sweepincr = ultmp; sweepincr = ltmp;
break; break;
case 'I': /* multicast interface */ case 'I': /* multicast interface */
if (inet_aton(optarg, &ifaddr) == 0) if (inet_aton(optarg, &ifaddr) == 0)
@ -399,15 +400,15 @@ main(int argc, char *const *argv)
loop = 0; loop = 0;
break; break;
case 'l': case 'l':
ultmp = strtoul(optarg, &ep, 0); ltmp = strtol(optarg, &ep, 0);
if (*ep || ep == optarg || ultmp > INT_MAX) if (*ep || ep == optarg || ltmp > INT_MAX || ltmp < 0)
errx(EX_USAGE, errx(EX_USAGE,
"invalid preload value: `%s'", optarg); "invalid preload value: `%s'", optarg);
if (uid) { if (uid) {
errno = EPERM; errno = EPERM;
err(EX_NOPERM, "-l flag"); err(EX_NOPERM, "-l flag");
} }
preload = ultmp; preload = ltmp;
break; break;
case 'M': case 'M':
switch(optarg[0]) { switch(optarg[0]) {
@ -425,10 +426,10 @@ main(int argc, char *const *argv)
} }
break; break;
case 'm': /* TTL */ case 'm': /* TTL */
ultmp = strtoul(optarg, &ep, 0); ltmp = strtol(optarg, &ep, 0);
if (*ep || ep == optarg || ultmp > MAXTTL) if (*ep || ep == optarg || ltmp > MAXTTL || ltmp < 0)
errx(EX_USAGE, "invalid TTL: `%s'", optarg); errx(EX_USAGE, "invalid TTL: `%s'", optarg);
ttl = ultmp; ttl = ltmp;
options |= F_TTL; options |= F_TTL;
break; break;
case 'n': case 'n':
@ -470,24 +471,24 @@ main(int argc, char *const *argv)
source = optarg; source = optarg;
break; break;
case 's': /* size of packet to send */ case 's': /* size of packet to send */
ultmp = strtoul(optarg, &ep, 0); ltmp = strtol(optarg, &ep, 0);
if (*ep || ep == optarg) if (*ep || ep == optarg || ltmp < 0)
errx(EX_USAGE, "invalid packet size: `%s'", errx(EX_USAGE, "invalid packet size: `%s'",
optarg); optarg);
if (uid != 0 && ultmp > DEFDATALEN) { if (uid != 0 && ltmp > DEFDATALEN) {
errno = EPERM; errno = EPERM;
err(EX_NOPERM, err(EX_NOPERM,
"packet size too large: %lu > %u", "packet size too large: %ld > %u",
ultmp, DEFDATALEN); ltmp, DEFDATALEN);
} }
datalen = ultmp; datalen = ltmp;
break; break;
case 'T': /* multicast TTL */ case 'T': /* multicast TTL */
ultmp = strtoul(optarg, &ep, 0); ltmp = strtol(optarg, &ep, 0);
if (*ep || ep == optarg || ultmp > MAXTTL) if (*ep || ep == optarg || ltmp > MAXTTL || ltmp < 0)
errx(EX_USAGE, "invalid multicast TTL: `%s'", errx(EX_USAGE, "invalid multicast TTL: `%s'",
optarg); optarg);
mttl = ultmp; mttl = ltmp;
options |= F_MTTL; options |= F_MTTL;
break; break;
case 't': case 't':
@ -513,10 +514,10 @@ main(int argc, char *const *argv)
break; break;
case 'z': case 'z':
options |= F_HDRINCL; options |= F_HDRINCL;
ultmp = strtoul(optarg, &ep, 0); ltmp = strtol(optarg, &ep, 0);
if (*ep || ep == optarg || ultmp > MAXTOS) if (*ep || ep == optarg || ltmp > MAXTOS || ltmp < 0)
errx(EX_USAGE, "invalid TOS: `%s'", optarg); errx(EX_USAGE, "invalid TOS: `%s'", optarg);
tos = ultmp; tos = ltmp;
break; break;
default: default:
usage(); usage();