From 24f956c7392c4d45f9cad95d3ef69014307a3408 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Mon, 12 Dec 2022 17:52:00 +0100 Subject: [PATCH] Kernel: Convert TCP pseudo-headers through a union This keeps us from tripping strict aliasing, which previously made TCP connections inoperable when building without `-fsanitize=undefined` or `-fno-strict-aliasing`. --- Kernel/Net/TCPSocket.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Kernel/Net/TCPSocket.cpp b/Kernel/Net/TCPSocket.cpp index 2cd19f5137..d94a8976ae 100644 --- a/Kernel/Net/TCPSocket.cpp +++ b/Kernel/Net/TCPSocket.cpp @@ -360,31 +360,35 @@ bool TCPSocket::should_delay_next_ack() const NetworkOrdered TCPSocket::compute_tcp_checksum(IPv4Address const& source, IPv4Address const& destination, TCPPacket const& packet, u16 payload_size) { - struct [[gnu::packed]] PseudoHeader { - IPv4Address source; - IPv4Address destination; - u8 zero; - u8 protocol; - NetworkOrdered payload_size; + union PseudoHeader { + struct [[gnu::packed]] { + IPv4Address source; + IPv4Address destination; + u8 zero; + u8 protocol; + NetworkOrdered payload_size; + } header; + u16 raw[6]; }; + static_assert(sizeof(PseudoHeader) == 12); - PseudoHeader pseudo_header { source, destination, 0, (u8)IPv4Protocol::TCP, packet.header_size() + payload_size }; + PseudoHeader pseudo_header { .header = { source, destination, 0, (u8)IPv4Protocol::TCP, packet.header_size() + payload_size } }; u32 checksum = 0; - auto raw_pseudo_header = bit_cast(&pseudo_header); + auto* raw_pseudo_header = pseudo_header.raw; for (size_t i = 0; i < sizeof(pseudo_header) / sizeof(u16); ++i) { checksum += AK::convert_between_host_and_network_endian(raw_pseudo_header[i]); if (checksum > 0xffff) checksum = (checksum >> 16) + (checksum & 0xffff); } - auto raw_packet = bit_cast(&packet); + auto* raw_packet = bit_cast(&packet); for (size_t i = 0; i < packet.header_size() / sizeof(u16); ++i) { checksum += AK::convert_between_host_and_network_endian(raw_packet[i]); if (checksum > 0xffff) checksum = (checksum >> 16) + (checksum & 0xffff); } VERIFY(packet.data_offset() * 4 == packet.header_size()); - auto raw_payload = bit_cast(packet.payload()); + auto* raw_payload = bit_cast(packet.payload()); for (size_t i = 0; i < payload_size / sizeof(u16); ++i) { checksum += AK::convert_between_host_and_network_endian(raw_payload[i]); if (checksum > 0xffff)