This is the most trivial way to fix the issue with macOS not having SOCK_CLOEXEC and SOCK_NONBLOCK. There is not much better way, so this is the only way to make it work on such platform(s).
Signed-off-by: Martin Kletzander <[email protected]> --- lib/internal.h | 3 + generator/states-connect-socket-activation.c | 2 +- generator/states-connect.c | 11 ++-- lib/utils.c | 68 ++++++++++++++++++++ fuzzing/libnbd-fuzz-wrapper.c | 30 ++++++++- fuzzing/libnbd-libfuzzer-test.c | 30 ++++++++- 6 files changed, 136 insertions(+), 8 deletions(-) diff --git a/lib/internal.h b/lib/internal.h index 01f9d8ab5fea..8a4c189abe65 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -467,4 +467,7 @@ extern char *nbd_internal_printable_buffer (const void *buf, size_t count); extern char *nbd_internal_printable_string (const char *str); extern char *nbd_internal_printable_string_list (char **list); +extern int nbd_internal_socket(int domain, int type, int protocol, bool nonblock); +extern int nbd_internal_socketpair(int domain, int type, int protocol, int *fds); + #endif /* LIBNBD_INTERNAL_H */ diff --git a/generator/states-connect-socket-activation.c b/generator/states-connect-socket-activation.c index e601c9bb56be..8a2add312bc4 100644 --- a/generator/states-connect-socket-activation.c +++ b/generator/states-connect-socket-activation.c @@ -131,7 +131,7 @@ STATE_MACHINE { return 0; } - s = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + s = nbd_internal_socket (AF_UNIX, SOCK_STREAM, 0, false); if (s == -1) { SET_NEXT_STATE (%.DEAD); set_error (errno, "socket"); diff --git a/generator/states-connect.c b/generator/states-connect.c index fcac86f36a34..8de12183d627 100644 --- a/generator/states-connect.c +++ b/generator/states-connect.c @@ -52,7 +52,7 @@ STATE_MACHINE { assert (!h->sock); family = h->connaddr.ss_family; - fd = socket (family, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); + fd = nbd_internal_socket (family, SOCK_STREAM, 0, true); if (fd == -1) { SET_NEXT_STATE (%.DEAD); set_error (errno, "socket"); @@ -162,9 +162,10 @@ STATE_MACHINE { return -1; } - fd = socket (h->rp->ai_family, - h->rp->ai_socktype|SOCK_NONBLOCK|SOCK_CLOEXEC, - h->rp->ai_protocol); + fd = nbd_internal_socket (h->rp->ai_family, + h->rp->ai_socktype, + h->rp->ai_protocol, + true); if (fd == -1) { SET_NEXT_STATE (%NEXT_ADDRESS); return 0; @@ -227,7 +228,7 @@ STATE_MACHINE { assert (!h->sock); assert (h->argv.ptr); assert (h->argv.ptr[0]); - if (socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sv) == -1) { + if (nbd_internal_socketpair (AF_UNIX, SOCK_STREAM, 0, sv) == -1) { SET_NEXT_STATE (%.DEAD); set_error (errno, "socketpair"); return 0; diff --git a/lib/utils.c b/lib/utils.c index 260fd6a25796..972cbc5208a7 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -24,6 +24,7 @@ #include <unistd.h> #include <ctype.h> #include <errno.h> +#include <fcntl.h> #include "minmax.h" @@ -258,3 +259,70 @@ nbd_internal_printable_string_list (char **list) return s; } + +int nbd_internal_socket(int domain, + int type, + int protocol, + bool nonblock) +{ + int fd; + +#ifdef __APPLE__ + int flags; +#else + type |= SOCK_CLOEXEC; + if (nonblock) + type |= SOCK_NONBLOCK; +#endif + + fd = socket (domain, type, protocol); + +#ifdef __APPLE__ + if (fd == -1) + return -1; + + if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) { + close(fd); + return -1; + } + + if (nonblock) { + flags = fcntl (fd, F_GETFL, 0); + if (flags == -1 || + fcntl (fd, F_SETFL, flags|O_NONBLOCK) == -1) { + close(fd); + return -1; + } + } +#endif + + return fd; +} + +int +nbd_internal_socketpair (int domain, int type, int protocol, int *fds) +{ + int ret; + +#ifdef __APPLE__ + size_t i; +#else + type |= SOCK_CLOEXEC; +#endif + + ret = socketpair (domain, type, protocol, fds); + +#ifdef __APPLE__ + if (ret == 0) { + for (i = 0; i < 2; i++) { + if (fcntl (fds[i], F_SETFD, FD_CLOEXEC) == -1) { + close(fds[0]); + close(fds[1]); + return -1; + } + } + } +#endif + + return ret; +} diff --git a/fuzzing/libnbd-fuzz-wrapper.c b/fuzzing/libnbd-fuzz-wrapper.c index 99a6d803258f..3d127e673e9e 100644 --- a/fuzzing/libnbd-fuzz-wrapper.c +++ b/fuzzing/libnbd-fuzz-wrapper.c @@ -41,6 +41,34 @@ static void client (int s); static void server (int fd, int s); +static int +get_socketpair (int domain, int type, int protocol, int *fds) +{ + int ret; + +#ifdef __APPLE__ + size_t i; +#else + type |= SOCK_CLOEXEC; +#endif + + ret = socketpair (domain, type, protocol, fds); + +#ifdef __APPLE__ + if (ret == 0) { + for (i = 0; i < 2; i++) { + if (fcntl (fds[i], F_SETFD, FD_CLOEXEC) == -1) { + close(fds[0]); + close(fds[1]); + return -1; + } + } + } +#endif + + return ret; +} + int main (int argc, char *argv[]) { @@ -61,7 +89,7 @@ main (int argc, char *argv[]) } /* Create a connected socket. */ - if (socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sv) == -1) { + if (get_socketpair (AF_UNIX, SOCK_STREAM, 0, sv) == -1) { perror ("socketpair"); exit (EXIT_FAILURE); } diff --git a/fuzzing/libnbd-libfuzzer-test.c b/fuzzing/libnbd-libfuzzer-test.c index 5ee29b877bdb..0bf988ee8398 100644 --- a/fuzzing/libnbd-libfuzzer-test.c +++ b/fuzzing/libnbd-libfuzzer-test.c @@ -41,6 +41,34 @@ static void client (int sock); static void server (const uint8_t *data, size_t size, int sock); +static int +get_socketpair (int domain, int type, int protocol, int *fds) +{ + int ret; + +#ifdef __APPLE__ + size_t i; +#else + type |= SOCK_CLOEXEC; +#endif + + ret = socketpair (domain, type, protocol, fds); + +#ifdef __APPLE__ + if (ret == 0) { + for (i = 0; i < 2; i++) { + if (fcntl (fds[i], F_SETFD, FD_CLOEXEC) == -1) { + close(fds[0]); + close(fds[1]); + return -1; + } + } + } +#endif + + return ret; +} + /* This is the entry point called by libFuzzer. */ int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size) @@ -49,7 +77,7 @@ LLVMFuzzerTestOneInput (const uint8_t *data, size_t size) int sv[2], r, status; /* Create a connected socket. */ - if (socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sv) == -1) { + if (nbd_internal_socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sv) == -1) { perror ("socketpair"); exit (EXIT_FAILURE); } -- 2.32.0 _______________________________________________ Libguestfs mailing list [email protected] https://listman.redhat.com/mailman/listinfo/libguestfs
