mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
ping: Fix unsigned integer underflow resuling in a ping -R segfault
ping -R (F_RROUTE) will loop at ping.c:1381 until it segfaults or
the unsigned int hlen happens to be less than the size of an IP header:
slippy$ ping -R 192.168.0.101
PING 192.168.0.101 (192.168.0.101): 56 data bytes
64 bytes from 192.168.0.101: icmp_seq=0 ttl=63 time=1.081 ms
RR: 192.168.0.1
192.168.0.101
192.168.0.101
10.1.1.254
10.1.1.91
unknown option bb
unknown option 32
unknown option 6
...
unknown option 96
unknown option 2d
Segmentation fault
The reason for this is while looping through loose source routing (LSRR)
and strict source routing (SSRR), hlen will become smaller than the IP
header. It may even become negative. This should terminate the loop.
However, when hlen is unsigned, an integer underflow occurs becoming a
large number causing the loop to continue virtually forever until hlen
is either by chance smaller than the lenghth of an IP header or it
segfaults.
Reviewed by: asomers
Fixes: 46d7b45a26
MFC after: 3 days
Differential Revision: https://reviews.freebsd.org/D38744
This commit is contained in:
parent
ae4387d724
commit
70960bb86a
|
@ -1150,7 +1150,7 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
|
||||||
ssize_t icmp_data_raw_len;
|
ssize_t icmp_data_raw_len;
|
||||||
double triptime;
|
double triptime;
|
||||||
int dupflag, i, j, recv_len;
|
int dupflag, i, j, recv_len;
|
||||||
uint8_t hlen;
|
int8_t hlen;
|
||||||
uint16_t seq;
|
uint16_t seq;
|
||||||
static int old_rrlen;
|
static int old_rrlen;
|
||||||
static char old_rr[MAX_IPOPTLEN];
|
static char old_rr[MAX_IPOPTLEN];
|
||||||
|
@ -1171,7 +1171,7 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
|
||||||
hlen = (l & 0x0f) << 2;
|
hlen = (l & 0x0f) << 2;
|
||||||
|
|
||||||
/* Reject IP packets with a short header */
|
/* Reject IP packets with a short header */
|
||||||
if (hlen < sizeof(struct ip)) {
|
if (hlen < (int8_t) sizeof(struct ip)) {
|
||||||
if (options & F_VERBOSE)
|
if (options & F_VERBOSE)
|
||||||
warn("IHL too short (%d bytes) from %s", hlen,
|
warn("IHL too short (%d bytes) from %s", hlen,
|
||||||
inet_ntoa(from->sin_addr));
|
inet_ntoa(from->sin_addr));
|
||||||
|
|
Loading…
Reference in a new issue