summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-02-12 22:56:54 +0100
committerAndreas Kling <kling@serenityos.org>2021-02-12 23:00:25 +0100
commitda981578e31327d8ee4f9a39014fdc90150b2575 (patch)
tree8b2e1229e84fefbd06f67ada24f821752748659e
parente47af3044aef94200e8de8b60f7b2342db6bd2da (diff)
downloadserenity-da981578e31327d8ee4f9a39014fdc90150b2575.zip
Kernel: Don't use a VLA for outgoing TCP packets
Since the payload size is user-controlled, this could be used to overflow the kernel stack. We should probably also be breaking things into smaller packets at a higher level, e.g TCPSocket::protocol_send(), but let's do that as a separate exercise. Fixes #5310.
-rw-r--r--Kernel/Net/TCPSocket.cpp9
1 files changed, 4 insertions, 5 deletions
diff --git a/Kernel/Net/TCPSocket.cpp b/Kernel/Net/TCPSocket.cpp
index e0dfa1da02..8d796828b7 100644
--- a/Kernel/Net/TCPSocket.cpp
+++ b/Kernel/Net/TCPSocket.cpp
@@ -187,9 +187,8 @@ KResultOr<size_t> TCPSocket::protocol_send(const UserOrKernelBuffer& data, size_
KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload, size_t payload_size)
{
const size_t buffer_size = sizeof(TCPPacket) + payload_size;
- alignas(TCPPacket) u8 buffer[buffer_size];
- new (buffer) TCPPacket;
- auto& tcp_packet = *(TCPPacket*)(buffer);
+ auto buffer = ByteBuffer::create_zeroed(buffer_size);
+ auto& tcp_packet = *(TCPPacket*)(buffer.data());
ASSERT(local_port());
tcp_packet.set_source_port(local_port());
tcp_packet.set_destination_port(peer_port());
@@ -214,7 +213,7 @@ KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload,
if (tcp_packet.has_syn() || payload_size > 0) {
LOCKER(m_not_acked_lock);
- m_not_acked.append({ m_sequence_number, ByteBuffer::copy(buffer, buffer_size) });
+ m_not_acked.append({ m_sequence_number, move(buffer) });
send_outgoing_packets();
return KSuccess;
}
@@ -222,7 +221,7 @@ KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload,
auto routing_decision = route_to(peer_address(), local_address(), bound_interface());
ASSERT(!routing_decision.is_zero());
- auto packet_buffer = UserOrKernelBuffer::for_kernel_buffer(buffer);
+ auto packet_buffer = UserOrKernelBuffer::for_kernel_buffer(buffer.data());
auto result = routing_decision.adapter->send_ipv4(
routing_decision.next_hop, peer_address(), IPv4Protocol::TCP,
packet_buffer, buffer_size, ttl());