summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-08-09 10:42:01 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-08-09 10:42:01 +0200
commit7e309e27ddbd0cbb9430d344d862020c2f87b81c (patch)
tree5d94fff5be9f04b044d4686e04b0eeda37da21e1
parentf9de264f88cac6c245beb7e0c653ea527fbaa550 (diff)
downloadserenity-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.cpp64
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