From d9d17737c3ea3cc6dd27e48b351e7b9036113b9c Mon Sep 17 00:00:00 2001 From: nmzik Date: Sun, 6 Sep 2026 05:07:44 +0400 Subject: [PATCH] net: return native SO_ERROR --- src/libs/network.cpp | 34 ++++++++++++++++++++++----------- tests/KernelFileSystemTests.cpp | 7 +++++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/libs/network.cpp b/src/libs/network.cpp index 0198e6f72..369ba2a6e 100644 --- a/src/libs/network.cpp +++ b/src/libs/network.cpp @@ -918,7 +918,10 @@ static int SetGuestSocketError(int error) { return -1; } -static int SetHostSocketError(int error) { +static int ConvertHostSocketError(int error) { + if (error == 0) { + return 0; + } int posix_error = Posix::POSIX_EIO; #if defined(_WIN32) switch (error) { @@ -971,14 +974,14 @@ static int SetHostSocketError(int error) { default: break; } #endif - return SetGuestSocketError(posix_error); + return posix_error; } static int SetHostSocketError() { #if defined(_WIN32) - return SetHostSocketError(WSAGetLastError()); + return SetGuestSocketError(ConvertHostSocketError(WSAGetLastError())); #else - return SetHostSocketError(errno); + return SetGuestSocketError(ConvertHostSocketError(errno)); #endif } @@ -1873,18 +1876,27 @@ int KYTY_SYSV_ABI Getsockopt(int s, int level, int optname, void* optval, uint32 return -1; } -#if defined(_WIN32) - int len = static_cast(*optlen); + // Guest socket options: SOL_SOCKET=0xffff, SO_ERROR=0x1007. + const bool socket_error = (level == 0xffff && optname == 0x1007); +#if !defined(_WIN32) + if (!socket_error) { + return SetGuestSocketError(Posix::POSIX_ENOPROTOOPT); + } +#endif + if (socket_error) { + optname = SO_ERROR; + } + SocketLength len = static_cast(*optlen); if (::getsockopt(socket, ConvertSocketOptionLevel(level), optname, static_cast(optval), - &len) == SOCKET_ERROR) { + &len) != 0) { return SetHostSocketError(); } + if (socket_error && len >= static_cast(sizeof(int))) { + auto* error = static_cast(optval); + *error = ConvertHostSocketError(*error); + } *optlen = static_cast(len); return 0; -#else - *Posix::GetErrorAddr() = Posix::POSIX_ENOSYS; - return -1; -#endif } int KYTY_SYSV_ABI Setsockopt(int s, int level, int optname, const void* optval, uint32_t optlen) { diff --git a/tests/KernelFileSystemTests.cpp b/tests/KernelFileSystemTests.cpp index da26ee421..e9ce956c2 100644 --- a/tests/KernelFileSystemTests.cpp +++ b/tests/KernelFileSystemTests.cpp @@ -99,6 +99,13 @@ void CheckSocketWakeup() { const int enabled = 1; Check(Net::Setsockopt(writer, 6, 1, &enabled, sizeof(enabled)) == 0, "enable TCP_NODELAY"); + int socket_error = -1; + uint32_t error_size = sizeof(socket_error); + *Libs::Posix::GetErrorAddr() = Libs::Posix::POSIX_EINVAL; + Check(Net::Getsockopt(writer, 0xffff, 0x1007, &socket_error, &error_size) == 0 && + socket_error == 0 && error_size == sizeof(socket_error) && + *Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EINVAL, + "SO_ERROR reports socket status without changing guest errno"); std::array readable {}; const auto bit = uint64_t {1} << (reader % 64);