diff options
author | Andreas Kling <kling@serenityos.org> | 2022-08-21 16:45:42 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-08-21 16:45:42 +0200 |
commit | 42435ce5e475c355330f3cb16d2334a339588cb9 (patch) | |
tree | 2aaadda6ea84fda3e4b5d76a5dd24bf3e1369d12 /Kernel/Net | |
parent | 8997c6a4d1f1047e53d640982568e1e45ed8f171 (diff) | |
download | serenity-42435ce5e475c355330f3cb16d2334a339588cb9.zip |
Kernel: Make sys$recvfrom() with MSG_DONTWAIT not so racy
Instead of temporary changing the open file description's "blocking"
flag while doing a non-waiting recvfrom, we instead plumb the currently
wanted blocking behavior all the way through to the underlying socket.
Diffstat (limited to 'Kernel/Net')
-rw-r--r-- | Kernel/Net/IPv4Socket.cpp | 14 | ||||
-rw-r--r-- | Kernel/Net/IPv4Socket.h | 6 | ||||
-rw-r--r-- | Kernel/Net/LocalSocket.cpp | 4 | ||||
-rw-r--r-- | Kernel/Net/LocalSocket.h | 2 | ||||
-rw-r--r-- | Kernel/Net/Socket.cpp | 2 | ||||
-rw-r--r-- | Kernel/Net/Socket.h | 2 |
6 files changed, 15 insertions, 15 deletions
diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp index 1a1aa8750d..00acbd8eb2 100644 --- a/Kernel/Net/IPv4Socket.cpp +++ b/Kernel/Net/IPv4Socket.cpp @@ -246,7 +246,7 @@ ErrorOr<size_t> IPv4Socket::sendto(OpenFileDescription&, UserOrKernelBuffer cons return nsent_or_error; } -ErrorOr<size_t> IPv4Socket::receive_byte_buffered(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>) +ErrorOr<size_t> IPv4Socket::receive_byte_buffered(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, bool blocking) { MutexLocker locker(mutex()); @@ -255,7 +255,7 @@ ErrorOr<size_t> IPv4Socket::receive_byte_buffered(OpenFileDescription& descripti if (m_receive_buffer->is_empty()) { if (protocol_is_disconnected()) return 0; - if (!description.is_blocking()) + if (!blocking) return set_so_error(EAGAIN); locker.unlock(); @@ -285,7 +285,7 @@ ErrorOr<size_t> IPv4Socket::receive_byte_buffered(OpenFileDescription& descripti return nreceived_or_error; } -ErrorOr<size_t> IPv4Socket::receive_packet_buffered(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> addr, Userspace<socklen_t*> addr_length, Time& packet_timestamp) +ErrorOr<size_t> IPv4Socket::receive_packet_buffered(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> addr, Userspace<socklen_t*> addr_length, Time& packet_timestamp, bool blocking) { MutexLocker locker(mutex()); ReceivedPacket taken_packet; @@ -296,7 +296,7 @@ ErrorOr<size_t> IPv4Socket::receive_packet_buffered(OpenFileDescription& descrip // But if so, we still need to deliver at least one EOF read to userspace.. right? if (protocol_is_disconnected()) return 0; - if (!description.is_blocking()) + if (!blocking) return set_so_error(EAGAIN); } @@ -380,7 +380,7 @@ ErrorOr<size_t> IPv4Socket::receive_packet_buffered(OpenFileDescription& descrip return protocol_receive(packet->data->bytes(), buffer, buffer_length, flags); } -ErrorOr<size_t> IPv4Socket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> user_addr, Userspace<socklen_t*> user_addr_length, Time& packet_timestamp) +ErrorOr<size_t> IPv4Socket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*> user_addr, Userspace<socklen_t*> user_addr_length, Time& packet_timestamp, bool blocking) { if (user_addr_length) { socklen_t addr_length; @@ -398,9 +398,9 @@ ErrorOr<size_t> IPv4Socket::recvfrom(OpenFileDescription& description, UserOrKer ErrorOr<size_t> nreceived = 0; if (buffer_mode() == BufferMode::Bytes) - nreceived = receive_byte_buffered(description, offset_buffer, offset_buffer_length, flags, user_addr, user_addr_length); + nreceived = receive_byte_buffered(description, offset_buffer, offset_buffer_length, flags, user_addr, user_addr_length, blocking); else - nreceived = receive_packet_buffered(description, offset_buffer, offset_buffer_length, flags, user_addr, user_addr_length, packet_timestamp); + nreceived = receive_packet_buffered(description, offset_buffer, offset_buffer_length, flags, user_addr, user_addr_length, packet_timestamp, blocking); if (nreceived.is_error()) total_nreceived = nreceived; diff --git a/Kernel/Net/IPv4Socket.h b/Kernel/Net/IPv4Socket.h index fa3a7c9e59..fb4784d3a4 100644 --- a/Kernel/Net/IPv4Socket.h +++ b/Kernel/Net/IPv4Socket.h @@ -40,7 +40,7 @@ public: virtual bool can_read(OpenFileDescription const&, u64) const override; virtual bool can_write(OpenFileDescription const&, u64) const override; virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int, Userspace<sockaddr const*>, socklen_t) override; - virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&) override; + virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&, bool blocking) override; virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t) override; virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override; @@ -98,8 +98,8 @@ protected: private: virtual bool is_ipv4() const override { return true; } - ErrorOr<size_t> receive_byte_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>); - ErrorOr<size_t> receive_packet_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&); + ErrorOr<size_t> receive_byte_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, bool blocking); + ErrorOr<size_t> receive_packet_buffered(OpenFileDescription&, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&, bool blocking); void set_can_read(bool); diff --git a/Kernel/Net/LocalSocket.cpp b/Kernel/Net/LocalSocket.cpp index d5820aad41..0ad680b654 100644 --- a/Kernel/Net/LocalSocket.cpp +++ b/Kernel/Net/LocalSocket.cpp @@ -334,12 +334,12 @@ DoubleBuffer* LocalSocket::send_buffer_for(OpenFileDescription& description) return nullptr; } -ErrorOr<size_t> LocalSocket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_size, int, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&) +ErrorOr<size_t> LocalSocket::recvfrom(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_size, int, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&, bool blocking) { auto* socket_buffer = receive_buffer_for(description); if (!socket_buffer) return set_so_error(EINVAL); - if (!description.is_blocking()) { + if (!blocking) { if (socket_buffer->is_empty()) { if (!has_attached_peer(description)) return 0; diff --git a/Kernel/Net/LocalSocket.h b/Kernel/Net/LocalSocket.h index 8174b235fd..91722d72cd 100644 --- a/Kernel/Net/LocalSocket.h +++ b/Kernel/Net/LocalSocket.h @@ -46,7 +46,7 @@ public: virtual bool can_read(OpenFileDescription const&, u64) const override; virtual bool can_write(OpenFileDescription const&, u64) const override; virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int, Userspace<sockaddr const*>, socklen_t) override; - virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&) override; + virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&, bool blocking) override; virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override; virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override; virtual ErrorOr<void> chown(Credentials const&, OpenFileDescription&, UserID, GroupID) override; diff --git a/Kernel/Net/Socket.cpp b/Kernel/Net/Socket.cpp index b38be8a6e0..2832603db3 100644 --- a/Kernel/Net/Socket.cpp +++ b/Kernel/Net/Socket.cpp @@ -242,7 +242,7 @@ ErrorOr<size_t> Socket::read(OpenFileDescription& description, u64, UserOrKernel if (is_shut_down_for_reading()) return 0; Time t {}; - return recvfrom(description, buffer, size, 0, {}, 0, t); + return recvfrom(description, buffer, size, 0, {}, 0, t, description.is_blocking()); } ErrorOr<size_t> Socket::write(OpenFileDescription& description, u64, UserOrKernelBuffer const& data, size_t size) diff --git a/Kernel/Net/Socket.h b/Kernel/Net/Socket.h index 4e0de6ec11..63f92aa270 100644 --- a/Kernel/Net/Socket.h +++ b/Kernel/Net/Socket.h @@ -80,7 +80,7 @@ public: virtual bool is_local() const { return false; } virtual bool is_ipv4() const { return false; } virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int flags, Userspace<sockaddr const*>, socklen_t) = 0; - virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&) = 0; + virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&, bool blocking) = 0; virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t); virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>); |