From d6a3d9dd53cf11a862fc9be56a3e69de79d593a3 Mon Sep 17 00:00:00 2001 From: ningding Date: Mon, 20 Jul 2026 19:18:19 -0700 Subject: [PATCH] TCPIP: make the return value of network_socket_accept_tcp more expressive The network_socket_accept_tcp function can only return either a valid sealed capability or an untagged nullptr, so the caller cannot distinguish a timeout from an out-of-memory failure. Change it so that it can return an invalid capability that encodes the error code. --- include/NetAPI.h | 10 ++++++-- lib/tcpip/network_wrapper.cc | 47 +++++++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/include/NetAPI.h b/include/NetAPI.h index 20ad6dfb..65be5f0e 100644 --- a/include/NetAPI.h +++ b/include/NetAPI.h @@ -235,8 +235,14 @@ Socket __cheri_compartment("NetAPI") * of the connected client. These can be null if the caller is not interested * in the client's address or port. * - * This returns a valid sealed capability to a connected socket on success, or - * an untagged value on failure. + * This returns either a valid sealed socket type or an untagged capability that + * encodes the error code, and here are what each of them represent: + * - `-ENOMEM`: allocation of the wrapper timed out or does not have memory for + * now. + * - `-EINVAL`: The timeout pointer is invalid, or FreeRTOS_accept returns + * invalid socket, or fail to claim the socket poiting to mallocCapability, or + * fail to add socket to the socket reset list, + * - `-ETIMEDOUT`: timed out on FreeRTOS_accept. */ Socket __cheri_compartment("TCPIP") network_socket_accept_tcp(Timeout *timeout, diff --git a/lib/tcpip/network_wrapper.cc b/lib/tcpip/network_wrapper.cc index fb9ca2a4..caa0c0a9 100644 --- a/lib/tcpip/network_wrapper.cc +++ b/lib/tcpip/network_wrapper.cc @@ -608,7 +608,8 @@ Socket network_socket_accept_tcp(Timeout *timeout, uint16_t *port) { Socket socket = nullptr; - with_sealed_socket( + int retVal = with_sealed_socket( + timeout, [&](SealedSocket *listeningSocket) { if (!check_timeout_pointer(timeout)) { @@ -621,24 +622,39 @@ Socket network_socket_accept_tcp(Timeout *timeout, if (socketWrapper == nullptr) { Debug::log("Failed to allocate socket wrapper."); - return -EINVAL; + return -ENOMEM; } socketWrapper->socketEpoch = currentSocketEpoch.load(); struct freertos_sockaddr addressTmp; uint32_t addressLength = sizeof(addressTmp); - auto rawSocket = FreeRTOS_accept( - listeningSocket->socket, &addressTmp, &addressLength); - if (rawSocket == nullptr) + FreeRTOS_Socket_t *rawSocket = nullptr; + + // acceptResult: 0 = valid socket || -EINVAL = FREERTOS_INVALID_SOCKET + // || -ETIMEDOUT = timed out + int acceptResult = with_freertos_timeout( + timeout, + listeningSocket->socket, + FREERTOS_SO_RCVTIMEO, + [&]() -> int { + rawSocket = FreeRTOS_accept( + listeningSocket->socket, &addressTmp, &addressLength); + if (rawSocket == nullptr) + { + return -ETIMEDOUT; + } + if (rawSocket == FREERTOS_INVALID_SOCKET) + { + return -EINVAL; + } + return 0; // returns a valid socket + }); + + if (acceptResult != 0) { - Debug::log("Failed to create socket."); - // This cannot fail unless buggy - we know that we - // successfully allocated the token with this malloc - // capability. Same for other calls to `token_obj_destroy` - // in this function. token_obj_destroy(mallocCapability, socket_key(), sealedSocket); - return -EINVAL; + return acceptResult; } socketWrapper->socket = rawSocket; @@ -720,6 +736,15 @@ Socket network_socket_accept_tcp(Timeout *timeout, return 0; }, sealedListeningSocket); + + if (retVal != 0) + { + __clang_ignored_warning_push("-Wcheri-capability-misuse"); + auto errCode = reinterpret_cast(retVal); + __clang_ignored_warning_pop(); + return errCode; + } + return socket; }