Page MenuHomeFreeBSD

D37195.diff
No OneTemporary

D37195.diff

diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -963,6 +963,9 @@
warn("recvmsg");
continue;
}
+ /* If we have a 0 byte read from recvfrom continue */
+ if (cc == 0)
+ continue;
#ifdef SO_TIMESTAMP
if (cmsg != NULL &&
cmsg->cmsg_level == SOL_SOCKET &&
@@ -1144,8 +1147,10 @@
struct icmp icp;
struct ip ip;
const u_char *icmp_data_raw;
+ ssize_t icmp_data_raw_len;
double triptime;
- int dupflag, hlen, i, j, recv_len;
+ int dupflag, i, j, recv_len;
+ uint8_t hlen;
uint16_t seq;
static int old_rrlen;
static char old_rr[MAX_IPOPTLEN];
@@ -1155,15 +1160,27 @@
const u_char *oicmp_raw;
/*
- * Get size of IP header of the received packet. The
- * information is contained in the lower four bits of the
- * first byte.
+ * Get size of IP header of the received packet.
+ * The header length is contained in the lower four bits of the first
+ * byte and represents the number of 4 byte octets the header takes up.
+ *
+ * The IHL minimum value is 5 (20 bytes) and its maximum value is 15
+ * (60 bytes).
*/
memcpy(&l, buf, sizeof(l));
hlen = (l & 0x0f) << 2;
- memcpy(&ip, buf, hlen);
- /* Check the IP header */
+ /* Reject IP packets with a short header */
+ if (hlen < sizeof(struct ip)) {
+ if (options & F_VERBOSE)
+ warn("IHL too short (%d bytes) from %s", hlen,
+ inet_ntoa(from->sin_addr));
+ return;
+ }
+
+ memcpy(&ip, buf, sizeof(struct ip));
+
+ /* Check packet has enough data to carry a valid ICMP header */
recv_len = cc;
if (cc < hlen + ICMP_MINLEN) {
if (options & F_VERBOSE)
@@ -1175,6 +1192,7 @@
#ifndef icmp_data
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_ip);
#else
+ icmp_data_raw_len = cc - (hlen + offsetof(struct icmp, icmp_data));
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_data);
#endif
@@ -1304,12 +1322,45 @@
* as root to avoid leaking information not normally
* available to those not running as root.
*/
+
+ /*
+ * If we don't have enough bytes for a quoted IP header and an
+ * ICMP header then stop.
+ */
+ if (icmp_data_raw_len <
+ (ssize_t)(sizeof(struct ip) + sizeof(struct icmp))) {
+ if (options & F_VERBOSE)
+ warnx("quoted data too short (%zd bytes) from %s",
+ icmp_data_raw_len, inet_ntoa(from->sin_addr));
+ return;
+ }
+
memcpy(&oip_header_len, icmp_data_raw, sizeof(oip_header_len));
oip_header_len = (oip_header_len & 0x0f) << 2;
- memcpy(&oip, icmp_data_raw, oip_header_len);
+
+ /* Reject IP packets with a short header */
+ if (oip_header_len < sizeof(struct ip)) {
+ if (options & F_VERBOSE)
+ warnx("inner IHL too short (%d bytes) from %s",
+ oip_header_len, inet_ntoa(from->sin_addr));
+ return;
+ }
+
+ /*
+ * Check against the actual IHL length, to protect against
+ * quoated packets carrying IP options.
+ */
+ if (icmp_data_raw_len <
+ (ssize_t)(oip_header_len + sizeof(struct icmp))) {
+ if (options & F_VERBOSE)
+ warnx("inner packet too short (%zd bytes) from %s",
+ icmp_data_raw_len, inet_ntoa(from->sin_addr));
+ return;
+ }
+
+ memcpy(&oip, icmp_data_raw, sizeof(struct ip));
oicmp_raw = icmp_data_raw + oip_header_len;
- memcpy(&oicmp, oicmp_raw, offsetof(struct icmp, icmp_id) +
- sizeof(oicmp.icmp_id));
+ memcpy(&oicmp, oicmp_raw, sizeof(struct icmp));
if (((options & F_VERBOSE) && uid == 0) ||
(!(options & F_QUIET2) &&

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 16, 6:00 PM (21 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14662425
Default Alt Text
D37195.diff (3 KB)

Event Timeline