1 /* 2 * Check decoding of ppoll syscall. 3 * 4 * Copyright (c) 2015-2018 Dmitry V. Levin <ldv (at) altlinux.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "tests.h" 31 #include <asm/unistd.h> 32 33 #ifdef __NR_ppoll 34 35 # include <errno.h> 36 # include <poll.h> 37 # include <signal.h> 38 # include <stdio.h> 39 # include <string.h> 40 # include <unistd.h> 41 42 static const char *errstr; 43 44 static long 45 sys_ppoll(const kernel_ulong_t ufds, 46 const kernel_ulong_t nfds, 47 const kernel_ulong_t tsp, 48 const kernel_ulong_t sigmask, 49 const kernel_ulong_t sigsetsize) 50 { 51 long rc = syscall(__NR_ppoll, ufds, nfds, tsp, sigmask, sigsetsize); 52 errstr = sprintrc(rc); 53 return rc; 54 } 55 56 int 57 main(void) 58 { 59 # ifdef PATH_TRACING_FD 60 skip_if_unavailable("/proc/self/fd/"); 61 # endif 62 63 static const kernel_ulong_t bogus_nfds = 64 (kernel_ulong_t) 0xdeadbeeffacefeedULL; 65 static const kernel_ulong_t bogus_sigsetsize = 66 (kernel_ulong_t) 0xdeadbeefbadc0dedULL; 67 static const char *const POLLWRNORM_str = 68 (POLLWRNORM == POLLOUT) ? "" : "|POLLWRNORM"; 69 static const char *const USR2_CHLD_str = 70 (SIGUSR2 < SIGCHLD) ? "USR2 CHLD" : "CHLD USR2"; 71 void *const efault = tail_alloc(1024) + 1024; 72 TAIL_ALLOC_OBJECT_CONST_PTR(struct timespec, ts); 73 const unsigned int sigset_size = get_sigset_size(); 74 void *const sigmask = tail_alloc(sigset_size); 75 struct pollfd *fds; 76 sigset_t mask; 77 int pipe_fd[4]; 78 long rc; 79 80 sys_ppoll(0, bogus_nfds, 0, 0, bogus_sigsetsize); 81 if (ENOSYS == errno) 82 perror_msg_and_skip("ppoll"); 83 # ifndef PATH_TRACING_FD 84 printf("ppoll(NULL, %u, NULL, NULL, %llu) = %s\n", 85 (unsigned) bogus_nfds, (unsigned long long) bogus_sigsetsize, 86 errstr); 87 # endif 88 89 sys_ppoll((unsigned long) efault, 42, (unsigned long) efault + 8, 90 (unsigned long) efault + 16, sigset_size); 91 # ifndef PATH_TRACING_FD 92 printf("ppoll(%p, %u, %p, %p, %u) = %s\n", 93 efault, 42, efault + 8, efault + 16, sigset_size, errstr); 94 # endif 95 96 ts->tv_sec = 0xdeadbeefU; 97 ts->tv_nsec = 0xfacefeedU; 98 sys_ppoll(0, 0, (unsigned long) ts, 0, sigset_size); 99 # ifndef PATH_TRACING_FD 100 printf("ppoll(NULL, 0, {tv_sec=%lld, tv_nsec=%llu}, NULL, %u) = %s\n", 101 (long long) ts->tv_sec, zero_extend_signed_to_ull(ts->tv_nsec), 102 sigset_size, errstr); 103 # endif 104 105 ts->tv_sec = (time_t) 0xcafef00ddeadbeefLL; 106 ts->tv_nsec = (long) 0xbadc0dedfacefeedL; 107 sys_ppoll(0, 0, (unsigned long) ts, 0, sigset_size); 108 # ifndef PATH_TRACING_FD 109 printf("ppoll(NULL, 0, {tv_sec=%lld, tv_nsec=%llu}, NULL, %u) = %s\n", 110 (long long) ts->tv_sec, zero_extend_signed_to_ull(ts->tv_nsec), 111 sigset_size, errstr); 112 # endif 113 114 if (pipe(pipe_fd) || pipe(pipe_fd + 2)) 115 perror_msg_and_fail("pipe"); 116 117 ts->tv_sec = 42; 118 ts->tv_nsec = 999999999; 119 120 const struct pollfd fds1[] = { 121 { .fd = pipe_fd[0], .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND }, 122 { .fd = pipe_fd[1], .events = POLLOUT | POLLWRNORM | POLLWRBAND }, 123 { .fd = pipe_fd[2], .events = POLLIN | POLLPRI }, 124 { .fd = pipe_fd[3], .events = POLLOUT } 125 }; 126 fds = efault - sizeof(fds1); 127 memcpy(fds, fds1, sizeof(fds1)); 128 129 sigemptyset(&mask); 130 sigaddset(&mask, SIGUSR2); 131 sigaddset(&mask, SIGCHLD); 132 memcpy(sigmask, &mask, sigset_size); 133 134 rc = sys_ppoll((unsigned long) fds, 135 F8ILL_KULONG_MASK | ARRAY_SIZE(fds1), (unsigned long) ts, 136 (unsigned long) sigmask, sigset_size); 137 if (rc != 2) 138 perror_msg_and_fail("ppoll 1"); 139 # ifndef PATH_TRACING_FD 140 printf("ppoll([{fd=%d, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}" 141 ", {fd=%d, events=POLLOUT%s|POLLWRBAND}" 142 # if VERBOSE 143 ", {fd=%d, events=POLLIN|POLLPRI}, {fd=%d, events=POLLOUT}]" 144 # else 145 ", ...]" 146 # endif 147 ", %u, {tv_sec=42, tv_nsec=999999999}, [%s], %u) = %ld" 148 " ([{fd=%d, revents=POLLOUT%s}, {fd=%d, revents=POLLOUT}]" 149 ", left {tv_sec=%u, tv_nsec=%u})\n", 150 pipe_fd[0], pipe_fd[1], POLLWRNORM_str, 151 # if VERBOSE 152 pipe_fd[2], pipe_fd[3], 153 # endif 154 (unsigned int) ARRAY_SIZE(fds1), USR2_CHLD_str, 155 (unsigned int) sigset_size, rc, pipe_fd[1], POLLWRNORM_str, 156 pipe_fd[3], (unsigned int) ts->tv_sec, 157 (unsigned int) ts->tv_nsec); 158 # endif /* !PATH_TRACING_FD */ 159 160 # ifdef PATH_TRACING_FD 161 ts->tv_sec = 123; 162 ts->tv_nsec = 987654321; 163 fds[3].fd = PATH_TRACING_FD; 164 165 rc = sys_ppoll((unsigned long) fds, 166 F8ILL_KULONG_MASK | ARRAY_SIZE(fds1), (unsigned long) ts, 167 (unsigned long) sigmask, sigset_size); 168 if (rc != 2) 169 perror_msg_and_fail("ppoll -P"); 170 printf("ppoll([{fd=%d, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}" 171 ", {fd=%d, events=POLLOUT%s|POLLWRBAND}" 172 # if VERBOSE 173 ", {fd=%d, events=POLLIN|POLLPRI}, {fd=%d, events=POLLOUT}]" 174 # else 175 ", ...]" 176 # endif 177 ", %u, {tv_sec=123, tv_nsec=987654321}, [%s], %u) = %ld" 178 " ([{fd=%d, revents=POLLOUT%s}, {fd=%d, revents=POLLOUT}]" 179 ", left {tv_sec=%u, tv_nsec=%u})\n", 180 pipe_fd[0], pipe_fd[1], POLLWRNORM_str, 181 # if VERBOSE 182 pipe_fd[2], PATH_TRACING_FD, 183 # endif 184 (unsigned int) ARRAY_SIZE(fds1), USR2_CHLD_str, 185 (unsigned int) sigset_size, rc, pipe_fd[1], POLLWRNORM_str, 186 PATH_TRACING_FD, (unsigned int) ts->tv_sec, 187 (unsigned int) ts->tv_nsec); 188 # endif /* PATH_TRACING_FD */ 189 190 ts->tv_sec = 0; 191 ts->tv_nsec = 999; 192 const struct pollfd fds2[] = { 193 { .fd = pipe_fd[1], .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND }, 194 { .fd = pipe_fd[0], .events = POLLOUT | POLLWRNORM | POLLWRBAND } 195 }; 196 fds = efault - sizeof(fds2); 197 memcpy(fds, fds2, sizeof(fds2)); 198 199 memset(&mask, -1, sizeof(mask)); 200 sigdelset(&mask, SIGHUP); 201 sigdelset(&mask, SIGKILL); 202 sigdelset(&mask, SIGSTOP); 203 memcpy(sigmask, &mask, sigset_size); 204 205 rc = sys_ppoll((unsigned long) fds, 206 F8ILL_KULONG_MASK | ARRAY_SIZE(fds2), (unsigned long) ts, 207 (unsigned long) sigmask, sigset_size); 208 if (rc != 0) 209 perror_msg_and_fail("ppoll 2"); 210 # ifndef PATH_TRACING_FD 211 printf("ppoll([{fd=%d, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}" 212 ", {fd=%d, events=POLLOUT%s|POLLWRBAND}], %u" 213 ", {tv_sec=0, tv_nsec=999}, ~[HUP KILL STOP], %u)" 214 " = %ld (Timeout)\n", 215 pipe_fd[1], pipe_fd[0], POLLWRNORM_str, 216 (unsigned) ARRAY_SIZE(fds2), sigset_size, rc); 217 # endif /* !PATH_TRACING_FD */ 218 219 if (F8ILL_KULONG_SUPPORTED) { 220 sys_ppoll(f8ill_ptr_to_kulong(fds), ARRAY_SIZE(fds2), 221 f8ill_ptr_to_kulong(ts), f8ill_ptr_to_kulong(sigmask), 222 sigset_size); 223 # ifndef PATH_TRACING_FD 224 printf("ppoll(%#llx, %u, %#llx, %#llx, %u) = %s\n", 225 (unsigned long long) f8ill_ptr_to_kulong(fds), 226 (unsigned) ARRAY_SIZE(fds2), 227 (unsigned long long) f8ill_ptr_to_kulong(ts), 228 (unsigned long long) f8ill_ptr_to_kulong(sigmask), 229 (unsigned) sigset_size, errstr); 230 # endif /* !PATH_TRACING_FD */ 231 } 232 233 puts("+++ exited with 0 +++"); 234 return 0; 235 } 236 237 #else 238 239 SKIP_MAIN_UNDEFINED("__NR_ppoll") 240 241 #endif 242