Skip to content

Commit e335905

Browse files
committed
F-4950: negate wolfIP error code when setting errno in POSIX shim macros
conditional_steal_call, conditional_steal_blocking_call and wolfip_accept_common assigned the raw negative wolfIP return code to errno (e.g. errno = -EINVAL) instead of its positive magnitude. Callers comparing errno == EINVAL / ENOTCONN / ECONNRESET would silently mismatch. Negate the value to match the adjacent hand-written paths (bind/close/sendto/send) and the macros' own EAGAIN/wait-error branches. Adds test-posix-errno which drives getpeername() through the conditional_steal_call macro and asserts errno is a positive value.
1 parent 285437e commit e335905

3 files changed

Lines changed: 87 additions & 3 deletions

File tree

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,17 @@ build/packet_ping: $(OBJ) build/port/posix/bsd_socket.o build/test/packet_ping.o
332332
@echo "[LD] $@"
333333
@$(CC) $(CFLAGS) -o $@ $(BEGIN_GROUP) $(^) $(LDFLAGS) $(END_GROUP)
334334

335+
# F-4950 regression: test_posix_errno.c #includes bsd_socket.c directly, so the
336+
# shim object must not be linked again here.
337+
build/test-posix-errno: $(OBJ) build/test/test_posix_errno.o
338+
@echo "[LD] $@"
339+
@$(CC) $(CFLAGS) -o $@ $(BEGIN_GROUP) $(^) $(LDFLAGS) $(END_GROUP)
340+
341+
.PHONY: posix-errno-test
342+
posix-errno-test: build/test-posix-errno
343+
@echo "[RUN] $<"
344+
@./build/test-posix-errno
345+
335346

336347
build/test-wolfssl:CFLAGS+=-Wno-cpp -DWOLFSSL_DEBUG -DWOLFSSL_WOLFIP
337348
build/test-httpd:CFLAGS+=-Wno-cpp -DWOLFSSL_DEBUG -DWOLFSSL_WOLFIP -Isrc/http

src/port/posix/bsd_socket.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ static int wolfip_wait_for_event_locked(struct wolfip_fd_entry *entry, short wai
538538
if (__wolfip_internal >= 0) { \
539539
int __wolfip_retval = wolfIP_sock_##call(IPSTACK, __wolfip_internal, ## __VA_ARGS__); \
540540
if (__wolfip_retval < 0) { \
541-
errno = __wolfip_retval; \
541+
errno = -__wolfip_retval; \
542542
pthread_mutex_unlock(&wolfIP_mutex); \
543543
return -1; \
544544
} \
@@ -585,7 +585,7 @@ static int wolfip_wait_for_event_locked(struct wolfip_fd_entry *entry, short wai
585585
} \
586586
} while (__wolfip_retval == -EAGAIN); \
587587
if (__wolfip_retval < 0) { \
588-
errno = __wolfip_retval; \
588+
errno = -__wolfip_retval; \
589589
pthread_mutex_unlock(&wolfIP_mutex); \
590590
return -1; \
591591
} \
@@ -1544,7 +1544,7 @@ static int wolfip_accept_common(int sockfd, struct sockaddr *addr, socklen_t *ad
15441544
}
15451545
} while (internal_ret == -EAGAIN);
15461546
if (internal_ret < 0) {
1547-
errno = internal_ret;
1547+
errno = -internal_ret;
15481548
pthread_mutex_unlock(&wolfIP_mutex);
15491549
return -1;
15501550
}

src/test/test_posix_errno.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/* test_posix_errno.c
2+
*
3+
* Copyright (C) 2024 wolfSSL Inc.
4+
*
5+
* This file is part of wolfIP TCP/IP stack.
6+
*
7+
* wolfIP is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfIP is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
*/
21+
22+
/* Regression test for F-4950: the POSIX shim macros must translate a negative
23+
* wolfIP return code into a positive errno, exactly as the hand-written paths
24+
* (bind/close/send/...) already do. Driving getpeername() through the
25+
* conditional_steal_call() macro on a wolfIP-managed fd exercises the
26+
* "errno = -ret" conversion: with the sign bug present errno is set to the raw
27+
* negative code and the assertion below fails. */
28+
29+
#include <assert.h>
30+
#include <errno.h>
31+
#include <stdio.h>
32+
#include <string.h>
33+
#include <netinet/in.h>
34+
35+
/* Pull in the shim itself so we can reach its file-static state
36+
* (in_the_stack / IPSTACK). The library constructor runs at load; without
37+
* CAP_NET_ADMIN its TAP setup simply fails and returns, leaving the host_*
38+
* passthrough pointers populated, which is all this test needs. */
39+
#include "../port/posix/bsd_socket.c"
40+
41+
int main(void)
42+
{
43+
struct sockaddr_in peer;
44+
socklen_t peerlen = 0; /* deliberately too small -> internal error path */
45+
int fd;
46+
int ret;
47+
48+
/* The library constructor already initialised the static stack via
49+
* wolfIP_init_static(); make sure it is present and take over the shim
50+
* path so socket()/getpeername() are served by wolfIP, not libc. */
51+
if (!IPSTACK)
52+
wolfIP_init_static(&IPSTACK);
53+
in_the_stack = 0;
54+
55+
fd = socket(AF_INET, SOCK_STREAM, 0);
56+
assert(fd >= 0);
57+
58+
errno = 0;
59+
memset(&peer, 0, sizeof(peer));
60+
ret = getpeername(fd, (struct sockaddr *)&peer, &peerlen);
61+
62+
printf("getpeername ret=%d errno=%d (%s)\n", ret, errno,
63+
errno > 0 ? strerror(errno) : "negative/raw");
64+
65+
/* The call must fail... */
66+
assert(ret == -1);
67+
/* ...and errno must be a real positive errno value, never the raw negative
68+
* wolfIP code (the F-4950 defect). */
69+
assert(errno > 0);
70+
71+
printf("F-4950 regression test passed\n");
72+
return 0;
73+
}

0 commit comments

Comments
 (0)