1 /* 2 * Copyright (c) 2015 Dmitry V. Levin <ldv (at) altlinux.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * Based on test by Dr. David Alan Gilbert <dave (at) treblig.org> 30 */ 31 32 #ifdef TEST_SYSCALL_NAME 33 34 # include <stdio.h> 35 # include <unistd.h> 36 # include <sys/select.h> 37 38 # define TEST_SYSCALL_NR nrify(TEST_SYSCALL_NAME) 39 # define nrify(arg) nrify_(arg) 40 # define nrify_(arg) __NR_ ## arg 41 42 # define TEST_SYSCALL_STR stringify(TEST_SYSCALL_NAME) 43 # define stringify(arg) stringify_(arg) 44 # define stringify_(arg) #arg 45 46 static fd_set set[0x1000000 / sizeof(fd_set)]; 47 48 int main(void) 49 { 50 int fds[2]; 51 struct { 52 struct timeval tv; 53 int pad[2]; 54 } tm_in = { 55 .tv = { .tv_sec = 0xc0de1, .tv_usec = 0xc0de2 }, 56 .pad = { 0xdeadbeef, 0xbadc0ded } 57 }, tm = tm_in; 58 59 if (pipe(fds)) 60 return 77; 61 62 /* 63 * Start with a nice simple select. 64 */ 65 FD_ZERO(set); 66 FD_SET(fds[0], set); 67 FD_SET(fds[1], set); 68 if (syscall(TEST_SYSCALL_NR, fds[1] + 1, set, set, set, NULL) != 1) 69 return 77; 70 printf("%s(%d, [%d %d], [%d %d], [%d %d], NULL) = 1 ()\n", 71 TEST_SYSCALL_STR, fds[1] + 1, fds[0], fds[1], 72 fds[0], fds[1], fds[0], fds[1]); 73 74 /* 75 * Another simple one, with a timeout. 76 */ 77 FD_SET(1, set); 78 FD_SET(2, set); 79 FD_SET(fds[0], set); 80 FD_SET(fds[1], set); 81 if (syscall(TEST_SYSCALL_NR, fds[1] + 1, NULL, set, NULL, &tm.tv) != 3) 82 return 77; 83 printf("%s(%d, NULL, [1 2 %d %d], NULL, {%lld, %lld})" 84 " = 3 (out [1 2 %d], left {%lld, %lld})\n", 85 TEST_SYSCALL_STR, fds[1] + 1, fds[0], fds[1], 86 (long long) tm_in.tv.tv_sec, (long long) tm_in.tv.tv_usec, 87 fds[1], 88 (long long) tm.tv.tv_sec, (long long) tm.tv.tv_usec); 89 90 /* 91 * Now the crash case that trinity found, negative nfds 92 * but with a pointer to a large chunk of valid memory. 93 */ 94 FD_ZERO(set); 95 FD_SET(fds[1],set); 96 if (syscall(TEST_SYSCALL_NR, -1, NULL, set, NULL, NULL) != -1) 97 return 77; 98 printf("%s(-1, NULL, %p, NULL, NULL) = -1 EINVAL (%m)\n", 99 TEST_SYSCALL_STR, set); 100 101 /* 102 * Another variant, with nfds exceeding FD_SETSIZE limit. 103 */ 104 FD_ZERO(set); 105 FD_SET(fds[0],set); 106 tm.tv.tv_sec = 0; 107 tm.tv.tv_usec = 123; 108 if (syscall(TEST_SYSCALL_NR, FD_SETSIZE + 1, set, set + 1, NULL, &tm.tv)) 109 return 77; 110 printf("%s(%d, [%d], [], NULL, {0, 123}) = 0 (Timeout)\n", 111 TEST_SYSCALL_STR, FD_SETSIZE + 1, fds[0]); 112 113 puts("+++ exited with 0 +++"); 114 return 0; 115 } 116 117 #else 118 119 int 120 main(void) 121 { 122 return 77; 123 } 124 125 #endif 126