1 /* 2 * Copyright (c) 2015-2016 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 #include <assert.h> 33 #include <stdio.h> 34 #include <unistd.h> 35 #include <sys/select.h> 36 37 static fd_set set[0x1000000 / sizeof(fd_set)]; 38 39 int main(void) 40 { 41 int fds[2]; 42 struct { 43 struct timeval tv; 44 int pad[2]; 45 } tm_in = { 46 .tv = { .tv_sec = 0xc0de1, .tv_usec = 0xc0de2 }, 47 .pad = { 0xdeadbeef, 0xbadc0ded } 48 }, tm = tm_in; 49 50 if (pipe(fds)) 51 perror_msg_and_fail("pipe"); 52 53 /* 54 * Start with a nice simple select. 55 */ 56 FD_ZERO(set); 57 FD_SET(fds[0], set); 58 FD_SET(fds[1], set); 59 int rc = syscall(TEST_SYSCALL_NR, fds[1] + 1, set, set, set, NULL); 60 if (rc < 0) 61 perror_msg_and_skip(TEST_SYSCALL_STR); 62 assert(rc == 1); 63 printf("%s(%d, [%d %d], [%d %d], [%d %d], NULL) = 1 ()\n", 64 TEST_SYSCALL_STR, fds[1] + 1, fds[0], fds[1], 65 fds[0], fds[1], fds[0], fds[1]); 66 67 /* 68 * Another simple one, with a timeout. 69 */ 70 FD_SET(1, set); 71 FD_SET(2, set); 72 FD_SET(fds[0], set); 73 FD_SET(fds[1], set); 74 assert(syscall(TEST_SYSCALL_NR, fds[1] + 1, NULL, set, NULL, &tm.tv) == 3); 75 printf("%s(%d, NULL, [1 2 %d %d], NULL, {tv_sec=%lld, tv_usec=%lld})" 76 " = 3 (out [1 2 %d], left {tv_sec=%lld, tv_usec=%lld})\n", 77 TEST_SYSCALL_STR, fds[1] + 1, fds[0], fds[1], 78 (long long) tm_in.tv.tv_sec, (long long) tm_in.tv.tv_usec, 79 fds[1], 80 (long long) tm.tv.tv_sec, (long long) tm.tv.tv_usec); 81 82 /* 83 * Now the crash case that trinity found, negative nfds 84 * but with a pointer to a large chunk of valid memory. 85 */ 86 FD_ZERO(set); 87 FD_SET(fds[1],set); 88 assert(syscall(TEST_SYSCALL_NR, -1, NULL, set, NULL, NULL) == -1); 89 printf("%s(-1, NULL, %p, NULL, NULL) = -1 EINVAL (%m)\n", 90 TEST_SYSCALL_STR, set); 91 92 /* 93 * Another variant, with nfds exceeding FD_SETSIZE limit. 94 */ 95 FD_ZERO(set); 96 FD_SET(fds[0],set); 97 tm.tv.tv_sec = 0; 98 tm.tv.tv_usec = 123; 99 assert(syscall(TEST_SYSCALL_NR, FD_SETSIZE + 1, set, set + 1, NULL, &tm.tv) == 0); 100 printf("%s(%d, [%d], [], NULL, {tv_sec=0, tv_usec=123}) = 0 (Timeout)\n", 101 TEST_SYSCALL_STR, FD_SETSIZE + 1, fds[0]); 102 103 puts("+++ exited with 0 +++"); 104 return 0; 105 } 106