diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-08-09 10:42:01 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-08-09 10:42:01 +0200 |
commit | 7e309e27ddbd0cbb9430d344d862020c2f87b81c (patch) | |
tree | 5d94fff5be9f04b044d4686e04b0eeda37da21e1 | |
parent | f9de264f88cac6c245beb7e0c653ea527fbaa550 (diff) | |
download | serenity-7e309e27ddbd0cbb9430d344d862020c2f87b81c.zip |
Kernel: Clean up and sanitize incoming packet handling a bit more
Once we've converted from an Ethernet frame to an IPv4 packet, we can
pass the IPv4Packet around instead of the EthernetFrameHeader.
Also add some more code to ignore invalid-looking packets.
-rw-r--r-- | Kernel/Net/NetworkTask.cpp | 64 |
1 files changed, 39 insertions, 25 deletions
diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index 4d0a92a87d..8a980a7916 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -20,11 +20,11 @@ //#define UDP_DEBUG //#define TCP_DEBUG -static void handle_arp(const EthernetFrameHeader&, int frame_size); -static void handle_ipv4(const EthernetFrameHeader&, int frame_size); -static void handle_icmp(const EthernetFrameHeader&, int frame_size); -static void handle_udp(const EthernetFrameHeader&, int frame_size); -static void handle_tcp(const EthernetFrameHeader&, int frame_size); +static void handle_arp(const EthernetFrameHeader&, size_t frame_size); +static void handle_ipv4(const EthernetFrameHeader&, size_t frame_size); +static void handle_icmp(const EthernetFrameHeader&, const IPv4Packet&); +static void handle_udp(const IPv4Packet&); +static void handle_tcp(const IPv4Packet&); Lockable<HashMap<IPv4Address, MACAddress>>& arp_table() { @@ -118,9 +118,9 @@ void NetworkTask_main() } } -void handle_arp(const EthernetFrameHeader& eth, int frame_size) +void handle_arp(const EthernetFrameHeader& eth, size_t frame_size) { - constexpr int minimum_arp_frame_size = sizeof(EthernetFrameHeader) + sizeof(ARPPacket); + constexpr size_t minimum_arp_frame_size = sizeof(EthernetFrameHeader) + sizeof(ARPPacket); if (frame_size < minimum_arp_frame_size) { kprintf("handle_arp: Frame too small (%d, need %d)\n", frame_size, minimum_arp_frame_size); return; @@ -180,9 +180,9 @@ void handle_arp(const EthernetFrameHeader& eth, int frame_size) } } -void handle_ipv4(const EthernetFrameHeader& eth, int frame_size) +void handle_ipv4(const EthernetFrameHeader& eth, size_t frame_size) { - constexpr int minimum_ipv4_frame_size = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet); + constexpr size_t minimum_ipv4_frame_size = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet); if (frame_size < minimum_ipv4_frame_size) { kprintf("handle_ipv4: Frame too small (%d, need %d)\n", frame_size, minimum_ipv4_frame_size); return; @@ -208,21 +208,19 @@ void handle_ipv4(const EthernetFrameHeader& eth, int frame_size) switch ((IPv4Protocol)packet.protocol()) { case IPv4Protocol::ICMP: - return handle_icmp(eth, frame_size); + return handle_icmp(eth, packet); case IPv4Protocol::UDP: - return handle_udp(eth, frame_size); + return handle_udp(packet); case IPv4Protocol::TCP: - return handle_tcp(eth, frame_size); + return handle_tcp(packet); default: kprintf("handle_ipv4: Unhandled protocol %u\n", packet.protocol()); break; } } -void handle_icmp(const EthernetFrameHeader& eth, int frame_size) +void handle_icmp(const EthernetFrameHeader& eth, const IPv4Packet& ipv4_packet) { - (void)frame_size; - auto& ipv4_packet = *static_cast<const IPv4Packet*>(eth.payload()); auto& icmp_header = *static_cast<const ICMPHeader*>(ipv4_packet.payload()); #ifdef ICMP_DEBUG kprintf("handle_icmp: source=%s, destination=%s, type=%b, code=%b\n", @@ -266,10 +264,12 @@ void handle_icmp(const EthernetFrameHeader& eth, int frame_size) } } -void handle_udp(const EthernetFrameHeader& eth, int frame_size) +void handle_udp(const IPv4Packet& ipv4_packet) { - (void)frame_size; - auto& ipv4_packet = *static_cast<const IPv4Packet*>(eth.payload()); + if (ipv4_packet.payload_size() < sizeof(UDPPacket)) { + kprintf("handle_udp: Packet too small (%u, need %zu)\n", ipv4_packet.payload_size()); + return; + } auto adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination()); if (!adapter) { @@ -298,18 +298,26 @@ void handle_udp(const EthernetFrameHeader& eth, int frame_size) socket->did_receive(ipv4_packet.source(), udp_packet.source_port(), KBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); } -void handle_tcp(const EthernetFrameHeader& eth, int frame_size) +void handle_tcp(const IPv4Packet& ipv4_packet) { - (void)frame_size; - auto& ipv4_packet = *static_cast<const IPv4Packet*>(eth.payload()); - - auto adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination()); - if (!adapter) { - kprintf("handle_tcp: this packet is not for me, it's for %s\n", ipv4_packet.destination().to_string().characters()); + if (ipv4_packet.payload_size() < sizeof(TCPPacket)) { + kprintf("handle_tcp: IPv4 payload is too small to be a TCP packet (%u, need %zu)\n", ipv4_packet.payload_size(), sizeof(TCPPacket)); return; } auto& tcp_packet = *static_cast<const TCPPacket*>(ipv4_packet.payload()); + + size_t minimum_tcp_header_size = 5 * sizeof(u32); + size_t maximum_tcp_header_size = 15 * sizeof(u32); + if (tcp_packet.header_size() < minimum_tcp_header_size || tcp_packet.header_size() > maximum_tcp_header_size) { + kprintf("handle_tcp: TCP packet header has invalid size %zu\n", tcp_packet.header_size()); + } + + if (ipv4_packet.payload_size() < tcp_packet.header_size()) { + kprintf("handle_tcp: IPv4 payload is smaller than TCP header claims (%u, supposedly %u)\n", ipv4_packet.payload_size(), tcp_packet.header_size()); + return; + } + size_t payload_size = ipv4_packet.payload_size() - tcp_packet.header_size(); #ifdef TCP_DEBUG @@ -329,6 +337,12 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size) payload_size); #endif + auto adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination()); + if (!adapter) { + kprintf("handle_tcp: this packet is not for me, it's for %s\n", ipv4_packet.destination().to_string().characters()); + return; + } + IPv4SocketTuple tuple(ipv4_packet.destination(), tcp_packet.destination_port(), ipv4_packet.source(), tcp_packet.source_port()); #ifdef TCP_DEBUG |