From fe70c799e5dec5108034f5f16719b5c10ef02596 Mon Sep 17 00:00:00 2001 From: Weijia Wang Date: Thu, 28 Jul 2022 01:37:50 +0200 Subject: [PATCH 1/3] os: wrap SOCK_CLOEXEC Signed-off-by: Weijia Wang --- src/wayland-os.c | 22 ++++++++++++++++++++++ src/wayland-os.h | 3 +++ tests/client-test.c | 3 ++- tests/connection-test.c | 9 +++++---- tests/os-wrappers-test.c | 10 ++++++++-- tests/resources-test.c | 7 ++++--- 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/wayland-os.c b/src/wayland-os.c index a9066cae..df971957 100644 --- a/src/wayland-os.c +++ b/src/wayland-os.c @@ -69,16 +69,38 @@ wl_os_socket_cloexec(int domain, int type, int protocol) { int fd; +#ifdef SOCK_CLOEXEC fd = socket(domain, type | SOCK_CLOEXEC, protocol); if (fd >= 0) return fd; if (errno != EINVAL) return -1; +#endif fd = socket(domain, type, protocol); return set_cloexec_or_close(fd); } +int +wl_os_socketpair_cloexec(int domain, int type, int protocol, int sv[2]) +{ + int retval; + +#ifdef SOCK_CLOEXEC + retval = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv); + if (retval >= 0) + return retval; + if (errno != EINVAL) + return -1; +#endif + + retval = socketpair(domain, type, protocol, sv); + if (set_cloexec_or_close(sv[0]) == -1 || set_cloexec_or_close(sv[1]) == -1) + retval = -1; + + return retval; +} + #if defined(__FreeBSD__) int wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) diff --git a/src/wayland-os.h b/src/wayland-os.h index 068fd2fe..42e28007 100644 --- a/src/wayland-os.h +++ b/src/wayland-os.h @@ -32,6 +32,9 @@ int wl_os_socket_cloexec(int domain, int type, int protocol); +int +wl_os_socketpair_cloexec(int domain, int type, int protocol, int sv[2]); + int wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid); diff --git a/tests/client-test.c b/tests/client-test.c index 960cfa95..117a3036 100644 --- a/tests/client-test.c +++ b/tests/client-test.c @@ -34,6 +34,7 @@ #include #include +#include "wayland-os.h" #include "wayland-private.h" #include "wayland-server.h" #include "test-runner.h" @@ -59,7 +60,7 @@ TEST(client_destroy_listener) struct client_destroy_listener a, b; int s[2]; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); diff --git a/tests/connection-test.c b/tests/connection-test.c index 9762e0da..80f4f443 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -37,6 +37,7 @@ #include #include +#include "wayland-os.h" #include "wayland-private.h" #include "test-runner.h" #include "test-compositor.h" @@ -48,7 +49,7 @@ setup(int *s) { struct wl_connection *connection; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); connection = wl_connection_create(s[0]); assert(connection); @@ -181,8 +182,8 @@ struct marshal_data { static void setup_marshal_data(struct marshal_data *data) { - assert(socketpair(AF_UNIX, - SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, + SOCK_STREAM, 0, data->s) == 0); data->read_connection = wl_connection_create(data->s[0]); assert(data->read_connection); data->write_connection = wl_connection_create(data->s[1]); @@ -824,7 +825,7 @@ TEST(request_bogus_size) for (bogus_size = 11; bogus_size >= 0; bogus_size--) { fprintf(stderr, "* bogus size %d\n", bogus_size); - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c index 8d8c3ab9..06025bcd 100644 --- a/tests/os-wrappers-test.c +++ b/tests/os-wrappers-test.c @@ -92,10 +92,12 @@ socket(int domain, int type, int protocol) { wrapped_calls_socket++; +#ifdef SOCK_CLOEXEC if (fall_back && (type & SOCK_CLOEXEC)) { errno = EINVAL; return -1; } +#endif return real_socket(domain, type, protocol); } @@ -179,7 +181,11 @@ do_os_wrappers_socket_cloexec(int n) * Must have 2 calls if falling back, but must also allow * falling back without a forced fallback. */ +#ifdef SOCK_CLOEXEC assert(wrapped_calls_socket > n); +#else + assert(wrapped_calls_socket == 1); +#endif exec_fd_leak_check(nr_fds); } @@ -253,8 +259,8 @@ struct marshal_data { static void setup_marshal_data(struct marshal_data *data) { - assert(socketpair(AF_UNIX, - SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, + SOCK_STREAM, 0, data->s) == 0); data->read_connection = wl_connection_create(data->s[0]); assert(data->read_connection); diff --git a/tests/resources-test.c b/tests/resources-test.c index fa6ba2b2..ca4595cb 100644 --- a/tests/resources-test.c +++ b/tests/resources-test.c @@ -28,6 +28,7 @@ #include #include +#include "wayland-os.h" #include "wayland-server.h" #include "test-runner.h" @@ -40,7 +41,7 @@ TEST(create_resource_tst) int s[2]; uint32_t id; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); @@ -111,7 +112,7 @@ TEST(destroy_res_tst) .notify = &destroy_notify }; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); @@ -159,7 +160,7 @@ TEST(create_resource_with_same_id) int s[2]; uint32_t id; - assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0); display = wl_display_create(); assert(display); client = wl_client_create(display, s[0]); From dc2be77f63984110f24ac5832257ea0704d5a1ca Mon Sep 17 00:00:00 2001 From: Weijia Wang Date: Thu, 28 Jul 2022 01:38:31 +0200 Subject: [PATCH 2/3] os: disable tests on HAVE_BROKEN_MSG_CMSG_CLOEXEC Signed-off-by: Weijia Wang --- tests/os-wrappers-test.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c index 06025bcd..754408da 100644 --- a/tests/os-wrappers-test.c +++ b/tests/os-wrappers-test.c @@ -143,10 +143,12 @@ recvmsg(int sockfd, struct msghdr *msg, int flags) { wrapped_calls_recvmsg++; +#if !(HAVE_BROKEN_MSG_CMSG_CLOEXEC) if (fall_back && (flags & MSG_CMSG_CLOEXEC)) { errno = EINVAL; return -1; } +#endif return real_recvmsg(sockfd, msg, flags); } @@ -225,7 +227,9 @@ do_os_wrappers_dupfd_cloexec(int n) * Must have 4 calls if falling back, but must also allow * falling back without a forced fallback. */ +#if !(HAVE_BROKEN_MSG_CMSG_CLOEXEC) assert(wrapped_calls_fcntl > n); +#endif exec_fd_leak_check(nr_fds); } From f9aa9b4a07519dc110d8217f989668092b8d7baf Mon Sep 17 00:00:00 2001 From: Weijia Wang Date: Sun, 31 Jul 2022 13:41:07 +0200 Subject: [PATCH 3/3] build: fix build on darwin Signed-off-by: Weijia Wang --- egl/wayland-egl-symbols-check | 11 +++++++++-- meson.build | 8 ++++---- src/wayland-os.c | 2 +- tests/display-test.c | 7 +++++++ tests/os-wrappers-test.c | 9 +++++++++ tests/test-runner.c | 11 +++++++++++ tests/test-runner.h | 10 ++++++++-- 7 files changed, 49 insertions(+), 9 deletions(-) diff --git a/egl/wayland-egl-symbols-check b/egl/wayland-egl-symbols-check index d04fd042..f8248cbe 100755 --- a/egl/wayland-egl-symbols-check +++ b/egl/wayland-egl-symbols-check @@ -14,7 +14,11 @@ if ! test -n "$NM"; then exit 99 fi -AVAIL_FUNCS="$($NM -D --format=bsd --defined-only $LIB | awk '{print $3}')" +if [ "$(uname)" == "Darwin" ]; then + AVAIL_FUNCS="$($NM $LIB | awk '{print $3}')" +else + AVAIL_FUNCS="$($NM -D --format=bsd --defined-only $LIB | awk '{print $3}')" +fi # Official ABI, taken from the header. REQ_FUNCS="wl_egl_window_resize @@ -37,8 +41,11 @@ if test -n "$NEW_ABI"; then fi REMOVED_ABI=$(echo "$REQ_FUNCS" | while read func; do +if [ "$(uname)" == "Darwin" ]; then + echo "$AVAIL_FUNCS" | grep -q "^_$func$" && continue +else echo "$AVAIL_FUNCS" | grep -q "^$func$" && continue - +fi echo $func done) diff --git a/meson.build b/meson.build index f469756f..03b845d6 100644 --- a/meson.build +++ b/meson.build @@ -16,7 +16,7 @@ config_h.set_quoted('PACKAGE', meson.project_name()) config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) cc_args = [] -if host_machine.system() != 'freebsd' +if host_machine.system() not in ['darwin', 'freebsd'] cc_args += ['-D_POSIX_C_SOURCE=200809L'] endif add_project_arguments(cc_args, language: 'c') @@ -51,7 +51,7 @@ foreach f: have_funcs config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f)) endforeach config_h.set10('HAVE_XUCRED_CR_PID', cc.has_member('struct xucred', 'cr_pid', prefix : '#include ')) -have_broken_msg_cmsg_cloexec = false +have_broken_msg_cmsg_cloexec = (host_machine.system() == 'darwin') if host_machine.system() == 'freebsd' have_broken_msg_cmsg_cloexec = not cc.compiles(''' #include /* To get __FreeBSD_version. */ @@ -69,8 +69,8 @@ endif config_h.set10('HAVE_BROKEN_MSG_CMSG_CLOEXEC', have_broken_msg_cmsg_cloexec) if get_option('libraries') - if host_machine.system() == 'freebsd' - # When building for FreeBSD, epoll(7) is provided by a userspace + if host_machine.system() in ['darwin', 'freebsd'] + # When building for macOS or FreeBSD, epoll(7) is provided by a userspace # wrapper around kqueue(2). epoll_dep = dependency('epoll-shim') else diff --git a/src/wayland-os.c b/src/wayland-os.c index df971957..c2ee1c63 100644 --- a/src/wayland-os.c +++ b/src/wayland-os.c @@ -101,7 +101,7 @@ wl_os_socketpair_cloexec(int domain, int type, int protocol, int sv[2]) return retval; } -#if defined(__FreeBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) int wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) { diff --git a/tests/display-test.c b/tests/display-test.c index bcb3267f..874d1b97 100644 --- a/tests/display-test.c +++ b/tests/display-test.c @@ -39,6 +39,10 @@ #include #include +#ifdef __APPLE__ +#include +#endif + #include #include @@ -1495,6 +1499,9 @@ send_overflow_client(void *data) /* Limit the send buffer size for the display socket to guarantee * that the test will cause an overflow. */ sock = wl_display_get_fd(c->wl_display); +#ifdef __APPLE__ + assert(fcntl(sock, F_SETFL, ~O_NONBLOCK) != -1); +#endif assert(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval)) == 0); /* Request to break out of 'display_run' in the main process */ diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c index 754408da..334a645f 100644 --- a/tests/os-wrappers-test.c +++ b/tests/os-wrappers-test.c @@ -63,6 +63,14 @@ static int fall_back; * __interceptor_ and check at run time if they linked to anything or not. */ +#ifdef __APPLE__ +#define DECL(ret_type, func, ...) \ + static ret_type (*real_ ## func)(__VA_ARGS__); \ + static int wrapped_calls_ ## func; + +#define REAL(func) \ + (__typeof__(real_ ## func))dlsym(RTLD_NEXT, #func) +#else #define DECL(ret_type, func, ...) \ ret_type __interceptor_ ## func(__VA_ARGS__) __attribute__((weak)); \ static ret_type (*real_ ## func)(__VA_ARGS__); \ @@ -71,6 +79,7 @@ static int fall_back; #define REAL(func) (__interceptor_ ## func) ? \ __interceptor_ ## func : \ (__typeof__(&__interceptor_ ## func))dlsym(RTLD_NEXT, #func) +#endif DECL(int, socket, int, int, int); DECL(int, fcntl, int, int, ...); diff --git a/tests/test-runner.c b/tests/test-runner.c index d07dab15..7a61ecba 100644 --- a/tests/test-runner.c +++ b/tests/test-runner.c @@ -63,7 +63,12 @@ static int timeouts_enabled = 1; /* set to one if the output goes to the terminal */ static int is_atty = 0; +#ifdef __APPLE__ +extern const struct test __start_test_section __asm("section$start$__RODATA$test_section"); +extern const struct test __stop_test_section __asm("section$end$__RODATA$test_section"); +#else extern const struct test __start_test_section, __stop_test_section; +#endif static const struct test * find_test(const char *name) @@ -308,6 +313,12 @@ is_debugger_attached(void) return rc; } +#else +static int +is_debugger_attached(void) +{ + return 0; +} #endif int main(int argc, char *argv[]) diff --git a/tests/test-runner.h b/tests/test-runner.h index d0734009..b7133806 100644 --- a/tests/test-runner.h +++ b/tests/test-runner.h @@ -37,11 +37,17 @@ struct test { int must_fail; } __attribute__ ((aligned (16))); +#ifdef __APPLE__ +#define TEST_SECTION "__RODATA,test_section" +#else +#define TEST_SECTION "test_section" +#endif + #define TEST(name) \ static void name(void); \ \ const struct test test##name \ - __attribute__ ((used, section ("test_section"))) = { \ + __attribute__ ((used, section (TEST_SECTION))) = { \ #name, name, 0 \ }; \ \ @@ -51,7 +57,7 @@ struct test { static void name(void); \ \ const struct test test##name \ - __attribute__ ((used, section ("test_section"))) = { \ + __attribute__ ((used, section (TEST_SECTION))) = { \ #name, name, 1 \ }; \ \