Home | History | Annotate | Download | only in tests-mx32
      1 /*
      2  * Check decoding of select/_newselect syscalls.
      3  *
      4  * Copyright (c) 2015-2018 Dmitry V. Levin <ldv (at) altlinux.org>
      5  * Copyright (c) 2015-2017 The strace developers.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 /*
     32  * Based on test by Dr. David Alan Gilbert <dave (at) treblig.org>
     33  */
     34 
     35 #include <errno.h>
     36 #include <limits.h>
     37 #include <stdint.h>
     38 #include <stdio.h>
     39 #include <string.h>
     40 #include <unistd.h>
     41 #include <sys/select.h>
     42 
     43 static const char *errstr;
     44 
     45 static long
     46 xselect(const kernel_ulong_t nfds,
     47 	const kernel_ulong_t rs,
     48 	const kernel_ulong_t ws,
     49 	const kernel_ulong_t es,
     50 	const kernel_ulong_t tv)
     51 #ifndef xselect
     52 {
     53 	long rc = syscall(TEST_SYSCALL_NR,
     54 			  F8ILL_KULONG_MASK | nfds, rs, ws, es, tv);
     55 	errstr = sprintrc(rc);
     56 	return rc;
     57 }
     58 #else
     59 	;
     60 #endif
     61 
     62 #define XSELECT(expected_, ...)						\
     63 	do {								\
     64 		long rc = xselect(__VA_ARGS__);				\
     65 		if (rc != (expected_))					\
     66 			perror_msg_and_fail(TEST_SYSCALL_STR		\
     67 					    ": expected %d"		\
     68 					    ", returned %ld",		\
     69 					    (expected_), rc);		\
     70 	} while (0)							\
     71 /* End of XSELECT definition. */
     72 
     73 int
     74 main(void)
     75 {
     76 #ifdef PATH_TRACING_FD
     77 	skip_if_unavailable("/proc/self/fd/");
     78 #endif
     79 
     80 	for (int i = 3; i < FD_SETSIZE; ++i) {
     81 #ifdef PATH_TRACING_FD
     82 		if (i == PATH_TRACING_FD)
     83 			continue;
     84 #endif
     85 		(void) close(i);
     86 	}
     87 
     88 	int fds[2];
     89 	if (pipe(fds))
     90 		perror_msg_and_fail("pipe");
     91 
     92 	static const int smallset_size = sizeof(kernel_ulong_t) * 8;
     93 	const int nfds = fds[1] + 1;
     94 	if (nfds > smallset_size)
     95 		error_msg_and_fail("nfds[%d] > smallset_size[%d]\n",
     96 				   nfds, smallset_size);
     97 
     98 	struct timeval tv_in = { 0, 123 };
     99 	struct timeval *const tv = tail_memdup(&tv_in, sizeof(tv_in));
    100 	const uintptr_t a_tv = (uintptr_t) tv;
    101 
    102 	TAIL_ALLOC_OBJECT_VAR_PTR(kernel_ulong_t, l_rs);
    103 	fd_set *const rs = (void *) l_rs;
    104 	const uintptr_t a_rs = (uintptr_t) rs;
    105 
    106 	TAIL_ALLOC_OBJECT_VAR_PTR(kernel_ulong_t, l_ws);
    107 	fd_set *const ws = (void *) l_ws;
    108 	const uintptr_t a_ws = (uintptr_t) ws;
    109 
    110 	TAIL_ALLOC_OBJECT_VAR_PTR(kernel_ulong_t, l_es);
    111 	fd_set *const es = (void *) l_es;
    112 	const uintptr_t a_es = (uintptr_t) es;
    113 
    114 	long rc;
    115 
    116 	/*
    117 	 * An equivalent of nanosleep.
    118 	 */
    119 	if (xselect(0, 0, 0, 0, a_tv)) {
    120 		if (errno == ENOSYS)
    121 			perror_msg_and_skip(TEST_SYSCALL_STR);
    122 		else
    123 			perror_msg_and_fail(TEST_SYSCALL_STR);
    124 	}
    125 #ifndef PATH_TRACING_FD
    126 	printf("%s(0, NULL, NULL, NULL, {tv_sec=%lld, tv_usec=%llu})"
    127 	       " = 0 (Timeout)\n",
    128 	       TEST_SYSCALL_STR, (long long) tv_in.tv_sec,
    129 	       zero_extend_signed_to_ull(tv_in.tv_usec));
    130 #endif
    131 
    132 	/* EFAULT on tv argument */
    133 	XSELECT(-1, 0, 0, 0, 0, a_tv + 1);
    134 #ifndef PATH_TRACING_FD
    135 	printf("%s(0, NULL, NULL, NULL, %#lx) = %s\n",
    136 	       TEST_SYSCALL_STR, (unsigned long) a_tv + 1, errstr);
    137 #endif
    138 
    139 	/*
    140 	 * Start with a nice simple select with the same set.
    141 	 */
    142 	for (int i = nfds; i <= smallset_size; ++i) {
    143 		*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
    144 		XSELECT(1, i, a_rs, a_rs, a_rs, 0);
    145 #ifndef PATH_TRACING_FD
    146 		printf("%s(%d, [%d %d], [%d %d], [%d %d], NULL) = 1 ()\n",
    147 		       TEST_SYSCALL_STR, i, fds[0], fds[1],
    148 		       fds[0], fds[1], fds[0], fds[1]);
    149 #else
    150 		*l_rs = (1UL << fds[0]) | (1UL << fds[1]) |
    151 			(1UL << PATH_TRACING_FD);
    152 		XSELECT(i > PATH_TRACING_FD ? 3 : 1, i, a_rs, a_rs, a_rs, 0);
    153 		if (i > PATH_TRACING_FD) {
    154 			printf("%s(%d, [%d %d %d], [%d %d %d], [%d %d %d]"
    155 			       ", NULL) = 3 ()\n",
    156 			       TEST_SYSCALL_STR, i,
    157 			       fds[0], fds[1], PATH_TRACING_FD,
    158 			       fds[0], fds[1], PATH_TRACING_FD,
    159 			       fds[0], fds[1], PATH_TRACING_FD);
    160 		}
    161 #endif
    162 	}
    163 
    164 	/*
    165 	 * Odd timeout.
    166 	 */
    167 	*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
    168 	tv_in.tv_sec = 0xdeadbeefU;
    169 	tv_in.tv_usec = 0xfacefeedU;
    170 	memcpy(tv, &tv_in, sizeof(tv_in));
    171 	rc = xselect(nfds, a_rs, a_rs, a_rs, a_tv);
    172 	if (rc < 0) {
    173 #ifndef PATH_TRACING_FD
    174 		printf("%s(%d, [%d %d], [%d %d], [%d %d]"
    175 		       ", {tv_sec=%lld, tv_usec=%llu}) = %s\n",
    176 		       TEST_SYSCALL_STR, nfds, fds[0], fds[1],
    177 		       fds[0], fds[1], fds[0], fds[1],
    178 		       (long long) tv_in.tv_sec,
    179 		       zero_extend_signed_to_ull(tv_in.tv_usec),
    180 		       errstr);
    181 #endif /* !PATH_TRACING_FD */
    182 	} else {
    183 #ifndef PATH_TRACING_FD
    184 		printf("%s(%d, [%d %d], [%d %d], [%d %d]"
    185 		       ", {tv_sec=%lld, tv_usec=%llu}) = %ld"
    186 		       " (left {tv_sec=%lld, tv_usec=%llu})\n",
    187 		       TEST_SYSCALL_STR, nfds, fds[0], fds[1],
    188 		       fds[0], fds[1], fds[0], fds[1],
    189 		       (long long) tv_in.tv_sec,
    190 		       zero_extend_signed_to_ull(tv_in.tv_usec),
    191 		       rc, (long long) tv->tv_sec,
    192 		       zero_extend_signed_to_ull(tv->tv_usec));
    193 #endif /* !PATH_TRACING_FD */
    194 	}
    195 
    196 	/*
    197 	 * Very odd timeout.
    198 	 */
    199 	*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
    200 	tv_in.tv_sec = (time_t) 0xcafef00ddeadbeefLL;
    201 	tv_in.tv_usec = (suseconds_t) 0xbadc0dedfacefeedLL;
    202 	memcpy(tv, &tv_in, sizeof(tv_in));
    203 	rc = xselect(nfds, a_rs, a_rs, a_rs, a_tv);
    204 	if (rc < 0) {
    205 #ifndef PATH_TRACING_FD
    206 		printf("%s(%d, [%d %d], [%d %d], [%d %d]"
    207 		       ", {tv_sec=%lld, tv_usec=%llu}) = %s\n",
    208 		       TEST_SYSCALL_STR, nfds, fds[0], fds[1],
    209 		       fds[0], fds[1], fds[0], fds[1],
    210 		       (long long) tv_in.tv_sec,
    211 		       zero_extend_signed_to_ull(tv_in.tv_usec),
    212 		       errstr);
    213 #endif /* PATH_TRACING_FD */
    214 	} else {
    215 #ifndef PATH_TRACING_FD
    216 		printf("%s(%d, [%d %d], [%d %d], [%d %d]"
    217 		       ", {tv_sec=%lld, tv_usec=%llu}) = %ld"
    218 		       " (left {tv_sec=%lld, tv_usec=%llu})\n",
    219 		       TEST_SYSCALL_STR, nfds, fds[0], fds[1],
    220 		       fds[0], fds[1], fds[0], fds[1],
    221 		       (long long) tv_in.tv_sec,
    222 		       zero_extend_signed_to_ull(tv_in.tv_usec),
    223 		       rc, (long long) tv->tv_sec,
    224 		       zero_extend_signed_to_ull(tv->tv_usec));
    225 #endif /* PATH_TRACING_FD */
    226 	}
    227 
    228 	/*
    229 	 * Another simple one, with a timeout.
    230 	 */
    231 	for (int i = nfds; i <= smallset_size; ++i) {
    232 		*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
    233 		*l_ws = (1UL << 1) | (1UL << 2) |
    234 			(1UL << fds[0]) | (1UL << fds[1]);
    235 		*l_es = 0;
    236 		tv_in.tv_sec = 0xc0de1;
    237 		tv_in.tv_usec = 0xc0de2;
    238 		memcpy(tv, &tv_in, sizeof(tv_in));
    239 		XSELECT(3, i, a_rs, a_ws, a_es, a_tv);
    240 #ifndef PATH_TRACING_FD
    241 		printf("%s(%d, [%d %d], [%d %d %d %d], []"
    242 		       ", {tv_sec=%lld, tv_usec=%llu}) = 3 (out [1 2 %d]"
    243 		       ", left {tv_sec=%lld, tv_usec=%llu})\n",
    244 		       TEST_SYSCALL_STR, i, fds[0], fds[1],
    245 		       1, 2, fds[0], fds[1],
    246 		       (long long) tv_in.tv_sec,
    247 		       zero_extend_signed_to_ull(tv_in.tv_usec),
    248 		       fds[1],
    249 		       (long long) tv->tv_sec,
    250 		       zero_extend_signed_to_ull(tv->tv_usec));
    251 #else
    252 		*l_rs = (1UL << fds[0]) | (1UL << fds[1]) |
    253 			(1UL << PATH_TRACING_FD);
    254 		*l_ws = (1UL << 1) | (1UL << 2) |
    255 			(1UL << fds[0]) | (1UL << fds[1]);
    256 		tv_in.tv_sec = 0xc0de1;
    257 		tv_in.tv_usec = 0xc0de2;
    258 		memcpy(tv, &tv_in, sizeof(tv_in));
    259 		XSELECT(3 + (i > PATH_TRACING_FD), i, a_rs, a_ws, a_es, a_tv);
    260 		if (i > PATH_TRACING_FD) {
    261 			printf("%s(%d, [%d %d %d], [%d %d %d %d], []"
    262 			       ", {tv_sec=%lld, tv_usec=%llu})"
    263 			       " = 4 (in [%d], out [1 2 %d]"
    264 			       ", left {tv_sec=%lld, tv_usec=%llu})\n",
    265 			       TEST_SYSCALL_STR, i,
    266 			       fds[0], fds[1], PATH_TRACING_FD,
    267 			       1, 2, fds[0], fds[1],
    268 			       (long long) tv_in.tv_sec,
    269 			       zero_extend_signed_to_ull(tv_in.tv_usec),
    270 			       PATH_TRACING_FD, fds[1],
    271 			       (long long) tv->tv_sec,
    272 			       zero_extend_signed_to_ull(tv->tv_usec));
    273 		}
    274 
    275 		*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
    276 		*l_ws = (1UL << 1) | (1UL << 2) |
    277 			(1UL << fds[0]) | (1UL << fds[1]) |
    278 			(1UL << PATH_TRACING_FD);
    279 		tv_in.tv_sec = 0xc0de1;
    280 		tv_in.tv_usec = 0xc0de2;
    281 		memcpy(tv, &tv_in, sizeof(tv_in));
    282 		XSELECT(3 + (i > PATH_TRACING_FD), i, a_rs, a_ws, a_es, a_tv);
    283 		if (i > PATH_TRACING_FD) {
    284 			printf("%s(%d, [%d %d], [%d %d %d %d %d], []"
    285 			       ", {tv_sec=%lld, tv_usec=%llu})"
    286 			       " = 4 (out [1 2 %d %d]"
    287 			       ", left {tv_sec=%lld, tv_usec=%llu})\n",
    288 			       TEST_SYSCALL_STR, i,
    289 			       fds[0], fds[1],
    290 			       1, 2, fds[0], fds[1], PATH_TRACING_FD,
    291 			       (long long) tv_in.tv_sec,
    292 			       zero_extend_signed_to_ull(tv_in.tv_usec),
    293 			       fds[1], PATH_TRACING_FD,
    294 			       (long long) tv->tv_sec,
    295 			       zero_extend_signed_to_ull(tv->tv_usec));
    296 		}
    297 
    298 		*l_rs = (1UL << fds[0]) | (1UL << fds[1]);
    299 		*l_ws = (1UL << 1) | (1UL << 2) |
    300 			(1UL << fds[0]) | (1UL << fds[1]);
    301 		*l_es = (1UL << PATH_TRACING_FD);
    302 		tv_in.tv_sec = 0xc0de1;
    303 		tv_in.tv_usec = 0xc0de2;
    304 		memcpy(tv, &tv_in, sizeof(tv_in));
    305 		XSELECT(3, i, a_rs, a_ws, a_es, a_tv);
    306 		if (i > PATH_TRACING_FD) {
    307 		printf("%s(%d, [%d %d], [%d %d %d %d], [%d]"
    308 		       ", {tv_sec=%lld, tv_usec=%llu}) = 3 (out [1 2 %d]"
    309 		       ", left {tv_sec=%lld, tv_usec=%llu})\n",
    310 		       TEST_SYSCALL_STR, i,
    311 		       fds[0], fds[1],
    312 		       1, 2, fds[0], fds[1], PATH_TRACING_FD,
    313 		       (long long) tv_in.tv_sec,
    314 		       zero_extend_signed_to_ull(tv_in.tv_usec),
    315 		       fds[1],
    316 		       (long long) tv->tv_sec,
    317 		       zero_extend_signed_to_ull(tv->tv_usec));
    318 		}
    319 
    320 #endif /* PATH_TRACING_FD */
    321 	}
    322 
    323 	/*
    324 	 * Now the crash case that trinity found, negative nfds
    325 	 * but with a pointer to a large chunk of valid memory.
    326 	 */
    327 	static fd_set set[0x1000000 / sizeof(fd_set)];
    328 	FD_SET(fds[1], set);
    329 	XSELECT(-1, -1U, 0, (uintptr_t) set, 0, 0);
    330 #ifndef PATH_TRACING_FD
    331 	printf("%s(-1, NULL, %p, NULL, NULL) = %s\n",
    332 	       TEST_SYSCALL_STR, set, errstr);
    333 #endif
    334 
    335 	/*
    336 	 * Big sets, nfds exceeds FD_SETSIZE limit.
    337 	 */
    338 	const size_t big_size = sizeof(fd_set) + sizeof(long);
    339 	fd_set *const big_rs = tail_alloc(big_size);
    340 	const uintptr_t a_big_rs = (uintptr_t) big_rs;
    341 
    342 	fd_set *const big_ws = tail_alloc(big_size);
    343 	const uintptr_t a_big_ws = (uintptr_t) big_ws;
    344 
    345 	for (unsigned int i = FD_SETSIZE; i <= big_size * 8; ++i) {
    346 		memset(big_rs, 0, big_size);
    347 		memset(big_ws, 0, big_size);
    348 		FD_SET(fds[0], big_rs);
    349 		tv->tv_sec = 0;
    350 		tv->tv_usec = 10 + (i - FD_SETSIZE);
    351 		XSELECT(0, i, a_big_rs, a_big_ws, 0, a_tv);
    352 #ifndef PATH_TRACING_FD
    353 		printf("%s(%d, [%d], [], NULL, {tv_sec=0, tv_usec=%d})"
    354 		       " = 0 (Timeout)\n",
    355 		       TEST_SYSCALL_STR, i, fds[0], 10 + (i - FD_SETSIZE));
    356 #else
    357 		FD_SET(fds[0], big_rs);
    358 		FD_SET(PATH_TRACING_FD, big_rs);
    359 		tv->tv_sec = 0;
    360 		tv->tv_usec = 10 + (i - FD_SETSIZE);
    361 		XSELECT(1, i, a_big_rs, a_big_ws, 0, a_tv);
    362 		printf("%s(%d, [%d %d], [], NULL, {tv_sec=0, tv_usec=%d})"
    363 		       " = 1 (in [%d], left {tv_sec=0, tv_usec=%llu})\n",
    364 		       TEST_SYSCALL_STR, i, fds[0], PATH_TRACING_FD,
    365 		       10 + (i - FD_SETSIZE), PATH_TRACING_FD,
    366 		       zero_extend_signed_to_ull(tv->tv_usec));
    367 #endif /* PATH_TRACING_FD */
    368 	}
    369 
    370 	/*
    371 	 * Huge sets, nfds equals to INT_MAX.
    372 	 */
    373 	FD_SET(fds[0], set);
    374 	FD_SET(fds[1], set);
    375 	tv->tv_sec = 0;
    376 	tv->tv_usec = 123;
    377 	XSELECT(0, INT_MAX, (uintptr_t) set, (uintptr_t) &set[1],
    378 		(uintptr_t) &set[2], a_tv);
    379 #ifndef PATH_TRACING_FD
    380 	printf("%s(%d, [%d %d], [], [], {tv_sec=0, tv_usec=123})"
    381 	       " = 0 (Timeout)\n",
    382 	       TEST_SYSCALL_STR, INT_MAX, fds[0], fds[1]);
    383 #else
    384 	FD_SET(fds[0], set);
    385 	FD_SET(fds[1], set);
    386 	FD_SET(PATH_TRACING_FD, set);
    387 	tv->tv_sec = 0;
    388 	tv->tv_usec = 123;
    389 	XSELECT(1, INT_MAX, (uintptr_t) set, (uintptr_t) &set[1],
    390 		(uintptr_t) &set[2], a_tv);
    391 	printf("%s(%d, [%d %d %d], [], [], {tv_sec=0, tv_usec=123})"
    392 	       " = 1 (in [%d], left {tv_sec=0, tv_usec=%llu})\n",
    393 	       TEST_SYSCALL_STR, INT_MAX, fds[0], fds[1], PATH_TRACING_FD,
    394 	       PATH_TRACING_FD, zero_extend_signed_to_ull(tv->tv_usec));
    395 #endif /* PATH_TRACING_FD */
    396 
    397 	/*
    398 	 * Small sets, nfds exceeds FD_SETSIZE limit.
    399 	 * The kernel seems to be fine with it but strace cannot follow.
    400 	 */
    401 	*l_rs = (1UL << fds[0]) | (1UL << fds[1])
    402 #ifdef PATH_TRACING_FD
    403 		| (1UL << PATH_TRACING_FD)
    404 #endif
    405 		;
    406 	*l_ws = (1UL << fds[0]);
    407 	*l_es = (1UL << fds[0]) | (1UL << fds[1])
    408 #ifdef PATH_TRACING_FD
    409 		| (1UL << PATH_TRACING_FD)
    410 #endif
    411 		;
    412 	tv->tv_sec = 0;
    413 	tv->tv_usec = 123;
    414 	rc = xselect(FD_SETSIZE + 1, a_rs, a_ws, a_es, a_tv);
    415 	if (rc < 0) {
    416 #ifndef PATH_TRACING_FD
    417 		printf("%s(%d, %p, %p, %p, {tv_sec=0, tv_usec=123}) = %s\n",
    418 		       TEST_SYSCALL_STR, FD_SETSIZE + 1, rs, ws, es, errstr);
    419 #endif
    420 	} else {
    421 #ifndef PATH_TRACING_FD
    422 		printf("%s(%d, %p, %p, %p, {tv_sec=0, tv_usec=123})"
    423 		       " = 0 (Timeout)\n",
    424 		       TEST_SYSCALL_STR, FD_SETSIZE + 1, rs, ws, es);
    425 #endif
    426 	}
    427 
    428 	/*
    429 	 * Small sets, one of allocated descriptors exceeds smallset_size.
    430 	 */
    431 	if (dup2(fds[1], smallset_size) != smallset_size)
    432 		perror_msg_and_fail("dup2");
    433 #ifdef PATH_TRACING_FD
    434 	FD_SET(PATH_TRACING_FD, rs);
    435 	FD_SET(PATH_TRACING_FD, ws);
    436 	FD_SET(PATH_TRACING_FD, es);
    437 #endif
    438 	XSELECT(-1, smallset_size + 1, a_rs, a_ws, a_es, 0);
    439 #ifndef PATH_TRACING_FD
    440 	printf("%s(%d, %p, %p, %p, NULL) = %s\n",
    441 	       TEST_SYSCALL_STR, smallset_size + 1, rs, ws, es, errstr);
    442 #endif
    443 
    444 	/*
    445 	 * Small and big sets,
    446 	 * one of allocated descriptors exceeds smallset_size.
    447 	 */
    448 	memset(big_rs, 0, big_size);
    449 	FD_SET(fds[0], big_rs);
    450 	FD_SET(smallset_size, big_rs);
    451 	memset(big_ws, 0, big_size);
    452 	FD_SET(fds[1], big_ws);
    453 	FD_SET(smallset_size, big_ws);
    454 	XSELECT(-1, smallset_size + 1, a_big_rs, a_big_ws, a_es, 0);
    455 #ifndef PATH_TRACING_FD
    456 	printf("%s(%d, [%d %d], [%d %d], %p, NULL) = %s\n",
    457 	       TEST_SYSCALL_STR, smallset_size + 1,
    458 	       fds[0], smallset_size,
    459 	       fds[1], smallset_size,
    460 	       es, errstr);
    461 #endif /* !PATH_TRACING_FD */
    462 	XSELECT(-1, smallset_size + 1, a_es, a_big_ws, a_big_rs, 0);
    463 #ifndef PATH_TRACING_FD
    464 	printf("%s(%d, %p, [%d %d], [%d %d], NULL) = %s\n",
    465 	       TEST_SYSCALL_STR, smallset_size + 1,
    466 	       es,
    467 	       fds[1], smallset_size,
    468 	       fds[0], smallset_size,
    469 	       errstr);
    470 #endif /* !PATH_TRACING_FD */
    471 
    472 	puts("+++ exited with 0 +++");
    473 	return 0;
    474 }
    475