mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2026-03-31 07:11:27 -04:00
Avoid SOCK_CLOEXEC on Darwin
Signed-off-by: Torrekie Gen <me@torrekie.dev>
This commit is contained in:
parent
91484e380f
commit
3c6a88253c
8 changed files with 155 additions and 8 deletions
|
|
@ -74,18 +74,20 @@ int
|
||||||
wl_os_socket_cloexec(int domain, int type, int protocol)
|
wl_os_socket_cloexec(int domain, int type, int protocol)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
#if !defined(__APPLE__)
|
||||||
|
/* It is ok to bypass this logic on Darwin,
|
||||||
|
FD_CLOEXEC will be set by set_cloexec_or_close() */
|
||||||
fd = wl_socket(domain, type | SOCK_CLOEXEC, protocol);
|
fd = wl_socket(domain, type | SOCK_CLOEXEC, protocol);
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
return fd;
|
return fd;
|
||||||
if (errno != EINVAL)
|
if (errno != EINVAL)
|
||||||
return -1;
|
return -1;
|
||||||
|
#endif
|
||||||
fd = wl_socket(domain, type, protocol);
|
fd = wl_socket(domain, type, protocol);
|
||||||
return set_cloexec_or_close(fd);
|
return set_cloexec_or_close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
#if defined(LOCAL_PEERCRED)
|
||||||
int
|
int
|
||||||
wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
|
wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
|
||||||
{
|
{
|
||||||
|
|
@ -101,6 +103,14 @@ wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
|
||||||
#if HAVE_XUCRED_CR_PID
|
#if HAVE_XUCRED_CR_PID
|
||||||
/* Since https://cgit.freebsd.org/src/commit/?id=c5afec6e895a */
|
/* Since https://cgit.freebsd.org/src/commit/?id=c5afec6e895a */
|
||||||
*pid = ucred.cr_pid;
|
*pid = ucred.cr_pid;
|
||||||
|
#elif defined(LOCAL_PEERPID)
|
||||||
|
/* Try LOCAL_PEERPID if no cr_pid in xucred */
|
||||||
|
size_t pid_size;
|
||||||
|
pid_t peerpid;
|
||||||
|
if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERPID, &peerpid, &pid_size))
|
||||||
|
*pid = peerpid;
|
||||||
|
else
|
||||||
|
*pid = 0;
|
||||||
#else
|
#else
|
||||||
*pid = 0;
|
*pid = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -178,13 +188,16 @@ recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags)
|
||||||
ssize_t
|
ssize_t
|
||||||
wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
|
wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
|
||||||
{
|
{
|
||||||
#if HAVE_BROKEN_MSG_CMSG_CLOEXEC
|
#if HAVE_BROKEN_MSG_CMSG_CLOEXEC || defined(__APPLE__)
|
||||||
/*
|
/*
|
||||||
* FreeBSD had a broken implementation of MSG_CMSG_CLOEXEC between 2015
|
* FreeBSD had a broken implementation of MSG_CMSG_CLOEXEC between 2015
|
||||||
* and 2021, so we have to use the non-MSG_CMSG_CLOEXEC fallback
|
* and 2021, so we have to use the non-MSG_CMSG_CLOEXEC fallback
|
||||||
* directly when compiling against a version that does not include the
|
* directly when compiling against a version that does not include the
|
||||||
* fix (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211).
|
* fix (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211).
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
* Darwin has no MSG_CMSG_CLOEXEC, so use fallback too.
|
||||||
|
*/
|
||||||
#pragma message("Using fallback directly since MSG_CMSG_CLOEXEC is broken.")
|
#pragma message("Using fallback directly since MSG_CMSG_CLOEXEC is broken.")
|
||||||
#else
|
#else
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
@ -220,7 +233,7 @@ wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
#ifdef HAVE_ACCEPT4
|
#if defined(HAVE_ACCEPT4) && !defined(__APPLE__)
|
||||||
fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
|
fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,13 @@ TEST(client_destroy_listener)
|
||||||
bool user_data_destroyed = false;
|
bool user_data_destroyed = false;
|
||||||
int s[2];
|
int s[2];
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||||
|
#else
|
||||||
|
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||||
|
assert(set_cloexec_or_close(s[0]) != -1);
|
||||||
|
assert(set_cloexec_or_close(s[1]) != -1);
|
||||||
|
#endif
|
||||||
display = wl_display_create();
|
display = wl_display_create();
|
||||||
assert(display);
|
assert(display);
|
||||||
client = wl_client_create(display, s[0]);
|
client = wl_client_create(display, s[0]);
|
||||||
|
|
@ -184,7 +190,13 @@ TEST(client_destroy_removes_link)
|
||||||
struct client_destroy_listener destroy_listener;
|
struct client_destroy_listener destroy_listener;
|
||||||
int s[2];
|
int s[2];
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||||
|
#else
|
||||||
|
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||||
|
assert(set_cloexec_or_close(s[0]) != -1);
|
||||||
|
assert(set_cloexec_or_close(s[1]) != -1);
|
||||||
|
#endif
|
||||||
display = wl_display_create();
|
display = wl_display_create();
|
||||||
assert(display);
|
assert(display);
|
||||||
client = wl_client_create(display, s[0]);
|
client = wl_client_create(display, s[0]);
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,13 @@ setup(int *s)
|
||||||
{
|
{
|
||||||
struct wl_connection *connection;
|
struct wl_connection *connection;
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||||
|
#else
|
||||||
|
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||||
|
assert(set_cloexec_or_close(s[0]) != -1);
|
||||||
|
assert(set_cloexec_or_close(s[1]) != -1);
|
||||||
|
#endif
|
||||||
|
|
||||||
connection = wl_connection_create(s[0], WL_BUFFER_DEFAULT_MAX_SIZE);
|
connection = wl_connection_create(s[0], WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||||
assert(connection);
|
assert(connection);
|
||||||
|
|
@ -181,8 +187,14 @@ struct marshal_data {
|
||||||
static void
|
static void
|
||||||
setup_marshal_data(struct marshal_data *data)
|
setup_marshal_data(struct marshal_data *data)
|
||||||
{
|
{
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
assert(socketpair(AF_UNIX,
|
assert(socketpair(AF_UNIX,
|
||||||
SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
|
SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
|
||||||
|
#else
|
||||||
|
assert(socketpair(AF_UNIX, SOCK_STREAM , 0, data->s) == 0);
|
||||||
|
assert(set_cloexec_or_close(data->s[0]) != -1);
|
||||||
|
assert(set_cloexec_or_close(data->s[1]) != -1);
|
||||||
|
#endif
|
||||||
data->read_connection = wl_connection_create(data->s[0],
|
data->read_connection = wl_connection_create(data->s[0],
|
||||||
WL_BUFFER_DEFAULT_MAX_SIZE);
|
WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||||
assert(data->read_connection);
|
assert(data->read_connection);
|
||||||
|
|
@ -885,7 +897,13 @@ TEST(request_bogus_size)
|
||||||
for (bogus_size = 11; bogus_size >= 0; bogus_size--) {
|
for (bogus_size = 11; bogus_size >= 0; bogus_size--) {
|
||||||
fprintf(stderr, "* bogus size %d\n", bogus_size);
|
fprintf(stderr, "* bogus size %d\n", bogus_size);
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||||
|
#else
|
||||||
|
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||||
|
assert(set_cloexec_or_close(s[0]) != -1);
|
||||||
|
assert(set_cloexec_or_close(s[1]) != -1);
|
||||||
|
#endif
|
||||||
display = wl_display_create();
|
display = wl_display_create();
|
||||||
assert(display);
|
assert(display);
|
||||||
client = wl_client_create(display, s[0]);
|
client = wl_client_create(display, s[0]);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
/* This test should be skipped on Darwin (as of 2024) */
|
||||||
|
#ifndef __APPLE__
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
@ -387,5 +389,5 @@ TEST(os_wrappers_epoll_create_cloexec_fallback)
|
||||||
init_fallbacks(1);
|
init_fallbacks(1);
|
||||||
do_os_wrappers_epoll_create_cloexec(2);
|
do_os_wrappers_epoll_create_cloexec(2);
|
||||||
}
|
}
|
||||||
|
#endif /* __APPLE__ */
|
||||||
/* FIXME: add tests for wl_os_accept_cloexec() */
|
/* FIXME: add tests for wl_os_accept_cloexec() */
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,14 @@ TEST(create_resource_tst)
|
||||||
int s[2];
|
int s[2];
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||||
|
#else
|
||||||
|
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||||
|
assert(set_cloexec_or_close(s[0]) != -1);
|
||||||
|
assert(set_cloexec_or_close(s[1]) != -1);
|
||||||
|
#endif
|
||||||
|
|
||||||
display = wl_display_create();
|
display = wl_display_create();
|
||||||
assert(display);
|
assert(display);
|
||||||
client = wl_client_create(display, s[0]);
|
client = wl_client_create(display, s[0]);
|
||||||
|
|
@ -111,7 +118,13 @@ TEST(destroy_res_tst)
|
||||||
.notify = &destroy_notify
|
.notify = &destroy_notify
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||||
|
#else
|
||||||
|
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||||
|
assert(set_cloexec_or_close(s[0]) != -1);
|
||||||
|
assert(set_cloexec_or_close(s[1]) != -1);
|
||||||
|
#endif
|
||||||
display = wl_display_create();
|
display = wl_display_create();
|
||||||
assert(display);
|
assert(display);
|
||||||
client = wl_client_create(display, s[0]);
|
client = wl_client_create(display, s[0]);
|
||||||
|
|
@ -159,7 +172,13 @@ TEST(create_resource_with_same_id)
|
||||||
int s[2];
|
int s[2];
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||||
|
#else
|
||||||
|
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||||
|
assert(set_cloexec_or_close(s[0]) != -1);
|
||||||
|
assert(set_cloexec_or_close(s[1]) != -1);
|
||||||
|
#endif
|
||||||
display = wl_display_create();
|
display = wl_display_create();
|
||||||
assert(display);
|
assert(display);
|
||||||
client = wl_client_create(display, s[0]);
|
client = wl_client_create(display, s[0]);
|
||||||
|
|
@ -243,7 +262,13 @@ TEST(resource_destroy_iteration)
|
||||||
.notify = &resource_destroy_notify
|
.notify = &resource_destroy_notify
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||||
|
#else
|
||||||
|
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||||
|
assert(set_cloexec_or_close(s[0]) != -1);
|
||||||
|
assert(set_cloexec_or_close(s[1]) != -1);
|
||||||
|
#endif
|
||||||
display = wl_display_create();
|
display = wl_display_create();
|
||||||
assert(display);
|
assert(display);
|
||||||
client = wl_client_create(display, s[0]);
|
client = wl_client_create(display, s[0]);
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,30 @@ count_open_fds(void)
|
||||||
/* return the current number of entries */
|
/* return the current number of entries */
|
||||||
return size / sizeof(struct kinfo_file);
|
return size / sizeof(struct kinfo_file);
|
||||||
}
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <libproc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On Darwin, use libproc API to get fds of a PID
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
count_open_fds(void)
|
||||||
|
{
|
||||||
|
int buffer_size, buffer_used;
|
||||||
|
pid_t pid = getpid();
|
||||||
|
int nfds;
|
||||||
|
struct proc_fdinfo *fdinfo;
|
||||||
|
|
||||||
|
buffer_size = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, 0, 0);
|
||||||
|
fdinfo = malloc(buffer_size);
|
||||||
|
|
||||||
|
buffer_used = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdinfo, buffer_size);
|
||||||
|
assert(buffer_used > 0 && "proc_pidinfo PROC_PIDLISTFDS failed.");
|
||||||
|
|
||||||
|
nfds = buffer_used / PROC_PIDLISTFD_SIZE;
|
||||||
|
free(fdinfo);
|
||||||
|
return nfds;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
int
|
int
|
||||||
count_open_fds(void)
|
count_open_fds(void)
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,12 @@ static int timeouts_enabled = 1;
|
||||||
/* set to one if the output goes to the terminal */
|
/* set to one if the output goes to the terminal */
|
||||||
static int is_atty = 0;
|
static int is_atty = 0;
|
||||||
|
|
||||||
|
#if __APPLE__
|
||||||
|
extern const struct test __start_test_section __asm("section$start$__DATA$test_section");
|
||||||
|
extern const struct test __stop_test_section __asm("section$end$__DATA$test_section");
|
||||||
|
#else
|
||||||
extern const struct test __start_test_section, __stop_test_section;
|
extern const struct test __start_test_section, __stop_test_section;
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct test *
|
static const struct test *
|
||||||
find_test(const char *name)
|
find_test(const char *name)
|
||||||
|
|
@ -308,6 +313,23 @@ is_debugger_attached(void)
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
/* https://stackoverflow.com/a/2200786 */
|
||||||
|
static int
|
||||||
|
is_debugger_attached(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
|
||||||
|
struct kinfo_proc info;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
info.kp_proc.p_flag = 0;
|
||||||
|
ret = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
static int
|
static int
|
||||||
is_debugger_attached(void)
|
is_debugger_attached(void)
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,17 @@ struct test {
|
||||||
int must_fail;
|
int must_fail;
|
||||||
} __attribute__ ((aligned (16)));
|
} __attribute__ ((aligned (16)));
|
||||||
|
|
||||||
|
#if __APPLE__
|
||||||
|
#define TEST_SECTION "__DATA,test_section"
|
||||||
|
#else
|
||||||
|
#define TEST_SECTION "test_section"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TEST(name) \
|
#define TEST(name) \
|
||||||
static void name(void); \
|
static void name(void); \
|
||||||
\
|
\
|
||||||
const struct test test##name \
|
const struct test test##name \
|
||||||
__attribute__ ((used, section ("test_section"))) = { \
|
__attribute__ ((used, section (TEST_SECTION))) = { \
|
||||||
#name, name, 0 \
|
#name, name, 0 \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
|
|
@ -51,7 +57,7 @@ struct test {
|
||||||
static void name(void); \
|
static void name(void); \
|
||||||
\
|
\
|
||||||
const struct test test##name \
|
const struct test test##name \
|
||||||
__attribute__ ((used, section ("test_section"))) = { \
|
__attribute__ ((used, section (TEST_SECTION))) = { \
|
||||||
#name, name, 1 \
|
#name, name, 1 \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
|
|
@ -93,3 +99,28 @@ test_disable_coredumps(void);
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* For systems without SOCK_CLOEXEC */
|
||||||
|
#include <fcntl.h>
|
||||||
|
__attribute__((used))
|
||||||
|
static int
|
||||||
|
set_cloexec_or_close(int fd)
|
||||||
|
{
|
||||||
|
long flags;
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
flags = fcntl(fd, F_GETFD);
|
||||||
|
if (flags == -1)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
err:
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue