xref: /aosp_15_r20/external/wayland/tests/os-wrappers-test.c (revision 84e872a0dc482bffdb63672969dd03a827d67c73)
1*84e872a0SLloyd Pique /*
2*84e872a0SLloyd Pique  * Copyright © 2012 Collabora, Ltd.
3*84e872a0SLloyd Pique  * Copyright © 2012 Intel Corporation
4*84e872a0SLloyd Pique  *
5*84e872a0SLloyd Pique  * Permission is hereby granted, free of charge, to any person obtaining
6*84e872a0SLloyd Pique  * a copy of this software and associated documentation files (the
7*84e872a0SLloyd Pique  * "Software"), to deal in the Software without restriction, including
8*84e872a0SLloyd Pique  * without limitation the rights to use, copy, modify, merge, publish,
9*84e872a0SLloyd Pique  * distribute, sublicense, and/or sell copies of the Software, and to
10*84e872a0SLloyd Pique  * permit persons to whom the Software is furnished to do so, subject to
11*84e872a0SLloyd Pique  * the following conditions:
12*84e872a0SLloyd Pique  *
13*84e872a0SLloyd Pique  * The above copyright notice and this permission notice (including the
14*84e872a0SLloyd Pique  * next paragraph) shall be included in all copies or substantial
15*84e872a0SLloyd Pique  * portions of the Software.
16*84e872a0SLloyd Pique  *
17*84e872a0SLloyd Pique  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18*84e872a0SLloyd Pique  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19*84e872a0SLloyd Pique  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20*84e872a0SLloyd Pique  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21*84e872a0SLloyd Pique  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22*84e872a0SLloyd Pique  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23*84e872a0SLloyd Pique  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24*84e872a0SLloyd Pique  * SOFTWARE.
25*84e872a0SLloyd Pique  */
26*84e872a0SLloyd Pique #include "../config.h"
27*84e872a0SLloyd Pique 
28*84e872a0SLloyd Pique #define _GNU_SOURCE
29*84e872a0SLloyd Pique 
30*84e872a0SLloyd Pique #include <stdlib.h>
31*84e872a0SLloyd Pique #include <stdint.h>
32*84e872a0SLloyd Pique #include <assert.h>
33*84e872a0SLloyd Pique #include <sys/types.h>
34*84e872a0SLloyd Pique #include <sys/socket.h>
35*84e872a0SLloyd Pique #include <sys/stat.h>
36*84e872a0SLloyd Pique #include <unistd.h>
37*84e872a0SLloyd Pique #include <dlfcn.h>
38*84e872a0SLloyd Pique #include <errno.h>
39*84e872a0SLloyd Pique #include <stdarg.h>
40*84e872a0SLloyd Pique #include <fcntl.h>
41*84e872a0SLloyd Pique #include <stdio.h>
42*84e872a0SLloyd Pique #include <sys/epoll.h>
43*84e872a0SLloyd Pique 
44*84e872a0SLloyd Pique #include "wayland-private.h"
45*84e872a0SLloyd Pique #include "test-runner.h"
46*84e872a0SLloyd Pique #include "wayland-os.h"
47*84e872a0SLloyd Pique 
48*84e872a0SLloyd Pique static int fall_back;
49*84e872a0SLloyd Pique 
50*84e872a0SLloyd Pique /* Play nice with sanitizers
51*84e872a0SLloyd Pique  *
52*84e872a0SLloyd Pique  * Sanitizers need to intercept syscalls in the compiler run-time library. As
53*84e872a0SLloyd Pique  * this isn't a separate ELF object, the usual dlsym(RTLD_NEXT) approach won't
54*84e872a0SLloyd Pique  * work: there can only be one function named "socket" etc. To support this, the
55*84e872a0SLloyd Pique  * sanitizer library names its interceptors with the prefix __interceptor_ ("__"
56*84e872a0SLloyd Pique  * being reserved for the implementation) and then weakly aliases it to the real
57*84e872a0SLloyd Pique  * function. The functions we define below will override the weak alias, and we
58*84e872a0SLloyd Pique  * can call them by the __interceptor_ name directly. This allows the sanitizer
59*84e872a0SLloyd Pique  * to do its work before calling the next version of the function via dlsym.
60*84e872a0SLloyd Pique  *
61*84e872a0SLloyd Pique  * However! We also don't know which of these functions the sanitizer actually
62*84e872a0SLloyd Pique  * wants to override, so we have to declare our own weak symbols for
63*84e872a0SLloyd Pique  * __interceptor_ and check at run time if they linked to anything or not.
64*84e872a0SLloyd Pique */
65*84e872a0SLloyd Pique 
66*84e872a0SLloyd Pique #define DECL(ret_type, func, ...) \
67*84e872a0SLloyd Pique 	ret_type __interceptor_ ## func(__VA_ARGS__) __attribute__((weak)); \
68*84e872a0SLloyd Pique 	static ret_type (*real_ ## func)(__VA_ARGS__);			\
69*84e872a0SLloyd Pique 	static int wrapped_calls_ ## func;
70*84e872a0SLloyd Pique 
71*84e872a0SLloyd Pique #define REAL(func) (__interceptor_ ## func) ?				\
72*84e872a0SLloyd Pique 	__interceptor_ ## func :					\
73*84e872a0SLloyd Pique 	(__typeof__(&__interceptor_ ## func))dlsym(RTLD_NEXT, #func)
74*84e872a0SLloyd Pique 
75*84e872a0SLloyd Pique DECL(int, socket, int, int, int);
76*84e872a0SLloyd Pique DECL(int, fcntl, int, int, ...);
77*84e872a0SLloyd Pique DECL(ssize_t, recvmsg, int, struct msghdr *, int);
78*84e872a0SLloyd Pique DECL(int, epoll_create1, int);
79*84e872a0SLloyd Pique 
80*84e872a0SLloyd Pique static void
init_fallbacks(int do_fallbacks)81*84e872a0SLloyd Pique init_fallbacks(int do_fallbacks)
82*84e872a0SLloyd Pique {
83*84e872a0SLloyd Pique 	fall_back = do_fallbacks;
84*84e872a0SLloyd Pique 	real_socket = REAL(socket);
85*84e872a0SLloyd Pique 	real_fcntl = REAL(fcntl);
86*84e872a0SLloyd Pique 	real_recvmsg = REAL(recvmsg);
87*84e872a0SLloyd Pique 	real_epoll_create1 = REAL(epoll_create1);
88*84e872a0SLloyd Pique }
89*84e872a0SLloyd Pique 
90*84e872a0SLloyd Pique __attribute__ ((visibility("default"))) int
socket(int domain,int type,int protocol)91*84e872a0SLloyd Pique socket(int domain, int type, int protocol)
92*84e872a0SLloyd Pique {
93*84e872a0SLloyd Pique 	wrapped_calls_socket++;
94*84e872a0SLloyd Pique 
95*84e872a0SLloyd Pique 	if (fall_back && (type & SOCK_CLOEXEC)) {
96*84e872a0SLloyd Pique 		errno = EINVAL;
97*84e872a0SLloyd Pique 		return -1;
98*84e872a0SLloyd Pique 	}
99*84e872a0SLloyd Pique 
100*84e872a0SLloyd Pique 	return real_socket(domain, type, protocol);
101*84e872a0SLloyd Pique }
102*84e872a0SLloyd Pique 
103*84e872a0SLloyd Pique __attribute__ ((visibility("default"))) int
104*84e872a0SLloyd Pique (fcntl)(int fd, int cmd, ...)
105*84e872a0SLloyd Pique {
106*84e872a0SLloyd Pique 	va_list ap;
107*84e872a0SLloyd Pique 	int arg;
108*84e872a0SLloyd Pique 	int has_arg;
109*84e872a0SLloyd Pique 
110*84e872a0SLloyd Pique 	wrapped_calls_fcntl++;
111*84e872a0SLloyd Pique 
112*84e872a0SLloyd Pique 	if (fall_back && (cmd == F_DUPFD_CLOEXEC)) {
113*84e872a0SLloyd Pique 		errno = EINVAL;
114*84e872a0SLloyd Pique 		return -1;
115*84e872a0SLloyd Pique 	}
116*84e872a0SLloyd Pique 	switch (cmd) {
117*84e872a0SLloyd Pique 	case F_DUPFD_CLOEXEC:
118*84e872a0SLloyd Pique 	case F_DUPFD:
119*84e872a0SLloyd Pique 	case F_SETFD:
120*84e872a0SLloyd Pique 		va_start(ap, cmd);
121*84e872a0SLloyd Pique 		arg = va_arg(ap, int);
122*84e872a0SLloyd Pique 		has_arg = 1;
123*84e872a0SLloyd Pique 		va_end(ap);
124*84e872a0SLloyd Pique 		break;
125*84e872a0SLloyd Pique 	case F_GETFD:
126*84e872a0SLloyd Pique 		has_arg = 0;
127*84e872a0SLloyd Pique 		break;
128*84e872a0SLloyd Pique 	default:
129*84e872a0SLloyd Pique 		fprintf(stderr, "Unexpected fctnl cmd %d\n", cmd);
130*84e872a0SLloyd Pique 		abort();
131*84e872a0SLloyd Pique 	}
132*84e872a0SLloyd Pique 
133*84e872a0SLloyd Pique 	if (has_arg) {
134*84e872a0SLloyd Pique 		return real_fcntl(fd, cmd, arg);
135*84e872a0SLloyd Pique 	}
136*84e872a0SLloyd Pique 	return real_fcntl(fd, cmd);
137*84e872a0SLloyd Pique }
138*84e872a0SLloyd Pique 
139*84e872a0SLloyd Pique __attribute__ ((visibility("default"))) ssize_t
recvmsg(int sockfd,struct msghdr * msg,int flags)140*84e872a0SLloyd Pique recvmsg(int sockfd, struct msghdr *msg, int flags)
141*84e872a0SLloyd Pique {
142*84e872a0SLloyd Pique 	wrapped_calls_recvmsg++;
143*84e872a0SLloyd Pique 
144*84e872a0SLloyd Pique 	if (fall_back && (flags & MSG_CMSG_CLOEXEC)) {
145*84e872a0SLloyd Pique 		errno = EINVAL;
146*84e872a0SLloyd Pique 		return -1;
147*84e872a0SLloyd Pique 	}
148*84e872a0SLloyd Pique 
149*84e872a0SLloyd Pique 	return real_recvmsg(sockfd, msg, flags);
150*84e872a0SLloyd Pique }
151*84e872a0SLloyd Pique 
152*84e872a0SLloyd Pique __attribute__ ((visibility("default"))) int
epoll_create1(int flags)153*84e872a0SLloyd Pique epoll_create1(int flags)
154*84e872a0SLloyd Pique {
155*84e872a0SLloyd Pique 	wrapped_calls_epoll_create1++;
156*84e872a0SLloyd Pique 
157*84e872a0SLloyd Pique 	if (fall_back) {
158*84e872a0SLloyd Pique 		wrapped_calls_epoll_create1++; /* epoll_create() not wrapped */
159*84e872a0SLloyd Pique 		errno = EINVAL;
160*84e872a0SLloyd Pique 		return -1;
161*84e872a0SLloyd Pique 	}
162*84e872a0SLloyd Pique 
163*84e872a0SLloyd Pique 	return real_epoll_create1(flags);
164*84e872a0SLloyd Pique }
165*84e872a0SLloyd Pique 
166*84e872a0SLloyd Pique static void
do_os_wrappers_socket_cloexec(int n)167*84e872a0SLloyd Pique do_os_wrappers_socket_cloexec(int n)
168*84e872a0SLloyd Pique {
169*84e872a0SLloyd Pique 	int fd;
170*84e872a0SLloyd Pique 	int nr_fds;
171*84e872a0SLloyd Pique 
172*84e872a0SLloyd Pique 	nr_fds = count_open_fds();
173*84e872a0SLloyd Pique 
174*84e872a0SLloyd Pique 	/* simply create a socket that closes on exec */
175*84e872a0SLloyd Pique 	fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
176*84e872a0SLloyd Pique 	assert(fd >= 0);
177*84e872a0SLloyd Pique 
178*84e872a0SLloyd Pique 	/*
179*84e872a0SLloyd Pique 	 * Must have 2 calls if falling back, but must also allow
180*84e872a0SLloyd Pique 	 * falling back without a forced fallback.
181*84e872a0SLloyd Pique 	 */
182*84e872a0SLloyd Pique 	assert(wrapped_calls_socket > n);
183*84e872a0SLloyd Pique 
184*84e872a0SLloyd Pique 	exec_fd_leak_check(nr_fds);
185*84e872a0SLloyd Pique }
186*84e872a0SLloyd Pique 
TEST(os_wrappers_socket_cloexec)187*84e872a0SLloyd Pique TEST(os_wrappers_socket_cloexec)
188*84e872a0SLloyd Pique {
189*84e872a0SLloyd Pique 	/* normal case */
190*84e872a0SLloyd Pique 	init_fallbacks(0);
191*84e872a0SLloyd Pique 	do_os_wrappers_socket_cloexec(0);
192*84e872a0SLloyd Pique }
193*84e872a0SLloyd Pique 
TEST(os_wrappers_socket_cloexec_fallback)194*84e872a0SLloyd Pique TEST(os_wrappers_socket_cloexec_fallback)
195*84e872a0SLloyd Pique {
196*84e872a0SLloyd Pique 	/* forced fallback */
197*84e872a0SLloyd Pique 	init_fallbacks(1);
198*84e872a0SLloyd Pique 	do_os_wrappers_socket_cloexec(1);
199*84e872a0SLloyd Pique }
200*84e872a0SLloyd Pique 
201*84e872a0SLloyd Pique static void
do_os_wrappers_dupfd_cloexec(int n)202*84e872a0SLloyd Pique do_os_wrappers_dupfd_cloexec(int n)
203*84e872a0SLloyd Pique {
204*84e872a0SLloyd Pique 	int base_fd;
205*84e872a0SLloyd Pique 	int fd;
206*84e872a0SLloyd Pique 	int nr_fds;
207*84e872a0SLloyd Pique 
208*84e872a0SLloyd Pique 	nr_fds = count_open_fds();
209*84e872a0SLloyd Pique 
210*84e872a0SLloyd Pique 	base_fd = socket(PF_LOCAL, SOCK_STREAM, 0);
211*84e872a0SLloyd Pique 	assert(base_fd >= 0);
212*84e872a0SLloyd Pique 
213*84e872a0SLloyd Pique 	fd = wl_os_dupfd_cloexec(base_fd, 13);
214*84e872a0SLloyd Pique 	assert(fd >= 13);
215*84e872a0SLloyd Pique 
216*84e872a0SLloyd Pique 	close(base_fd);
217*84e872a0SLloyd Pique 
218*84e872a0SLloyd Pique 	/*
219*84e872a0SLloyd Pique 	 * Must have 4 calls if falling back, but must also allow
220*84e872a0SLloyd Pique 	 * falling back without a forced fallback.
221*84e872a0SLloyd Pique 	 */
222*84e872a0SLloyd Pique 	assert(wrapped_calls_fcntl > n);
223*84e872a0SLloyd Pique 
224*84e872a0SLloyd Pique 	exec_fd_leak_check(nr_fds);
225*84e872a0SLloyd Pique }
226*84e872a0SLloyd Pique 
TEST(os_wrappers_dupfd_cloexec)227*84e872a0SLloyd Pique TEST(os_wrappers_dupfd_cloexec)
228*84e872a0SLloyd Pique {
229*84e872a0SLloyd Pique 	init_fallbacks(0);
230*84e872a0SLloyd Pique 	do_os_wrappers_dupfd_cloexec(0);
231*84e872a0SLloyd Pique }
232*84e872a0SLloyd Pique 
TEST(os_wrappers_dupfd_cloexec_fallback)233*84e872a0SLloyd Pique TEST(os_wrappers_dupfd_cloexec_fallback)
234*84e872a0SLloyd Pique {
235*84e872a0SLloyd Pique 	init_fallbacks(1);
236*84e872a0SLloyd Pique 	do_os_wrappers_dupfd_cloexec(3);
237*84e872a0SLloyd Pique }
238*84e872a0SLloyd Pique 
239*84e872a0SLloyd Pique struct marshal_data {
240*84e872a0SLloyd Pique 	struct wl_connection *read_connection;
241*84e872a0SLloyd Pique 	struct wl_connection *write_connection;
242*84e872a0SLloyd Pique 	int s[2];
243*84e872a0SLloyd Pique 	uint32_t read_mask;
244*84e872a0SLloyd Pique 	uint32_t write_mask;
245*84e872a0SLloyd Pique 	union {
246*84e872a0SLloyd Pique 		int h[3];
247*84e872a0SLloyd Pique 	} value;
248*84e872a0SLloyd Pique 	int nr_fds_begin;
249*84e872a0SLloyd Pique 	int nr_fds_conn;
250*84e872a0SLloyd Pique 	int wrapped_calls;
251*84e872a0SLloyd Pique };
252*84e872a0SLloyd Pique 
253*84e872a0SLloyd Pique static void
setup_marshal_data(struct marshal_data * data)254*84e872a0SLloyd Pique setup_marshal_data(struct marshal_data *data)
255*84e872a0SLloyd Pique {
256*84e872a0SLloyd Pique 	assert(socketpair(AF_UNIX,
257*84e872a0SLloyd Pique 			  SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
258*84e872a0SLloyd Pique 
259*84e872a0SLloyd Pique 	data->read_connection = wl_connection_create(data->s[0]);
260*84e872a0SLloyd Pique 	assert(data->read_connection);
261*84e872a0SLloyd Pique 
262*84e872a0SLloyd Pique 	data->write_connection = wl_connection_create(data->s[1]);
263*84e872a0SLloyd Pique 	assert(data->write_connection);
264*84e872a0SLloyd Pique }
265*84e872a0SLloyd Pique 
266*84e872a0SLloyd Pique static void
marshal_demarshal(struct marshal_data * data,void (* func)(void),int size,const char * format,...)267*84e872a0SLloyd Pique marshal_demarshal(struct marshal_data *data,
268*84e872a0SLloyd Pique 		  void (*func)(void), int size, const char *format, ...)
269*84e872a0SLloyd Pique {
270*84e872a0SLloyd Pique 	struct wl_closure *closure;
271*84e872a0SLloyd Pique 	static const int opcode = 4444;
272*84e872a0SLloyd Pique 	static struct wl_object sender = { NULL, NULL, 1234 };
273*84e872a0SLloyd Pique 	struct wl_message message = { "test", format, NULL };
274*84e872a0SLloyd Pique 	struct wl_map objects;
275*84e872a0SLloyd Pique 	struct wl_object object = { NULL, &func, 1234 };
276*84e872a0SLloyd Pique 	va_list ap;
277*84e872a0SLloyd Pique 	uint32_t msg[1] = { 1234 };
278*84e872a0SLloyd Pique 
279*84e872a0SLloyd Pique 	va_start(ap, format);
280*84e872a0SLloyd Pique 	closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
281*84e872a0SLloyd Pique 	va_end(ap);
282*84e872a0SLloyd Pique 
283*84e872a0SLloyd Pique 	assert(closure);
284*84e872a0SLloyd Pique 	assert(wl_closure_send(closure, data->write_connection) == 0);
285*84e872a0SLloyd Pique 	wl_closure_destroy(closure);
286*84e872a0SLloyd Pique 	assert(wl_connection_flush(data->write_connection) == size);
287*84e872a0SLloyd Pique 
288*84e872a0SLloyd Pique 	assert(wl_connection_read(data->read_connection) == size);
289*84e872a0SLloyd Pique 
290*84e872a0SLloyd Pique 	wl_map_init(&objects, WL_MAP_SERVER_SIDE);
291*84e872a0SLloyd Pique 	object.id = msg[0];
292*84e872a0SLloyd Pique 	closure = wl_connection_demarshal(data->read_connection,
293*84e872a0SLloyd Pique 					  size, &objects, &message);
294*84e872a0SLloyd Pique 	assert(closure);
295*84e872a0SLloyd Pique 	wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, data);
296*84e872a0SLloyd Pique 	wl_closure_destroy(closure);
297*84e872a0SLloyd Pique }
298*84e872a0SLloyd Pique 
299*84e872a0SLloyd Pique static void
validate_recvmsg_h(struct marshal_data * data,struct wl_object * object,int fd1,int fd2,int fd3)300*84e872a0SLloyd Pique validate_recvmsg_h(struct marshal_data *data,
301*84e872a0SLloyd Pique 		   struct wl_object *object, int fd1, int fd2, int fd3)
302*84e872a0SLloyd Pique {
303*84e872a0SLloyd Pique 	struct stat buf1, buf2;
304*84e872a0SLloyd Pique 
305*84e872a0SLloyd Pique 	assert(fd1 >= 0);
306*84e872a0SLloyd Pique 	assert(fd2 >= 0);
307*84e872a0SLloyd Pique 	assert(fd3 >= 0);
308*84e872a0SLloyd Pique 
309*84e872a0SLloyd Pique 	assert(fd1 != data->value.h[0]);
310*84e872a0SLloyd Pique 	assert(fd2 != data->value.h[1]);
311*84e872a0SLloyd Pique 	assert(fd3 != data->value.h[2]);
312*84e872a0SLloyd Pique 
313*84e872a0SLloyd Pique 	assert(fstat(fd3, &buf1) == 0);
314*84e872a0SLloyd Pique 	assert(fstat(data->value.h[2], &buf2) == 0);
315*84e872a0SLloyd Pique 	assert(buf1.st_dev == buf2.st_dev);
316*84e872a0SLloyd Pique 	assert(buf1.st_ino == buf2.st_ino);
317*84e872a0SLloyd Pique 
318*84e872a0SLloyd Pique 	/* close the original file descriptors */
319*84e872a0SLloyd Pique 	close(data->value.h[0]);
320*84e872a0SLloyd Pique 	close(data->value.h[1]);
321*84e872a0SLloyd Pique 	close(data->value.h[2]);
322*84e872a0SLloyd Pique 
323*84e872a0SLloyd Pique 	/* the dup'd (received) fds should still be open */
324*84e872a0SLloyd Pique 	assert(count_open_fds() == data->nr_fds_conn + 3);
325*84e872a0SLloyd Pique 
326*84e872a0SLloyd Pique 	/*
327*84e872a0SLloyd Pique 	 * Must have 2 calls if falling back, but must also allow
328*84e872a0SLloyd Pique 	 * falling back without a forced fallback.
329*84e872a0SLloyd Pique 	 */
330*84e872a0SLloyd Pique 	assert(wrapped_calls_recvmsg > data->wrapped_calls);
331*84e872a0SLloyd Pique 
332*84e872a0SLloyd Pique 	if (data->wrapped_calls == 0 && wrapped_calls_recvmsg > 1)
333*84e872a0SLloyd Pique 		printf("recvmsg fell back unforced.\n");
334*84e872a0SLloyd Pique 
335*84e872a0SLloyd Pique 	/* all fds opened during the test in any way should be gone on exec */
336*84e872a0SLloyd Pique 	exec_fd_leak_check(data->nr_fds_begin);
337*84e872a0SLloyd Pique }
338*84e872a0SLloyd Pique 
339*84e872a0SLloyd Pique static void
do_os_wrappers_recvmsg_cloexec(int n)340*84e872a0SLloyd Pique do_os_wrappers_recvmsg_cloexec(int n)
341*84e872a0SLloyd Pique {
342*84e872a0SLloyd Pique 	struct marshal_data data;
343*84e872a0SLloyd Pique 
344*84e872a0SLloyd Pique 	data.nr_fds_begin = count_open_fds();
345*84e872a0SLloyd Pique #if HAVE_BROKEN_MSG_CMSG_CLOEXEC
346*84e872a0SLloyd Pique 	/* We call the fallback directly on FreeBSD versions with a broken
347*84e872a0SLloyd Pique 	 * MSG_CMSG_CLOEXEC, so we don't call the local recvmsg() wrapper. */
348*84e872a0SLloyd Pique 	data.wrapped_calls = 0;
349*84e872a0SLloyd Pique #else
350*84e872a0SLloyd Pique 	data.wrapped_calls = n;
351*84e872a0SLloyd Pique #endif
352*84e872a0SLloyd Pique 
353*84e872a0SLloyd Pique 	setup_marshal_data(&data);
354*84e872a0SLloyd Pique 	data.nr_fds_conn = count_open_fds();
355*84e872a0SLloyd Pique 
356*84e872a0SLloyd Pique 	assert(pipe(data.value.h) >= 0);
357*84e872a0SLloyd Pique 
358*84e872a0SLloyd Pique 	data.value.h[2] = open("/dev/zero", O_RDONLY);
359*84e872a0SLloyd Pique 	assert(data.value.h[2] >= 0);
360*84e872a0SLloyd Pique 
361*84e872a0SLloyd Pique 	marshal_demarshal(&data, (void *) validate_recvmsg_h,
362*84e872a0SLloyd Pique 			  8, "hhh", data.value.h[0], data.value.h[1],
363*84e872a0SLloyd Pique 			  data.value.h[2]);
364*84e872a0SLloyd Pique }
365*84e872a0SLloyd Pique 
TEST(os_wrappers_recvmsg_cloexec)366*84e872a0SLloyd Pique TEST(os_wrappers_recvmsg_cloexec)
367*84e872a0SLloyd Pique {
368*84e872a0SLloyd Pique 	init_fallbacks(0);
369*84e872a0SLloyd Pique 	do_os_wrappers_recvmsg_cloexec(0);
370*84e872a0SLloyd Pique }
371*84e872a0SLloyd Pique 
TEST(os_wrappers_recvmsg_cloexec_fallback)372*84e872a0SLloyd Pique TEST(os_wrappers_recvmsg_cloexec_fallback)
373*84e872a0SLloyd Pique {
374*84e872a0SLloyd Pique 	init_fallbacks(1);
375*84e872a0SLloyd Pique 	do_os_wrappers_recvmsg_cloexec(1);
376*84e872a0SLloyd Pique }
377*84e872a0SLloyd Pique 
378*84e872a0SLloyd Pique static void
do_os_wrappers_epoll_create_cloexec(int n)379*84e872a0SLloyd Pique do_os_wrappers_epoll_create_cloexec(int n)
380*84e872a0SLloyd Pique {
381*84e872a0SLloyd Pique 	int fd;
382*84e872a0SLloyd Pique 	int nr_fds;
383*84e872a0SLloyd Pique 
384*84e872a0SLloyd Pique 	nr_fds = count_open_fds();
385*84e872a0SLloyd Pique 
386*84e872a0SLloyd Pique 	fd = wl_os_epoll_create_cloexec();
387*84e872a0SLloyd Pique 	assert(fd >= 0);
388*84e872a0SLloyd Pique 
389*84e872a0SLloyd Pique #ifdef EPOLL_CLOEXEC
390*84e872a0SLloyd Pique 	assert(wrapped_calls_epoll_create1 == n);
391*84e872a0SLloyd Pique #else
392*84e872a0SLloyd Pique 	printf("No epoll_create1.\n");
393*84e872a0SLloyd Pique #endif
394*84e872a0SLloyd Pique 
395*84e872a0SLloyd Pique 	exec_fd_leak_check(nr_fds);
396*84e872a0SLloyd Pique }
397*84e872a0SLloyd Pique 
TEST(os_wrappers_epoll_create_cloexec)398*84e872a0SLloyd Pique TEST(os_wrappers_epoll_create_cloexec)
399*84e872a0SLloyd Pique {
400*84e872a0SLloyd Pique 	init_fallbacks(0);
401*84e872a0SLloyd Pique 	do_os_wrappers_epoll_create_cloexec(1);
402*84e872a0SLloyd Pique }
403*84e872a0SLloyd Pique 
TEST(os_wrappers_epoll_create_cloexec_fallback)404*84e872a0SLloyd Pique TEST(os_wrappers_epoll_create_cloexec_fallback)
405*84e872a0SLloyd Pique {
406*84e872a0SLloyd Pique 	init_fallbacks(1);
407*84e872a0SLloyd Pique 	do_os_wrappers_epoll_create_cloexec(2);
408*84e872a0SLloyd Pique }
409*84e872a0SLloyd Pique 
410*84e872a0SLloyd Pique /* FIXME: add tests for wl_os_accept_cloexec() */
411