From 67b7bbe1f63e0b12d32839b5939f29dfb88fbd4d Mon Sep 17 00:00:00 2001 From: dayarthvader Date: Fri, 21 Jan 2022 21:30:06 +0200 Subject: [PATCH] ping: Handle optional field in the IPv4 header --- Userland/Utilities/ping.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Userland/Utilities/ping.cpp b/Userland/Utilities/ping.cpp index 43848be6de..a510950cac 100644 --- a/Userland/Utilities/ping.cpp +++ b/Userland/Utilities/ping.cpp @@ -30,6 +30,10 @@ static int min_ms; static int max_ms; static const char* host; static int payload_size = -1; +// variable part of header can be 0 to 40 bytes +// https://datatracker.ietf.org/doc/html/rfc791#section-3.1 +static constexpr int max_optional_header_size_in_bytes = 40; +static constexpr int min_header_size_in_bytes = 5; static void closing_statistics() { @@ -161,14 +165,13 @@ int main(int argc, char** argv) total_pings++; for (;;) { - // FIXME: IPv4 headers are not actually fixed-size, handle other sizes. - auto pong_packet_result = ByteBuffer::create_uninitialized(sizeof(struct ip) + sizeof(struct icmphdr) + payload_size); + auto pong_packet_result = ByteBuffer::create_uninitialized( + sizeof(struct ip) + max_optional_header_size_in_bytes + sizeof(struct icmphdr) + payload_size); if (!pong_packet_result.has_value()) { warnln("failed to allocate a large enough buffer for the pong packet"); return 1; } auto& pong_packet = pong_packet_result.value(); - struct icmphdr* pong_hdr = reinterpret_cast(pong_packet.data() + sizeof(struct ip)); socklen_t peer_address_size = sizeof(peer_address); rc = recvfrom(fd, pong_packet.data(), pong_packet.size(), 0, (struct sockaddr*)&peer_address, &peer_address_size); if (rc < 0) { @@ -180,6 +183,13 @@ int main(int argc, char** argv) return 1; } + i8 internet_header_length = *pong_packet.data() & 0x0F; + if (internet_header_length < min_header_size_in_bytes) { + outln("ping: illegal ihl field value {:x}", internet_header_length); + continue; + } + + struct icmphdr* pong_hdr = reinterpret_cast(pong_packet.data() + (internet_header_length * 4)); if (pong_hdr->type != ICMP_ECHOREPLY) continue; if (pong_hdr->code != 0)