1 /*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999-2017 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
SYS_FUNC(read)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
SYS_FUNC(write)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
print_iovec(struct tcb * tcp,void * elem_buf,size_t elem_size,void * data)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
tprint_iov_upto(struct tcb * const tcp,const kernel_ulong_t len,const kernel_ulong_t addr,const enum iov_decode decode_iov,const kernel_ulong_t data_size)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 umoven_or_printaddr_ignore_syserror, print_iovec, &config);
127 }
128
SYS_FUNC(readv)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
SYS_FUNC(writev)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
SYS_FUNC(pread)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
SYS_FUNC(pwrite)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
print_lld_from_low_high_val(struct tcb * tcp,int arg)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
do_preadv(struct tcb * tcp,const int flags_arg)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
SYS_FUNC(preadv)225 SYS_FUNC(preadv)
226 {
227 return do_preadv(tcp, -1);
228 }
229
230 static int
do_pwritev(struct tcb * tcp,const int flags_arg)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
SYS_FUNC(pwritev)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
SYS_FUNC(preadv2)269 SYS_FUNC(preadv2)
270 {
271 return do_preadv(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
272 }
273
SYS_FUNC(pwritev2)274 SYS_FUNC(pwritev2)
275 {
276 return do_pwritev(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
277 }
278
279 #include "xlat/splice_flags.h"
280
SYS_FUNC(tee)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
SYS_FUNC(splice)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
SYS_FUNC(vmsplice)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