Skip to content

Commit e8a89ef

Browse files
committed
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.
1 parent 7d04987 commit e8a89ef

2 files changed

Lines changed: 43 additions & 13 deletions

File tree

include/NetAPI.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,13 @@ Socket __cheri_compartment("NetAPI")
235235
* of the connected client. These can be null if the caller is not interested
236236
* in the client's address or port.
237237
*
238-
* This returns a valid sealed capability to a connected socket on success, or
239-
* an untagged value on failure.
238+
* This returns either a valid sealed socket type or an untagged capability that
239+
* encodes the error code, and here are what each of them represent:
240+
* - `-ENOMEM`: allocation of the wrapper timed out or does not have memory for now.
241+
* - `-EINVAL`: The timeout pointer is invalid, or FreeRTOS_accept returns invalid
242+
* socket, or fail to claim the socket poiting to mallocCapability,
243+
* or fail to add socket to the socket reset list,
244+
* - `-ETIMEDOUT`: timed out on FreeRTOS_accept.
240245
*/
241246
Socket __cheri_compartment("TCPIP")
242247
network_socket_accept_tcp(Timeout *timeout,

lib/tcpip/network_wrapper.cc

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,8 @@ Socket network_socket_accept_tcp(Timeout *timeout,
608608
uint16_t *port)
609609
{
610610
Socket socket = nullptr;
611-
with_sealed_socket(
611+
int retVal = with_sealed_socket(
612+
timeout,
612613
[&](SealedSocket *listeningSocket) {
613614
if (!check_timeout_pointer(timeout))
614615
{
@@ -621,24 +622,39 @@ Socket network_socket_accept_tcp(Timeout *timeout,
621622
if (socketWrapper == nullptr)
622623
{
623624
Debug::log("Failed to allocate socket wrapper.");
624-
return -EINVAL;
625+
return -ENOMEM;
625626
}
626627

627628
socketWrapper->socketEpoch = currentSocketEpoch.load();
628629

629630
struct freertos_sockaddr addressTmp;
630631
uint32_t addressLength = sizeof(addressTmp);
631-
auto rawSocket = FreeRTOS_accept(
632-
listeningSocket->socket, &addressTmp, &addressLength);
633-
if (rawSocket == nullptr)
632+
FreeRTOS_Socket_t *rawSocket = nullptr;
633+
634+
// acceptResult: 0 = valid socket || -EINVAL = FREERTOS_INVALID_SOCKET
635+
// || -ETIMEDOUT = timed out
636+
int acceptResult = with_freertos_timeout(
637+
timeout,
638+
listeningSocket->socket,
639+
FREERTOS_SO_RCVTIMEO,
640+
[&]() -> int {
641+
rawSocket = FreeRTOS_accept(
642+
listeningSocket->socket, &addressTmp, &addressLength);
643+
if (rawSocket == nullptr)
644+
{
645+
return -ETIMEDOUT;
646+
}
647+
if (rawSocket == FREERTOS_INVALID_SOCKET)
648+
{
649+
return -EINVAL;
650+
}
651+
return 0; // returns a valid socket
652+
});
653+
654+
if (acceptResult != 0)
634655
{
635-
Debug::log("Failed to create socket.");
636-
// This cannot fail unless buggy - we know that we
637-
// successfully allocated the token with this malloc
638-
// capability. Same for other calls to `token_obj_destroy`
639-
// in this function.
640656
token_obj_destroy(mallocCapability, socket_key(), sealedSocket);
641-
return -EINVAL;
657+
return acceptResult;
642658
}
643659
socketWrapper->socket = rawSocket;
644660

@@ -720,6 +736,15 @@ Socket network_socket_accept_tcp(Timeout *timeout,
720736
return 0;
721737
},
722738
sealedListeningSocket);
739+
740+
if (retVal != 0)
741+
{
742+
__clang_ignored_warning_push("-Wcheri-capability-misuse");
743+
auto errCode = reinterpret_cast<Socket>(retVal);
744+
__clang_ignored_warning_pop();
745+
return errCode;
746+
}
747+
723748
return socket;
724749
}
725750

0 commit comments

Comments
 (0)