forked from Bananymous/banan-os
Kernel: Validate network packet sizes before casting
This caused a lot of crashes on invalid packets :D
This commit is contained in:
parent
b8622f2b4b
commit
bc0acc6f44
|
@ -2,6 +2,8 @@
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
|
#define DEBUG_ARP 0
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -167,13 +169,18 @@ namespace Kernel
|
||||||
|
|
||||||
void ARPTable::add_arp_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
|
void ARPTable::add_arp_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
|
||||||
{
|
{
|
||||||
|
if (buffer.size() < sizeof(ARPPacket))
|
||||||
|
{
|
||||||
|
dwarnln_if(DEBUG_ARP, "ARP packet too small");
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto& arp_packet = buffer.as<const ARPPacket>();
|
auto& arp_packet = buffer.as<const ARPPacket>();
|
||||||
|
|
||||||
SpinLockGuard _(m_pending_lock);
|
SpinLockGuard _(m_pending_lock);
|
||||||
|
|
||||||
if (m_pending_packets.full())
|
if (m_pending_packets.full())
|
||||||
{
|
{
|
||||||
dprintln("arp packet queue full");
|
dwarnln_if(DEBUG_ARP, "ARP packet queue full");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,6 +201,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ByteSpan packet)
|
BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ByteSpan packet)
|
||||||
{
|
{
|
||||||
|
ASSERT(packet.size() >= sizeof(IPv4Header));
|
||||||
auto& ipv4_header = packet.as<const IPv4Header>();
|
auto& ipv4_header = packet.as<const IPv4Header>();
|
||||||
auto ipv4_data = packet.slice(sizeof(IPv4Header));
|
auto ipv4_data = packet.slice(sizeof(IPv4Header));
|
||||||
|
|
||||||
|
@ -213,6 +214,11 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
case NetworkProtocol::ICMP:
|
case NetworkProtocol::ICMP:
|
||||||
{
|
{
|
||||||
|
if (ipv4_data.size() < sizeof(ICMPHeader))
|
||||||
|
{
|
||||||
|
dwarnln("IPv4 packet too small for ICMP");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
auto& icmp_header = ipv4_data.as<const ICMPHeader>();
|
auto& icmp_header = ipv4_data.as<const ICMPHeader>();
|
||||||
switch (icmp_header.type)
|
switch (icmp_header.type)
|
||||||
{
|
{
|
||||||
|
@ -245,6 +251,11 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
case NetworkProtocol::UDP:
|
case NetworkProtocol::UDP:
|
||||||
{
|
{
|
||||||
|
if (ipv4_data.size() < sizeof(UDPHeader))
|
||||||
|
{
|
||||||
|
dwarnln("IPv4 packet too small for UDP");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
auto& udp_header = ipv4_data.as<const UDPHeader>();
|
auto& udp_header = ipv4_data.as<const UDPHeader>();
|
||||||
dst_port = udp_header.dst_port;
|
dst_port = udp_header.dst_port;
|
||||||
src_port = udp_header.src_port;
|
src_port = udp_header.src_port;
|
||||||
|
@ -252,6 +263,11 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
case NetworkProtocol::TCP:
|
case NetworkProtocol::TCP:
|
||||||
{
|
{
|
||||||
|
if (ipv4_data.size() < sizeof(TCPHeader))
|
||||||
|
{
|
||||||
|
dwarnln("IPv4 packet too small for TCP");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
auto& tcp_header = ipv4_data.as<const TCPHeader>();
|
auto& tcp_header = ipv4_data.as<const TCPHeader>();
|
||||||
dst_port = tcp_header.dst_port;
|
dst_port = tcp_header.dst_port;
|
||||||
src_port = tcp_header.src_port;
|
src_port = tcp_header.src_port;
|
||||||
|
@ -322,7 +338,7 @@ namespace Kernel
|
||||||
const size_t ipv4_packet_size = reinterpret_cast<const IPv4Header*>(buffer_start)->total_length;
|
const size_t ipv4_packet_size = reinterpret_cast<const IPv4Header*>(buffer_start)->total_length;
|
||||||
|
|
||||||
if (auto ret = handle_ipv4_packet(pending.interface, BAN::ByteSpan(buffer_start, ipv4_packet_size)); ret.is_error())
|
if (auto ret = handle_ipv4_packet(pending.interface, BAN::ByteSpan(buffer_start, ipv4_packet_size)); ret.is_error())
|
||||||
dwarnln("{}", ret.error());
|
dwarnln_if(DEBUG_IPV4, "{}", ret.error());
|
||||||
|
|
||||||
SpinLockGuard _(m_pending_lock);
|
SpinLockGuard _(m_pending_lock);
|
||||||
m_pending_total_size -= ipv4_packet_size;
|
m_pending_total_size -= ipv4_packet_size;
|
||||||
|
@ -333,32 +349,38 @@ namespace Kernel
|
||||||
|
|
||||||
void IPv4Layer::add_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
|
void IPv4Layer::add_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
|
||||||
{
|
{
|
||||||
|
if (buffer.size() < sizeof(IPv4Header))
|
||||||
|
{
|
||||||
|
dwarnln_if(DEBUG_IPV4, "IPv4 packet too small");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SpinLockGuard _(m_pending_lock);
|
SpinLockGuard _(m_pending_lock);
|
||||||
|
|
||||||
if (m_pending_packets.full())
|
if (m_pending_packets.full())
|
||||||
{
|
{
|
||||||
dwarnln("IPv4 packet queue full");
|
dwarnln_if(DEBUG_IPV4, "IPv4 packet queue full");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pending_total_size + buffer.size() > m_pending_packet_buffer->size())
|
if (m_pending_total_size + buffer.size() > m_pending_packet_buffer->size())
|
||||||
{
|
{
|
||||||
dwarnln("IPv4 packet queue full");
|
dwarnln_if(DEBUG_IPV4, "IPv4 packet queue full");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& ipv4_header = buffer.as<const IPv4Header>();
|
auto& ipv4_header = buffer.as<const IPv4Header>();
|
||||||
if (calculate_internet_checksum(BAN::ConstByteSpan::from(ipv4_header), {}) != 0)
|
if (calculate_internet_checksum(BAN::ConstByteSpan::from(ipv4_header), {}) != 0)
|
||||||
{
|
{
|
||||||
dwarnln("Invalid IPv4 packet");
|
dwarnln_if(DEBUG_IPV4, "Invalid IPv4 packet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ipv4_header.total_length > buffer.size() || ipv4_header.total_length > interface.payload_mtu())
|
if (ipv4_header.total_length > buffer.size() || ipv4_header.total_length > interface.payload_mtu())
|
||||||
{
|
{
|
||||||
if (ipv4_header.flags_frament & IPv4Flags::DF)
|
if (ipv4_header.flags_frament & IPv4Flags::DF)
|
||||||
dwarnln("Invalid IPv4 packet");
|
dwarnln_if(DEBUG_IPV4, "Invalid IPv4 packet");
|
||||||
else
|
else
|
||||||
dwarnln("IPv4 fragmentation not supported");
|
dwarnln_if(DEBUG_IPV4, "IPv4 fragmentation not supported");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue