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-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 
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 		    tfetch_mem_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