1/* 2 * Check decoding of ppoll syscall. 3 * 4 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@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 42static const char *errstr; 43 44static long 45sys_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 56int 57main(void) 58{ 59 static const kernel_ulong_t bogus_nfds = 60 (kernel_ulong_t) 0xdeadbeeffacefeedULL; 61 static const kernel_ulong_t bogus_sigsetsize = 62 (kernel_ulong_t) 0xdeadbeefbadc0dedULL; 63 static const char *const POLLWRNORM_str = 64 (POLLWRNORM == POLLOUT) ? "" : "|POLLWRNORM"; 65 static const char *const USR2_CHLD_str = 66 (SIGUSR2 < SIGCHLD) ? "USR2 CHLD" : "CHLD USR2"; 67 void *const efault = tail_alloc(1024) + 1024; 68 TAIL_ALLOC_OBJECT_CONST_PTR(struct timespec, ts); 69 const unsigned int sigset_size = get_sigset_size(); 70 void *const sigmask = tail_alloc(sigset_size); 71 struct pollfd *fds; 72 sigset_t mask; 73 int pipe_fd[4]; 74 long rc; 75 76 sys_ppoll(0, bogus_nfds, 0, 0, bogus_sigsetsize); 77 if (ENOSYS == errno) 78 perror_msg_and_skip("ppoll"); 79 printf("ppoll(NULL, %u, NULL, NULL, %llu) = %s\n", 80 (unsigned) bogus_nfds, (unsigned long long) bogus_sigsetsize, 81 errstr); 82 83 sys_ppoll((unsigned long) efault, 42, (unsigned long) efault + 8, 84 (unsigned long) efault + 16, sigset_size); 85 printf("ppoll(%p, %u, %p, %p, %u) = %s\n", 86 efault, 42, efault + 8, efault + 16, sigset_size, errstr); 87 88 ts->tv_sec = 0xdeadbeefU; 89 ts->tv_nsec = 0xfacefeedU; 90 sys_ppoll(0, 0, (unsigned long) ts, 0, sigset_size); 91 printf("ppoll(NULL, 0, {tv_sec=%lld, tv_nsec=%llu}, NULL, %u) = %s\n", 92 (long long) ts->tv_sec, zero_extend_signed_to_ull(ts->tv_nsec), 93 sigset_size, errstr); 94 95 ts->tv_sec = (time_t) 0xcafef00ddeadbeefLL; 96 ts->tv_nsec = (long) 0xbadc0dedfacefeedL; 97 sys_ppoll(0, 0, (unsigned long) ts, 0, sigset_size); 98 printf("ppoll(NULL, 0, {tv_sec=%lld, tv_nsec=%llu}, NULL, %u) = %s\n", 99 (long long) ts->tv_sec, zero_extend_signed_to_ull(ts->tv_nsec), 100 sigset_size, errstr); 101 102 if (pipe(pipe_fd) || pipe(pipe_fd + 2)) 103 perror_msg_and_fail("pipe"); 104 105 ts->tv_sec = 42; 106 ts->tv_nsec = 999999999; 107 108 const struct pollfd fds1[] = { 109 { .fd = pipe_fd[0], .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND }, 110 { .fd = pipe_fd[1], .events = POLLOUT | POLLWRNORM | POLLWRBAND }, 111 { .fd = pipe_fd[2], .events = POLLIN | POLLPRI }, 112 { .fd = pipe_fd[3], .events = POLLOUT } 113 }; 114 fds = efault - sizeof(fds1); 115 memcpy(fds, fds1, sizeof(fds1)); 116 117 sigemptyset(&mask); 118 sigaddset(&mask, SIGUSR2); 119 sigaddset(&mask, SIGCHLD); 120 memcpy(sigmask, &mask, sigset_size); 121 122 rc = sys_ppoll((unsigned long) fds, 123 F8ILL_KULONG_MASK | ARRAY_SIZE(fds1), (unsigned long) ts, 124 (unsigned long) sigmask, sigset_size); 125 if (rc != 2) 126 perror_msg_and_fail("ppoll 1"); 127 printf("ppoll([{fd=%d, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}" 128 ", {fd=%d, events=POLLOUT%s|POLLWRBAND}" 129#if VERBOSE 130 ", {fd=%d, events=POLLIN|POLLPRI}, {fd=%d, events=POLLOUT}]" 131#else 132 ", ...]" 133#endif 134 ", %u, {tv_sec=42, tv_nsec=999999999}, [%s], %u) = %ld" 135 " ([{fd=%d, revents=POLLOUT%s}, {fd=%d, revents=POLLOUT}]" 136 ", left {tv_sec=%u, tv_nsec=%u})\n", 137 pipe_fd[0], pipe_fd[1], POLLWRNORM_str, 138#if VERBOSE 139 pipe_fd[2], pipe_fd[3], 140#endif 141 (unsigned int) ARRAY_SIZE(fds1), USR2_CHLD_str, 142 (unsigned int) sigset_size, rc, pipe_fd[1], POLLWRNORM_str, 143 pipe_fd[3], (unsigned int) ts->tv_sec, 144 (unsigned int) ts->tv_nsec); 145 146 ts->tv_sec = 0; 147 ts->tv_nsec = 999; 148 const struct pollfd fds2[] = { 149 { .fd = pipe_fd[1], .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND }, 150 { .fd = pipe_fd[0], .events = POLLOUT | POLLWRNORM | POLLWRBAND } 151 }; 152 fds = efault - sizeof(fds2); 153 memcpy(fds, fds2, sizeof(fds2)); 154 155 memset(&mask, -1, sizeof(mask)); 156 sigdelset(&mask, SIGHUP); 157 sigdelset(&mask, SIGKILL); 158 sigdelset(&mask, SIGSTOP); 159 memcpy(sigmask, &mask, sigset_size); 160 161 rc = sys_ppoll((unsigned long) fds, 162 F8ILL_KULONG_MASK | ARRAY_SIZE(fds2), (unsigned long) ts, 163 (unsigned long) sigmask, sigset_size); 164 if (rc != 0) 165 perror_msg_and_fail("ppoll 2"); 166 printf("ppoll([{fd=%d, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}" 167 ", {fd=%d, events=POLLOUT%s|POLLWRBAND}], %u" 168 ", {tv_sec=0, tv_nsec=999}, ~[HUP KILL STOP], %u)" 169 " = %ld (Timeout)\n", 170 pipe_fd[1], pipe_fd[0], POLLWRNORM_str, 171 (unsigned) ARRAY_SIZE(fds2), sigset_size, rc); 172 173 if (F8ILL_KULONG_SUPPORTED) { 174 sys_ppoll(f8ill_ptr_to_kulong(fds), ARRAY_SIZE(fds2), 175 f8ill_ptr_to_kulong(ts), f8ill_ptr_to_kulong(sigmask), 176 sigset_size); 177 printf("ppoll(%#llx, %u, %#llx, %#llx, %u) = %s\n", 178 (unsigned long long) f8ill_ptr_to_kulong(fds), 179 (unsigned) ARRAY_SIZE(fds2), 180 (unsigned long long) f8ill_ptr_to_kulong(ts), 181 (unsigned long long) f8ill_ptr_to_kulong(sigmask), 182 (unsigned) sigset_size, errstr); 183 } 184 185 puts("+++ exited with 0 +++"); 186 return 0; 187} 188 189#else 190 191SKIP_MAIN_UNDEFINED("__NR_ppoll") 192 193#endif 194