Ensure packet buffers are long enough for headers

This commit is contained in:
dmiller 2026-04-22 16:13:10 +00:00
parent b2a7459609
commit 21557e7b2f
4 changed files with 45 additions and 20 deletions

View file

@ -721,6 +721,8 @@ const u8 *ipv4_get_data(const struct ip *ip, const u8 *p, unsigned int *len)
const u8 *ipv4_get_data(const u8 *p, unsigned int *len)
{
struct ip ip;
if (*len < sizeof(ip))
return NULL;
memcpy(&ip, p, sizeof(ip));
return ipv4_get_data(&ip, p, len);
}
@ -736,6 +738,8 @@ const u8 *ipv6_get_data(const struct ip6_hdr *ip6, const u8 *p, unsigned int *le
const u8 *ipv6_get_data(const u8 *p, unsigned int *len, u8 *nxt)
{
struct ip6_hdr ip6;
if (*len < sizeof(ip6))
return NULL;
memcpy(&ip6, p, sizeof(ip6));
return ipv6_get_data(&ip6, p, len, nxt);
}
@ -751,6 +755,8 @@ const u8 *ipv6_get_data_any(const struct ip6_hdr *ip6, const u8 *p, unsigned int
const u8 *ipv6_get_data_any(const u8 *p, unsigned int *len, u8 *nxt)
{
struct ip6_hdr ip6;
if (*len < sizeof(ip6))
return NULL;
memcpy(&ip6, p, sizeof(ip6));
return ipv6_get_data_any(&ip6, p, len, nxt);
}
@ -759,6 +765,8 @@ const u8 *icmp_get_data(const u8 *icmp, unsigned int *len)
{
unsigned int header_len;
struct icmp_hdr hdr;
if (*len < sizeof(hdr))
return NULL;
memcpy(&hdr, icmp, sizeof(hdr));
if (hdr.icmp_type == ICMP_TIMEXCEED || hdr.icmp_type == ICMP_UNREACH)
@ -776,6 +784,8 @@ const u8 *icmpv6_get_data(const u8 *icmpv6, unsigned int *len)
{
unsigned int header_len;
struct icmpv6_hdr hdr;
if (*len < sizeof(hdr))
return NULL;
memcpy(&hdr, icmpv6, sizeof(hdr));
if (hdr.icmpv6_type == ICMPV6_TIMEXCEED || hdr.icmpv6_type == ICMPV6_UNREACH)

View file

@ -441,19 +441,12 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
if (sockaddr_storage_cmp(USI->SourceSockAddr(), &hdr.dst) != 0)
continue;
struct ip ip_tmp;
memcpy(&ip_tmp, pkt, sizeof(ip_tmp));
/* First check if it is ICMP, TCP, or UDP */
if (hdr.proto == IPPROTO_ICMP || hdr.proto == IPPROTO_ICMPV6) {
/* if it is our response */
if (bytes < 8U) {
if (!ip_tmp.ip_off)
error("Supposed ping packet is only %d bytes long!", bytes);
continue;
}
struct ppkt ping;
if (datalen < sizeof(ppkt))
continue;
memcpy(&ping, data, sizeof(ping));
current_reason = icmp_to_reason(hdr.proto, ping.type, ping.code);
@ -559,12 +552,16 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
if ((encaps_hdr.proto == IPPROTO_ICMP || encaps_hdr.proto == IPPROTO_ICMPV6)
&& USI->ptech.rawicmpscan) {
/* The response was based on a ping packet we sent */
if (encaps_len < ICMP_LEN_MIN)
continue;
struct icmp icmp;
memcpy(&icmp, encaps_data, sizeof(icmp));
memcpy(&icmp, encaps_data, MIN(encaps_len, sizeof(icmp)));
if (probe->icmpid() != ntohs(icmp.icmp_id))
continue;
} else if (encaps_hdr.proto == IPPROTO_TCP && USI->ptech.rawtcpscan) {
struct tcp_hdr tcp;
if (encaps_len < sizeof(tcp))
continue;
memcpy(&tcp, encaps_data, sizeof(tcp));
if (probe->dport() != ntohs(tcp.th_dport) ||
probe->sport() != ntohs(tcp.th_sport) ||
@ -572,12 +569,16 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
continue;
} else if (encaps_hdr.proto == IPPROTO_UDP && USI->ptech.rawudpscan) {
struct udp_hdr udp;
if (encaps_len < sizeof(udp))
continue;
memcpy(&udp, encaps_data, sizeof(udp));
if (probe->dport() != ntohs(udp.uh_dport) ||
probe->sport() != ntohs(udp.uh_sport))
continue;
} else if (encaps_hdr.proto == IPPROTO_SCTP && USI->ptech.rawsctpscan) {
struct sctp_hdr sctp;
if (encaps_len < sizeof(sctp))
continue;
memcpy(&sctp, encaps_data, sizeof(sctp));
if (probe->dport() != ntohs(sctp.sh_dport) ||
probe->sport() != ntohs(sctp.sh_sport) ||
@ -658,6 +659,8 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
}
} else if (hdr.proto == IPPROTO_TCP && USI->ptech.rawtcpscan) {
struct tcp_hdr tcp;
if (datalen < sizeof(tcp))
continue;
memcpy(&tcp, data, sizeof(tcp));
/* Check that the packet has useful flags. */
if (o.discovery_ignore_rst
@ -709,7 +712,8 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
}
} else if (hdr.proto == IPPROTO_UDP && USI->ptech.rawudpscan) {
struct udp_hdr udp;
memcpy(&udp, data, sizeof(udp));
if (datalen < sizeof(udp))
continue;
/* Search for this host on the incomplete list */
hss = USI->findHost(&hdr.src);
if (!hss)
@ -719,6 +723,7 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
listsz = hss->num_probes_outstanding();
goodone = false;
memcpy(&udp, data, sizeof(udp));
u16 sport = ntohs(udp.uh_sport);
u16 dport = ntohs(udp.uh_dport);
@ -745,6 +750,10 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
log_write(LOG_STDOUT, "In response to UDP-ping, we got UDP packet back from %s port %hu (trynum = %d)\n", inet_ntop_ez(&hdr.src, sizeof(hdr.src)), sport, probe->get_tryno());
}
} else if (hdr.proto == IPPROTO_SCTP && USI->ptech.rawsctpscan) {
struct sctp_hdr sctp;
struct dnet_sctp_chunkhdr chunk;
if (datalen < sizeof(sctp) + sizeof(chunk))
continue;
/* Search for this host on the incomplete list */
hss = USI->findHost(&hdr.src);
if (!hss)
@ -753,10 +762,8 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
listsz = hss->num_probes_outstanding();
goodone = false;
struct sctp_hdr sctp;
memcpy(&sctp, data, sizeof(sctp));
struct dnet_sctp_chunkhdr chunk;
memcpy(&chunk, (u8 *)data + 12, sizeof(chunk));
memcpy(&chunk, (u8 *)data + sizeof(sctp), sizeof(chunk));
u16 sport = ntohs(sctp.sh_sport);
u16 dport = ntohs(sctp.sh_dport);

View file

@ -1312,17 +1312,13 @@ static bool validateTCPhdr(const u8 *tcpc, unsigned len) {
*/
static bool validatepkt(const u8 *ipc, unsigned *len) {
struct ip ip;
if (*len < sizeof(ip))
return false;
memcpy(&ip, ipc, sizeof(ip));
const void *data;
unsigned int datalen, iplen;
u8 hdr;
if (*len < 1) {
if (o.debugging >= 3)
error("Rejecting tiny, supposed IP packet (size %u)", *len);
return false;
}
if (ip.ip_v == 4) {
unsigned fragoff, iplen;
@ -1352,6 +1348,8 @@ static bool validatepkt(const u8 *ipc, unsigned *len) {
hdr = ip.ip_p;
} else if (ip.ip_v == 6) {
struct ip6_hdr ip6;
if (*len < sizeof(ip6))
return false;
memcpy(&ip6, ipc, sizeof(ip6));
datalen = *len;

View file

@ -1132,6 +1132,8 @@ static bool decode_reply(const u8 *ip, unsigned int len, Reply *reply) {
if (hdr.version == 4 && hdr.proto == IPPROTO_ICMP) {
/* ICMP responses comprise all the TTL exceeded messages we expect from all
probe types, as well as actual replies from ICMP probes. */
if (len < ICMP_LEN_MIN)
return false;
ALIGN_HEADER(struct icmp_hdr, icmp, data, 0, len);
if ((icmp.icmp_type == ICMP_TIMEXCEED
&& icmp.icmp_code == ICMP_TIMEXCEED_INTRANS)
@ -1158,6 +1160,8 @@ static bool decode_reply(const u8 *ip, unsigned int len, Reply *reply) {
} else if (hdr.version == 6 && hdr.proto == IP_PROTO_ICMPV6) {
/* ICMPv6 responses comprise all the TTL exceeded messages we expect from
all probe types, as well as actual replies from ICMP probes. */
if (len < ICMP_LEN_MIN)
return false;
ALIGN_HEADER(struct icmpv6_hdr, icmpv6, data, 0, len);
/* TIMEXCEED, UNREACH */
if ((icmpv6.icmpv6_type == ICMPV6_TIMEXCEED
@ -1181,14 +1185,20 @@ static bool decode_reply(const u8 *ip, unsigned int len, Reply *reply) {
return false;
}
} else if (hdr.proto == IPPROTO_TCP) {
if (len < sizeof(struct tcp_hdr))
return false;
ALIGN_HEADER(struct tcp_hdr, tcp, data, 0, len);
reply->token = ntohs(tcp.th_dport) ^ global_id;
reply->target_addr = reply->from_addr;
} else if (hdr.proto == IPPROTO_UDP) {
if (len < sizeof(struct udp_hdr))
return false;
ALIGN_HEADER(struct udp_hdr, udp, data, 0, len);
reply->token = ntohs(udp.uh_dport) ^ global_id;
reply->target_addr = reply->from_addr;
} else if (hdr.proto == IPPROTO_SCTP) {
if (len < sizeof(struct sctp_hdr))
return false;
ALIGN_HEADER(struct sctp_hdr, sctp, data, 0, len);
reply->token = ntohs(sctp.sh_dport) ^ global_id;
reply->target_addr = reply->from_addr;