From c6a0694f50f239dd1f3f4ab6cc876a160a66f90f Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 23 Dec 2020 20:24:00 +0100 Subject: Kernel: Don't assert when reading from a listening-mode local socket Instead just fail with EINVAL as a listening socket is never suitable for reading from. Fixes #4511. --- Kernel/Net/LocalSocket.cpp | 33 +++++++++++++++++++-------------- Kernel/Net/LocalSocket.h | 4 ++-- 2 files changed, 21 insertions(+), 16 deletions(-) (limited to 'Kernel/Net') diff --git a/Kernel/Net/LocalSocket.cpp b/Kernel/Net/LocalSocket.cpp index 345cb7db05..b628d2dc6c 100644 --- a/Kernel/Net/LocalSocket.cpp +++ b/Kernel/Net/LocalSocket.cpp @@ -286,37 +286,42 @@ KResultOr LocalSocket::sendto(FileDescription& description, const UserOr { if (!has_attached_peer(description)) return KResult(-EPIPE); - ssize_t nwritten = send_buffer_for(description).write(data, data_size); + auto* socket_buffer = send_buffer_for(description); + if (!socket_buffer) + return KResult(-EINVAL); + ssize_t nwritten = socket_buffer->write(data, data_size); if (nwritten > 0) Thread::current()->did_unix_socket_write(nwritten); return nwritten; } -DoubleBuffer& LocalSocket::receive_buffer_for(FileDescription& description) +DoubleBuffer* LocalSocket::receive_buffer_for(FileDescription& description) { auto role = this->role(description); if (role == Role::Accepted) - return m_for_server; + return &m_for_server; if (role == Role::Connected) - return m_for_client; - ASSERT_NOT_REACHED(); + return &m_for_client; + return nullptr; } -DoubleBuffer& LocalSocket::send_buffer_for(FileDescription& description) +DoubleBuffer* LocalSocket::send_buffer_for(FileDescription& description) { auto role = this->role(description); if (role == Role::Connected) - return m_for_server; + return &m_for_server; if (role == Role::Accepted) - return m_for_client; - ASSERT_NOT_REACHED(); + return &m_for_client; + return nullptr; } KResultOr LocalSocket::recvfrom(FileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_size, int, Userspace, Userspace, timeval&) { - auto& buffer_for_me = receive_buffer_for(description); + auto* socket_buffer = receive_buffer_for(description); + if (!socket_buffer) + return KResult(-EINVAL); if (!description.is_blocking()) { - if (buffer_for_me.is_empty()) { + if (socket_buffer->is_empty()) { if (!has_attached_peer(description)) return 0; return KResult(-EAGAIN); @@ -326,10 +331,10 @@ KResultOr LocalSocket::recvfrom(FileDescription& description, UserOrKern if (Thread::current()->block(nullptr, description, unblock_flags).was_interrupted()) return KResult(-EINTR); } - if (!has_attached_peer(description) && buffer_for_me.is_empty()) + if (!has_attached_peer(description) && socket_buffer->is_empty()) return 0; - ASSERT(!buffer_for_me.is_empty()); - int nread = buffer_for_me.read(buffer, buffer_size); + ASSERT(!socket_buffer->is_empty()); + auto nread = socket_buffer->read(buffer, buffer_size); if (nread > 0) Thread::current()->did_unix_socket_read(nread); return nread; diff --git a/Kernel/Net/LocalSocket.h b/Kernel/Net/LocalSocket.h index 3b9395d1a1..f0025cdb14 100644 --- a/Kernel/Net/LocalSocket.h +++ b/Kernel/Net/LocalSocket.h @@ -72,8 +72,8 @@ private: virtual bool is_local() const override { return true; } bool has_attached_peer(const FileDescription&) const; static Lockable>& all_sockets(); - DoubleBuffer& receive_buffer_for(FileDescription&); - DoubleBuffer& send_buffer_for(FileDescription&); + DoubleBuffer* receive_buffer_for(FileDescription&); + DoubleBuffer* send_buffer_for(FileDescription&); NonnullRefPtrVector& sendfd_queue_for(const FileDescription&); NonnullRefPtrVector& recvfd_queue_for(const FileDescription&); -- cgit v1.2.3