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-2021 The strace developers.
7 * All rights reserved.
8 *
9 * SPDX-License-Identifier: LGPL-2.1-or-later
10 */
11
12 #include "defs.h"
13 #include <fcntl.h>
14 #include <sys/uio.h>
15
16 SYS_FUNC(read)
17 {
18 if (entering(tcp)) {
19 /* fd */
20 printfd(tcp, tcp->u_arg[0]);
21 tprint_arg_next();
22 } else {
23 /* buf */
24 if (syserror(tcp))
25 printaddr(tcp->u_arg[1]);
26 else
27 printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
28 tprint_arg_next();
29
30 /* count */
31 PRINT_VAL_U(tcp->u_arg[2]);
32 }
33 return 0;
34 }
35
36 SYS_FUNC(write)
37 {
38 /* fd */
39 printfd(tcp, tcp->u_arg[0]);
40 tprint_arg_next();
41
42 /* buf */
43 printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
44 tprint_arg_next();
45
46 /* count */
47 PRINT_VAL_U(tcp->u_arg[2]);
48
49 return RVAL_DECODED;
50 }
51
52 void
53 iov_decode_addr(struct tcb *tcp, kernel_ulong_t addr, kernel_ulong_t size,
54 void *opaque_data)
55 {
56 printaddr(addr);
57 }
58
59 void
60 iov_decode_str(struct tcb *tcp, kernel_ulong_t addr, kernel_ulong_t size,
61 void *opaque_data)
62 {
63 printstrn(tcp, addr, size);
64 }
65
66 struct print_iovec_config {
67 kernel_ulong_t data_size;
68 print_obj_by_addr_size_fn print_func;
69 void *opaque_data;
70 };
71
72 static bool
73 print_iovec_klong(struct tcb *const tcp,
74 const kernel_ulong_t iov_base,
75 const kernel_ulong_t iov_len,
76 struct print_iovec_config *const c)
77 {
78 kernel_ulong_t len = iov_len;
79
80 if (len > c->data_size)
81 len = c->data_size;
82 if (c->data_size != (kernel_ulong_t) -1)
83 c->data_size -= len;
84
85 tprint_struct_begin();
86 tprints_field_name("iov_base");
87 c->print_func(tcp, iov_base, len, c->opaque_data);
88 tprint_struct_next();
89
90 tprints_field_name("iov_len");
91 PRINT_VAL_U(iov_len);
92 tprint_struct_end();
93
94 return true;
95 }
96
97 #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
98 static bool
99 print_iovec_elem_int(struct tcb *tcp, void *elem_buf, size_t elem_size,
100 void *data)
101 {
102 const unsigned int *const iov = elem_buf;
103 return print_iovec_klong(tcp, iov[0], iov[1], data);
104 }
105 #endif
106
107 #if ANY_WORDSIZE_EQUALS_TO_KERNEL_LONG
108 static bool
109 print_iovec_elem_klong(struct tcb *tcp, void *elem_buf, size_t elem_size,
110 void *data)
111 {
112 const kernel_ulong_t *const iov = elem_buf;
113 return print_iovec_klong(tcp, iov[0], iov[1], data);
114 }
115 #endif
116
117 /*
118 * data_size limits the cumulative size of printed data.
119 * Example: recvmsg returning a short read.
120 */
121 void
122 tprint_iov_upto(struct tcb *const tcp, const kernel_ulong_t len,
123 const kernel_ulong_t addr,
124 const kernel_ulong_t data_size,
125 print_obj_by_addr_size_fn print_func,
126 void *opaque_data)
127 {
128 kernel_ulong_t iov[2];
129 struct print_iovec_config config = {
130 .data_size = data_size,
131 .print_func = print_func,
132 .opaque_data = opaque_data
133 };
134 const print_fn print_elem_func =
135 #if !ANY_WORDSIZE_EQUALS_TO_KERNEL_LONG
136 print_iovec_elem_int;
137 #elif !ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
138 print_iovec_elem_klong;
139 #else
140 current_wordsize < sizeof(kernel_ulong_t) ?
141 print_iovec_elem_int :
142 print_iovec_elem_klong;
143 #endif
144
145 print_array(tcp, addr, len, iov, current_wordsize * 2,
146 tfetch_mem_ignore_syserror, print_elem_func, &config);
147 }
148
149 SYS_FUNC(readv)
150 {
151 if (entering(tcp)) {
152 /* fd */
153 printfd(tcp, tcp->u_arg[0]);
154 tprint_arg_next();
155 } else {
156 /* iov */
157 tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1], tcp->u_rval,
158 syserror(tcp) ? iov_decode_addr
159 : iov_decode_str,
160 NULL);
161 tprint_arg_next();
162
163 /* iovcnt */
164 PRINT_VAL_U(tcp->u_arg[2]);
165 }
166 return 0;
167 }
168
169 SYS_FUNC(writev)
170 {
171 /* fd */
172 printfd(tcp, tcp->u_arg[0]);
173 tprint_arg_next();
174
175 /* iov */
176 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], iov_decode_str);
177 tprint_arg_next();
178
179 /* iovcnt */
180 PRINT_VAL_U(tcp->u_arg[2]);
181
182 return RVAL_DECODED;
183 }
184
185 SYS_FUNC(pread)
186 {
187 if (entering(tcp)) {
188 /* fd */
189 printfd(tcp, tcp->u_arg[0]);
190 tprint_arg_next();
191 } else {
192 /* buf */
193 if (syserror(tcp))
194 printaddr(tcp->u_arg[1]);
195 else
196 printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
197 tprint_arg_next();
198
199 /* count */
200 PRINT_VAL_U(tcp->u_arg[2]);
201 tprint_arg_next();
202
203 /* offset */
204 print_arg_lld(tcp, 3);
205 }
206 return 0;
207 }
208
209 SYS_FUNC(pwrite)
210 {
211 /* fd */
212 printfd(tcp, tcp->u_arg[0]);
213 tprint_arg_next();
214
215 /* buf */
216 printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
217 tprint_arg_next();
218
219 /* count */
220 PRINT_VAL_U(tcp->u_arg[2]);
221 tprint_arg_next();
222
223 /* offset */
224 print_arg_lld(tcp, 3);
225
226 return RVAL_DECODED;
227 }
228
229 static void
230 print_lld_from_low_high_val(struct tcb *tcp, int arg)
231 {
232 #if SIZEOF_KERNEL_LONG_T > 4
233 # ifndef current_klongsize
234 if (current_klongsize < SIZEOF_KERNEL_LONG_T)
235 PRINT_VAL_D((tcp->u_arg[arg + 1] << 32) | tcp->u_arg[arg]);
236 else
237 # endif /* !current_klongsize */
238 PRINT_VAL_D(tcp->u_arg[arg]);
239 #else /* SIZEOF_KERNEL_LONG_T == 4 */
240 PRINT_VAL_D(((unsigned long long) tcp->u_arg[arg + 1] << 32) |
241 ((unsigned long long) tcp->u_arg[arg]));
242 #endif
243 }
244
245 #include "xlat/rwf_flags.h"
246
247 static int
248 do_preadv(struct tcb *tcp, const int flags_arg)
249 {
250 if (entering(tcp)) {
251 /* fd */
252 printfd(tcp, tcp->u_arg[0]);
253 tprint_arg_next();
254 } else {
255 kernel_ulong_t len =
256 truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
257
258 /* iov */
259 tprint_iov_upto(tcp, len, tcp->u_arg[1], tcp->u_rval,
260 syserror(tcp) ? iov_decode_addr
261 : iov_decode_str,
262 NULL);
263 tprint_arg_next();
264
265 /* iovcnt */
266 PRINT_VAL_U(len);
267 tprint_arg_next();
268
269 /* offset */
270 print_lld_from_low_high_val(tcp, 3);
271
272 if (flags_arg >= 0) {
273 tprint_arg_next();
274
275 /* flags */
276 printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
277 }
278 }
279 return 0;
280 }
281
282 SYS_FUNC(preadv)
283 {
284 return do_preadv(tcp, -1);
285 }
286
287 static int
288 do_pwritev(struct tcb *tcp, const int flags_arg)
289 {
290 kernel_ulong_t len =
291 truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
292
293 /* fd */
294 printfd(tcp, tcp->u_arg[0]);
295 tprint_arg_next();
296
297 /* iov */
298 tprint_iov(tcp, len, tcp->u_arg[1], iov_decode_str);
299 tprint_arg_next();
300
301 /* iovcnt */
302 PRINT_VAL_U(len);
303 tprint_arg_next();
304
305 /* offset */
306 print_lld_from_low_high_val(tcp, 3);
307
308 if (flags_arg >= 0) {
309 tprint_arg_next();
310
311 /* flags */
312 printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
313 }
314
315 return RVAL_DECODED;
316 }
317
318 SYS_FUNC(pwritev)
319 {
320 return do_pwritev(tcp, -1);
321 }
322
323 /*
324 * x32 is the only architecture where preadv2 takes 5 arguments
325 * instead of 6, see preadv64v2 in kernel sources.
326 * Likewise, x32 is the only architecture where pwritev2 takes 5 arguments
327 * instead of 6, see pwritev64v2 in kernel sources.
328 */
329
330 #if defined X86_64
331 # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 2 ? 4 : 5)
332 #elif defined X32
333 # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 0 ? 4 : 5)
334 #else
335 # define PREADV2_PWRITEV2_FLAGS_ARG_NO 5
336 #endif
337
338 SYS_FUNC(preadv2)
339 {
340 return do_preadv(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
341 }
342
343 SYS_FUNC(pwritev2)
344 {
345 return do_pwritev(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
346 }
347
348 #include "xlat/splice_flags.h"
349
350 SYS_FUNC(tee)
351 {
352 /* int fd_in */
353 printfd(tcp, tcp->u_arg[0]);
354 tprint_arg_next();
355
356 /* int fd_out */
357 printfd(tcp, tcp->u_arg[1]);
358 tprint_arg_next();
359
360 /* size_t len */
361 PRINT_VAL_U(tcp->u_arg[2]);
362 tprint_arg_next();
363
364 /* unsigned int flags */
365 printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
366
367 return RVAL_DECODED;
368 }
369
370 SYS_FUNC(splice)
371 {
372 /* int fd_in */
373 printfd(tcp, tcp->u_arg[0]);
374 tprint_arg_next();
375
376 /* loff_t *off_in */
377 printnum_int64(tcp, tcp->u_arg[1], "%" PRId64);
378 tprint_arg_next();
379
380 /* int fd_out */
381 printfd(tcp, tcp->u_arg[2]);
382 tprint_arg_next();
383
384 /* loff_t *off_out */
385 printnum_int64(tcp, tcp->u_arg[3], "%" PRId64);
386 tprint_arg_next();
387
388 /* size_t len */
389 PRINT_VAL_U(tcp->u_arg[4]);
390 tprint_arg_next();
391
392 /* unsigned int flags */
393 printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???");
394
395 return RVAL_DECODED;
396 }
397
398 SYS_FUNC(vmsplice)
399 {
400 /* int fd */
401 printfd(tcp, tcp->u_arg[0]);
402 tprint_arg_next();
403
404 /* const struct iovec *iov */
405 tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], iov_decode_str);
406 tprint_arg_next();
407
408 /* unsigned long nr_segs */
409 PRINT_VAL_U(tcp->u_arg[2]);
410 tprint_arg_next();
411
412 /* unsigned int flags */
413 printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
414
415 return RVAL_DECODED;
416 }