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 * Copyright (c) 1999-2018 The strace developers. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "defs.h" 33 #include <fcntl.h> 34 #include <sys/uio.h> 35 36 SYS_FUNC(read) 37 { 38 if (entering(tcp)) { 39 printfd(tcp, tcp->u_arg[0]); 40 tprints(", "); 41 } else { 42 if (syserror(tcp)) 43 printaddr(tcp->u_arg[1]); 44 else 45 printstrn(tcp, tcp->u_arg[1], tcp->u_rval); 46 tprintf(", %" PRI_klu, tcp->u_arg[2]); 47 } 48 return 0; 49 } 50 51 SYS_FUNC(write) 52 { 53 printfd(tcp, tcp->u_arg[0]); 54 tprints(", "); 55 printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]); 56 tprintf(", %" PRI_klu, tcp->u_arg[2]); 57 58 return RVAL_DECODED; 59 } 60 61 struct print_iovec_config { 62 enum iov_decode decode_iov; 63 kernel_ulong_t data_size; 64 }; 65 66 static bool 67 print_iovec(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) 68 { 69 const kernel_ulong_t *iov; 70 kernel_ulong_t iov_buf[2], len; 71 struct print_iovec_config *c = data; 72 73 if (elem_size < sizeof(iov_buf)) { 74 iov_buf[0] = ((unsigned int *) elem_buf)[0]; 75 iov_buf[1] = ((unsigned int *) elem_buf)[1]; 76 iov = iov_buf; 77 } else { 78 iov = elem_buf; 79 } 80 81 tprints("{iov_base="); 82 83 len = iov[1]; 84 85 switch (c->decode_iov) { 86 case IOV_DECODE_STR: 87 if (len > c->data_size) 88 len = c->data_size; 89 if (c->data_size != (kernel_ulong_t) -1) 90 c->data_size -= len; 91 printstrn(tcp, iov[0], len); 92 break; 93 case IOV_DECODE_NETLINK: 94 if (len > c->data_size) 95 len = c->data_size; 96 if (c->data_size != (kernel_ulong_t) -1) 97 c->data_size -= len; 98 /* assume that the descriptor is 1st syscall argument */ 99 decode_netlink(tcp, tcp->u_arg[0], iov[0], len); 100 break; 101 default: 102 printaddr(iov[0]); 103 break; 104 } 105 106 tprintf(", iov_len=%" PRI_klu "}", iov[1]); 107 108 return true; 109 } 110 111 /* 112 * data_size limits the cumulative size of printed data. 113 * Example: recvmsg returing a short read. 114 */ 115 void 116 tprint_iov_upto(struct tcb *const tcp, const kernel_ulong_t len, 117 const kernel_ulong_t addr, const enum iov_decode decode_iov, 118 const kernel_ulong_t data_size) 119 { 120 kernel_ulong_t iov[2]; 121 struct print_iovec_config config = { 122 .decode_iov = decode_iov, .data_size = data_size 123 }; 124 125 print_array(tcp, addr, len, iov, current_wordsize * 2, 126 tfetch_mem_ignore_syserror, print_iovec, &config); 127 } 128 129 SYS_FUNC(readv) 130 { 131 if (entering(tcp)) { 132 printfd(tcp, tcp->u_arg[0]); 133 tprints(", "); 134 } else { 135 tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1], 136 syserror(tcp) ? IOV_DECODE_ADDR : 137 IOV_DECODE_STR, tcp->u_rval); 138 tprintf(", %" PRI_klu, tcp->u_arg[2]); 139 } 140 return 0; 141 } 142 143 SYS_FUNC(writev) 144 { 145 printfd(tcp, tcp->u_arg[0]); 146 tprints(", "); 147 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR); 148 tprintf(", %" PRI_klu, tcp->u_arg[2]); 149 150 return RVAL_DECODED; 151 } 152 153 SYS_FUNC(pread) 154 { 155 if (entering(tcp)) { 156 printfd(tcp, tcp->u_arg[0]); 157 tprints(", "); 158 } else { 159 if (syserror(tcp)) 160 printaddr(tcp->u_arg[1]); 161 else 162 printstrn(tcp, tcp->u_arg[1], tcp->u_rval); 163 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]); 164 printllval(tcp, "%lld", 3); 165 } 166 return 0; 167 } 168 169 SYS_FUNC(pwrite) 170 { 171 printfd(tcp, tcp->u_arg[0]); 172 tprints(", "); 173 printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]); 174 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]); 175 printllval(tcp, "%lld", 3); 176 177 return RVAL_DECODED; 178 } 179 180 static void 181 print_lld_from_low_high_val(struct tcb *tcp, int arg) 182 { 183 #if SIZEOF_KERNEL_LONG_T > 4 184 # ifndef current_klongsize 185 if (current_klongsize < SIZEOF_KERNEL_LONG_T) { 186 tprintf("%" PRI_kld, (tcp->u_arg[arg + 1] << 32) 187 | tcp->u_arg[arg]); 188 } else 189 # endif /* !current_klongsize */ 190 { 191 tprintf("%" PRI_kld, tcp->u_arg[arg]); 192 } 193 #else /* SIZEOF_KERNEL_LONG_T == 4 */ 194 tprintf("%lld", 195 ((long long) tcp->u_arg[arg + 1] << 32) 196 | ((long long) tcp->u_arg[arg])); 197 #endif 198 } 199 200 #include "xlat/rwf_flags.h" 201 202 static int 203 do_preadv(struct tcb *tcp, const int flags_arg) 204 { 205 if (entering(tcp)) { 206 printfd(tcp, tcp->u_arg[0]); 207 tprints(", "); 208 } else { 209 kernel_ulong_t len = 210 truncate_kulong_to_current_wordsize(tcp->u_arg[2]); 211 212 tprint_iov_upto(tcp, len, tcp->u_arg[1], 213 syserror(tcp) ? IOV_DECODE_ADDR : 214 IOV_DECODE_STR, tcp->u_rval); 215 tprintf(", %" PRI_klu ", ", len); 216 print_lld_from_low_high_val(tcp, 3); 217 if (flags_arg >= 0) { 218 tprints(", "); 219 printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???"); 220 } 221 } 222 return 0; 223 } 224 225 SYS_FUNC(preadv) 226 { 227 return do_preadv(tcp, -1); 228 } 229 230 static int 231 do_pwritev(struct tcb *tcp, const int flags_arg) 232 { 233 kernel_ulong_t len = 234 truncate_kulong_to_current_wordsize(tcp->u_arg[2]); 235 236 printfd(tcp, tcp->u_arg[0]); 237 tprints(", "); 238 tprint_iov(tcp, len, tcp->u_arg[1], IOV_DECODE_STR); 239 tprintf(", %" PRI_klu ", ", len); 240 print_lld_from_low_high_val(tcp, 3); 241 if (flags_arg >= 0) { 242 tprints(", "); 243 printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???"); 244 } 245 246 return RVAL_DECODED; 247 } 248 249 SYS_FUNC(pwritev) 250 { 251 return do_pwritev(tcp, -1); 252 } 253 254 /* 255 * x32 is the only architecture where preadv2 takes 5 arguments 256 * instead of 6, see preadv64v2 in kernel sources. 257 * Likewise, x32 is the only architecture where pwritev2 takes 5 arguments 258 * instead of 6, see pwritev64v2 in kernel sources. 259 */ 260 261 #if defined X86_64 262 # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 2 ? 4 : 5) 263 #elif defined X32 264 # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 0 ? 4 : 5) 265 #else 266 # define PREADV2_PWRITEV2_FLAGS_ARG_NO 5 267 #endif 268 269 SYS_FUNC(preadv2) 270 { 271 return do_preadv(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO); 272 } 273 274 SYS_FUNC(pwritev2) 275 { 276 return do_pwritev(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO); 277 } 278 279 #include "xlat/splice_flags.h" 280 281 SYS_FUNC(tee) 282 { 283 /* int fd_in */ 284 printfd(tcp, tcp->u_arg[0]); 285 tprints(", "); 286 /* int fd_out */ 287 printfd(tcp, tcp->u_arg[1]); 288 tprints(", "); 289 /* size_t len */ 290 tprintf("%" PRI_klu ", ", tcp->u_arg[2]); 291 /* unsigned int flags */ 292 printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???"); 293 294 return RVAL_DECODED; 295 } 296 297 SYS_FUNC(splice) 298 { 299 /* int fd_in */ 300 printfd(tcp, tcp->u_arg[0]); 301 tprints(", "); 302 /* loff_t *off_in */ 303 printnum_int64(tcp, tcp->u_arg[1], "%" PRId64); 304 tprints(", "); 305 /* int fd_out */ 306 printfd(tcp, tcp->u_arg[2]); 307 tprints(", "); 308 /* loff_t *off_out */ 309 printnum_int64(tcp, tcp->u_arg[3], "%" PRId64); 310 tprints(", "); 311 /* size_t len */ 312 tprintf("%" PRI_klu ", ", tcp->u_arg[4]); 313 /* unsigned int flags */ 314 printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???"); 315 316 return RVAL_DECODED; 317 } 318 319 SYS_FUNC(vmsplice) 320 { 321 /* int fd */ 322 printfd(tcp, tcp->u_arg[0]); 323 tprints(", "); 324 /* const struct iovec *iov, unsigned long nr_segs */ 325 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR); 326 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]); 327 /* unsigned int flags */ 328 printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???"); 329 330 return RVAL_DECODED; 331 } 332