From f96773410a343818f42adb38615e3bc76fb8a5e6 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Fri, 16 Sep 2022 04:09:03 +0100 Subject: [PATCH] Fix `bind()` calls to receive the correct size of `sockaddr` structure (#1490) For some implementations (e.g. Mac OS) `bind()` requires the length to be exactly equal to either `sockaddr_in` or `sockaddr_in6` structure. Because we always used `sizeof(struct sockaddr_storage)`, `bind()` was returning errors. In this change we fix the behavior. See StackOverflow [1] for details. [1] https://stackoverflow.com/questions/73707162/socket-bind-failed-with-invalid-argument-error-for-program-running-on-macos --- .../platform/common/posix/posix_socket.c | 21 ++++++++++++------- samples/socket-api/wasm-src/tcp_client.c | 6 +++--- samples/socket-api/wasm-src/tcp_server.c | 4 +++- samples/socket-api/wasm-src/udp_server.c | 4 +++- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/core/shared/platform/common/posix/posix_socket.c b/core/shared/platform/common/posix/posix_socket.c index f6091cde2..3f4e2afab 100644 --- a/core/shared/platform/common/posix/posix_socket.c +++ b/core/shared/platform/common/posix/posix_socket.c @@ -12,7 +12,8 @@ #include static bool -textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out) +textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out, + socklen_t *out_len) { struct sockaddr_in *v4; struct sockaddr_in6 *v6; @@ -23,6 +24,7 @@ textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out) if (inet_pton(AF_INET, textual, &v4->sin_addr.s_addr) == 1) { v4->sin_family = AF_INET; v4->sin_port = htons(port); + *out_len = sizeof(struct sockaddr_in); return true; } @@ -30,6 +32,7 @@ textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out) if (inet_pton(AF_INET6, textual, &v6->sin6_addr.s6_addr) == 1) { v6->sin6_family = AF_INET6; v6->sin6_port = htons(port); + *out_len = sizeof(struct sockaddr_in6); return true; } @@ -129,7 +132,7 @@ os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) int os_socket_bind(bh_socket_t socket, const char *host, int *port) { - struct sockaddr_storage addr; + struct sockaddr_storage addr = { 0 }; struct linger ling; socklen_t socklen; int ret; @@ -150,11 +153,12 @@ os_socket_bind(bh_socket_t socket, const char *host, int *port) goto fail; } - if (!textual_addr_to_sockaddr(host, *port, (struct sockaddr *)&addr)) { + if (!textual_addr_to_sockaddr(host, *port, (struct sockaddr *)&addr, + &socklen)) { goto fail; } - ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr)); + ret = bind(socket, (struct sockaddr *)&addr, socklen); if (ret < 0) { goto fail; } @@ -220,10 +224,11 @@ int os_socket_connect(bh_socket_t socket, const char *addr, int port) { struct sockaddr_storage addr_in = { 0 }; - socklen_t addr_len = sizeof(struct sockaddr_storage); + socklen_t addr_len; int ret = 0; - if (!textual_addr_to_sockaddr(addr, port, (struct sockaddr *)&addr_in)) { + if (!textual_addr_to_sockaddr(addr, port, (struct sockaddr *)&addr_in, + &addr_len)) { return BHT_ERROR; } @@ -245,7 +250,7 @@ int os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, bh_sockaddr_t *src_addr) { - struct sockaddr_storage sock_addr = {}; + struct sockaddr_storage sock_addr = { 0 }; socklen_t socklen = sizeof(sock_addr); int ret; @@ -274,7 +279,7 @@ int os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len, int flags, const bh_sockaddr_t *dest_addr) { - struct sockaddr_storage sock_addr = {}; + struct sockaddr_storage sock_addr = { 0 }; socklen_t socklen = 0; bh_sockaddr_to_sockaddr(dest_addr, &sock_addr, &socklen); diff --git a/samples/socket-api/wasm-src/tcp_client.c b/samples/socket-api/wasm-src/tcp_client.c index 937d70e57..aad449483 100644 --- a/samples/socket-api/wasm-src/tcp_client.c +++ b/samples/socket-api/wasm-src/tcp_client.c @@ -45,10 +45,12 @@ main(int argc, char *argv[]) if (argc > 1 && strcmp(argv[1], "inet6") == 0) { af = AF_INET6; + len = sizeof(struct sockaddr_in6); init_sockaddr_inet6((struct sockaddr_in6 *)&server_address); } else { af = AF_INET; + len = sizeof(struct sockaddr_in); init_sockaddr_inet((struct sockaddr_in *)&server_address); } @@ -60,9 +62,7 @@ main(int argc, char *argv[]) } printf("[Client] Connect socket\n"); - if (connect(socket_fd, (struct sockaddr *)&server_address, - sizeof(server_address)) - == -1) { + if (connect(socket_fd, (struct sockaddr *)&server_address, len) == -1) { perror("Connect failed"); close(socket_fd); return EXIT_FAILURE; diff --git a/samples/socket-api/wasm-src/tcp_server.c b/samples/socket-api/wasm-src/tcp_server.c index 7977b9c55..2798dc252 100644 --- a/samples/socket-api/wasm-src/tcp_server.c +++ b/samples/socket-api/wasm-src/tcp_server.c @@ -73,10 +73,12 @@ main(int argc, char *argv[]) if (argc > 1 && strcmp(argv[1], "inet6") == 0) { af = AF_INET6; + addrlen = sizeof(struct sockaddr_in6); init_sockaddr_inet6((struct sockaddr_in6 *)&addr); } else { af = AF_INET; + addrlen = sizeof(struct sockaddr_in6); init_sockaddr_inet((struct sockaddr_in *)&addr); } @@ -88,7 +90,6 @@ main(int argc, char *argv[]) } printf("[Server] Bind socket\n"); - addrlen = sizeof(addr); if (bind(socket_fd, (struct sockaddr *)&addr, addrlen) < 0) { perror("Bind failed"); goto fail; @@ -102,6 +103,7 @@ main(int argc, char *argv[]) printf("[Server] Wait for clients to connect ..\n"); while (connections < WORKER_NUM) { + addrlen = sizeof(struct sockaddr); client_sock_fds[connections] = accept(socket_fd, (struct sockaddr *)&addr, (socklen_t *)&addrlen); if (client_sock_fds[connections] < 0) { diff --git a/samples/socket-api/wasm-src/udp_server.c b/samples/socket-api/wasm-src/udp_server.c index 02b14500d..1e24dd2fd 100644 --- a/samples/socket-api/wasm-src/udp_server.c +++ b/samples/socket-api/wasm-src/udp_server.c @@ -48,10 +48,12 @@ main(int argc, char *argv[]) if (argc > 1 && strcmp(argv[1], "inet6") == 0) { af = AF_INET6; + addrlen = sizeof(struct sockaddr_in6); init_sockaddr_inet6((struct sockaddr_in6 *)&addr); } else { af = AF_INET; + addrlen = sizeof(struct sockaddr_in); init_sockaddr_inet((struct sockaddr_in *)&addr); } @@ -63,7 +65,6 @@ main(int argc, char *argv[]) } printf("[Server] Bind socket\n"); - addrlen = sizeof(addr); if (bind(socket_fd, (struct sockaddr *)&addr, addrlen) < 0) { perror("Bind failed"); goto fail; @@ -71,6 +72,7 @@ main(int argc, char *argv[]) printf("[Server] Wait for clients to connect ..\n"); while (connections < MAX_CONNECTIONS_COUNT) { + addrlen = sizeof(addr); int ret = recvfrom(socket_fd, buffer, sizeof(buffer), 0, (struct sockaddr *)&addr, &addrlen); if (ret < 0) {