1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl> 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 #include "defs.h" 32 33 SYS_FUNC(close) 34 { 35 printfd(tcp, tcp->u_arg[0]); 36 37 return RVAL_DECODED; 38 } 39 40 SYS_FUNC(dup) 41 { 42 printfd(tcp, tcp->u_arg[0]); 43 44 return RVAL_DECODED | RVAL_FD; 45 } 46 47 static int 48 do_dup2(struct tcb *tcp, int flags_arg) 49 { 50 printfd(tcp, tcp->u_arg[0]); 51 tprints(", "); 52 printfd(tcp, tcp->u_arg[1]); 53 if (flags_arg >= 0) { 54 tprints(", "); 55 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); 56 } 57 58 return RVAL_DECODED | RVAL_FD; 59 } 60 61 SYS_FUNC(dup2) 62 { 63 return do_dup2(tcp, -1); 64 } 65 66 SYS_FUNC(dup3) 67 { 68 return do_dup2(tcp, 2); 69 } 70 71 #if defined(ALPHA) 72 SYS_FUNC(getdtablesize) 73 { 74 return 0; 75 } 76 #endif 77 78 static int 79 decode_select(struct tcb *tcp, long *args, 80 void (*print_tv_ts) (struct tcb *, const long), 81 const char * (*sprint_tv_ts) (struct tcb *, const long)) 82 { 83 int i, j; 84 int nfds, fdsize; 85 fd_set *fds = NULL; 86 const char *sep; 87 long arg; 88 89 /* Kernel truncates arg[0] to int, we do the same. */ 90 nfds = (int) args[0]; 91 92 /* Kernel rejects negative nfds, so we don't parse it either. */ 93 if (nfds < 0) 94 nfds = 0; 95 96 /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */ 97 if (nfds > 1024*1024) 98 nfds = 1024*1024; 99 100 /* 101 * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below. 102 * Instead of args[0], use nfds for fd count, fdsize for array lengths. 103 */ 104 fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize; 105 106 if (entering(tcp)) { 107 tprintf("%d", (int) args[0]); 108 109 if (verbose(tcp) && fdsize > 0) 110 fds = malloc(fdsize); 111 for (i = 0; i < 3; i++) { 112 arg = args[i+1]; 113 tprints(", "); 114 if (!fds) { 115 printaddr(arg); 116 continue; 117 } 118 if (umoven_or_printaddr(tcp, arg, fdsize, fds)) 119 continue; 120 tprints("["); 121 for (j = 0, sep = "";; j++) { 122 j = next_set_bit(fds, j, nfds); 123 if (j < 0) 124 break; 125 tprints(sep); 126 printfd(tcp, j); 127 sep = " "; 128 } 129 tprints("]"); 130 } 131 free(fds); 132 tprints(", "); 133 print_tv_ts(tcp, args[4]); 134 } else { 135 static char outstr[1024]; 136 char *outptr; 137 #define end_outstr (outstr + sizeof(outstr)) 138 int ready_fds; 139 140 if (syserror(tcp)) 141 return 0; 142 143 ready_fds = tcp->u_rval; 144 if (ready_fds == 0) { 145 tcp->auxstr = "Timeout"; 146 return RVAL_STR; 147 } 148 149 fds = malloc(fdsize); 150 151 outptr = outstr; 152 sep = ""; 153 for (i = 0; i < 3 && ready_fds > 0; i++) { 154 int first = 1; 155 156 arg = args[i+1]; 157 if (!arg || !fds || umoven(tcp, arg, fdsize, fds) < 0) 158 continue; 159 for (j = 0;; j++) { 160 j = next_set_bit(fds, j, nfds); 161 if (j < 0) 162 break; 163 /* +2 chars needed at the end: ']',NUL */ 164 if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) { 165 if (first) { 166 outptr += sprintf(outptr, "%s%s [%u", 167 sep, 168 i == 0 ? "in" : i == 1 ? "out" : "except", 169 j 170 ); 171 first = 0; 172 sep = ", "; 173 } 174 else { 175 outptr += sprintf(outptr, " %u", j); 176 } 177 } 178 if (--ready_fds == 0) 179 break; 180 } 181 if (outptr != outstr) 182 *outptr++ = ']'; 183 } 184 free(fds); 185 /* This contains no useful information on SunOS. */ 186 if (args[4]) { 187 const char *str = sprint_tv_ts(tcp, args[4]); 188 if (outptr + sizeof("left ") + strlen(sep) + strlen(str) < end_outstr) { 189 outptr += sprintf(outptr, "%sleft %s", sep, str); 190 } 191 } 192 *outptr = '\0'; 193 tcp->auxstr = outstr; 194 return RVAL_STR; 195 #undef end_outstr 196 } 197 return 0; 198 } 199 200 SYS_FUNC(oldselect) 201 { 202 long long_args[5]; 203 #undef oldselect_args 204 #if SIZEOF_LONG == 4 205 # define oldselect_args long_args 206 #else 207 unsigned int oldselect_args[5]; 208 unsigned int i; 209 #endif 210 211 if (umove(tcp, tcp->u_arg[0], &oldselect_args) < 0) { 212 printaddr(tcp->u_arg[0]); 213 return 0; 214 } 215 #ifndef oldselect_args 216 for (i = 0; i < 5; i++) { 217 long_args[i] = oldselect_args[i]; 218 } 219 #endif 220 return decode_select(tcp, long_args, print_timeval, sprint_timeval); 221 #undef oldselect_args 222 } 223 224 #ifdef ALPHA 225 SYS_FUNC(osf_select) 226 { 227 return decode_select(tcp, tcp->u_arg, print_timeval32, sprint_timeval32); 228 } 229 #endif 230 231 SYS_FUNC(select) 232 { 233 return decode_select(tcp, tcp->u_arg, print_timeval, sprint_timeval); 234 } 235 236 #include "kernel_types.h" 237 238 static int 239 umove_kulong_array_or_printaddr(struct tcb *tcp, const long addr, 240 kernel_ulong_t *ptr, size_t n) 241 { 242 #if defined X86_64 || defined X32 243 if (current_personality == 1) { 244 #else 245 if (current_wordsize < sizeof(*ptr)) { 246 #endif 247 uint32_t ptr32[n]; 248 int r = umove_or_printaddr(tcp, addr, &ptr32); 249 if (!r) { 250 size_t i; 251 252 for (i = 0; i < n; ++i) 253 ptr[i] = (kernel_ulong_t) ptr32[i]; 254 } 255 return r; 256 } 257 return umoven_or_printaddr(tcp, addr, n * sizeof(*ptr), ptr); 258 } 259 260 SYS_FUNC(pselect6) 261 { 262 int rc = decode_select(tcp, tcp->u_arg, print_timespec, sprint_timespec); 263 if (entering(tcp)) { 264 kernel_ulong_t data[2]; 265 266 tprints(", "); 267 if (!umove_kulong_array_or_printaddr(tcp, tcp->u_arg[5], 268 data, ARRAY_SIZE(data))) { 269 tprints("{"); 270 /* NB: kernel requires data[1] == NSIG / 8 */ 271 print_sigset_addr_len(tcp, (unsigned long) data[0], 272 (unsigned long) data[1]); 273 tprintf(", %llu}", (unsigned long long) data[1]); 274 } 275 } 276 277 return rc; 278 } 279