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 <linux/aio_abi.h>
14
15 #include "xlat/aio_cmds.h"
16
17 #ifdef HAVE_STRUCT_IOCB_AIO_FLAGS
18 # include "xlat/aio_iocb_flags.h"
19 #endif
20
21 SYS_FUNC(io_setup)
22 {
23 if (entering(tcp)) {
24 /* nr_events */
25 unsigned int nr_events = tcp->u_arg[0];
26 PRINT_VAL_U(nr_events);
27 tprint_arg_next();
28 } else {
29 /* ctx_idp */
30 printnum_ptr(tcp, tcp->u_arg[1]);
31 }
32 return 0;
33 }
34
35 SYS_FUNC(io_destroy)
36 {
37 /* ctx_id */
38 printaddr(tcp->u_arg[0]);
39
40 return RVAL_DECODED;
41 }
42
43 enum iocb_sub {
44 SUB_NONE, SUB_COMMON, SUB_VECTOR, SUB_POLL
45 };
46
47 static enum iocb_sub
48 tprint_lio_opcode(unsigned int cmd)
49 {
50 static const enum iocb_sub subs[] = {
51 [IOCB_CMD_PREAD] = SUB_COMMON,
52 [IOCB_CMD_PWRITE] = SUB_COMMON,
53 [IOCB_CMD_FSYNC] = SUB_NONE,
54 [IOCB_CMD_FDSYNC] = SUB_NONE,
55 [IOCB_CMD_PREADX] = SUB_NONE,
56 [IOCB_CMD_POLL] = SUB_POLL,
57 [IOCB_CMD_NOOP] = SUB_NONE,
58 [IOCB_CMD_PREADV] = SUB_VECTOR,
59 [IOCB_CMD_PWRITEV] = SUB_VECTOR,
60 };
61
62 printxval_ex(aio_cmds, cmd, "IOCB_CMD_???", XLAT_STYLE_FMT_U);
63
64 return cmd < ARRAY_SIZE(subs) ? subs[cmd] : SUB_NONE;
65 }
66
67 static void
68 print_common_flags(struct tcb *tcp, const struct iocb *cb)
69 {
70 /* aio_flags and aio_resfd fields are available since v2.6.22-rc1~47 */
71 #ifdef HAVE_STRUCT_IOCB_AIO_FLAGS
72 if (cb->aio_flags) {
73 tprint_struct_next();
74 PRINT_FIELD_FLAGS(*cb, aio_flags, aio_iocb_flags,
75 "IOCB_FLAG_???");
76 }
77
78 if (cb->aio_flags & IOCB_FLAG_RESFD) {
79 tprint_struct_next();
80 PRINT_FIELD_FD(*cb, aio_resfd, tcp);
81 } else if (cb->aio_resfd) {
82 tprint_struct_next();
83 PRINT_FIELD_X(*cb, aio_resfd);
84 }
85 #endif
86 }
87
88 static bool
89 iocb_is_valid(const struct iocb *cb)
90 {
91 return cb->aio_buf == (unsigned long) cb->aio_buf &&
92 cb->aio_nbytes == (size_t) cb->aio_nbytes &&
93 (ssize_t) cb->aio_nbytes >= 0;
94 }
95
96 static enum iocb_sub
97 print_iocb_header(struct tcb *tcp, const struct iocb *cb)
98 {
99 enum iocb_sub sub;
100
101 PRINT_FIELD_X(*cb, aio_data);
102
103 if (cb->aio_key) {
104 tprint_struct_next();
105 PRINT_FIELD_U(*cb, aio_key);
106 }
107
108 #ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS
109 # define aio_rw_flags aio_reserved1
110 #endif
111 if (cb->aio_rw_flags) {
112 tprint_struct_next();
113 PRINT_FIELD_FLAGS(*cb, aio_rw_flags, rwf_flags, "RWF_???");
114 }
115
116 tprint_struct_next();
117 tprints_field_name("aio_lio_opcode");
118 sub = tprint_lio_opcode(cb->aio_lio_opcode);
119
120 if (cb->aio_flags & IOCB_FLAG_IOPRIO) {
121 tprint_struct_next();
122 PRINT_FIELD_OBJ_U(*cb, aio_reqprio, print_ioprio);
123 } else if (cb->aio_reqprio) {
124 tprint_struct_next();
125 PRINT_FIELD_D(*cb, aio_reqprio);
126 }
127
128 tprint_struct_next();
129 PRINT_FIELD_FD(*cb, aio_fildes, tcp);
130
131 return sub;
132 }
133
134 static void
135 print_iocb(struct tcb *tcp, const struct iocb *cb)
136 {
137 tprint_struct_begin();
138
139 enum iocb_sub sub = print_iocb_header(tcp, cb);
140
141 switch (sub) {
142 case SUB_COMMON:
143 if (cb->aio_lio_opcode == 1 && iocb_is_valid(cb)) {
144 tprint_struct_next();
145 PRINT_FIELD_OBJ_TCB_VAL(*cb, aio_buf, tcp,
146 printstrn, cb->aio_nbytes);
147 } else {
148 tprint_struct_next();
149 PRINT_FIELD_X(*cb, aio_buf);
150 }
151 tprint_struct_next();
152 PRINT_FIELD_U(*cb, aio_nbytes);
153 tprint_struct_next();
154 PRINT_FIELD_D(*cb, aio_offset);
155 print_common_flags(tcp, cb);
156 break;
157 case SUB_VECTOR:
158 if (iocb_is_valid(cb)) {
159 tprint_struct_next();
160 tprints_field_name("aio_buf");
161 tprint_iov(tcp, cb->aio_nbytes, cb->aio_buf,
162 cb->aio_lio_opcode == 8
163 ? iov_decode_str
164 : iov_decode_addr);
165 } else {
166 tprint_struct_next();
167 PRINT_FIELD_X(*cb, aio_buf);
168 tprint_struct_next();
169 PRINT_FIELD_U(*cb, aio_nbytes);
170 }
171 tprint_struct_next();
172 PRINT_FIELD_D(*cb, aio_offset);
173 print_common_flags(tcp, cb);
174 break;
175 case SUB_POLL:
176 tprint_struct_next();
177 PRINT_FIELD_FLAGS(*cb, aio_buf, pollflags, "POLL???");
178 print_common_flags(tcp, cb);
179 break;
180 case SUB_NONE:
181 break;
182 }
183
184 tprint_struct_end();
185 }
186
187 static bool
188 print_iocbp(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
189 {
190 kernel_ulong_t addr;
191 struct iocb cb;
192
193 if (elem_size < sizeof(kernel_ulong_t)) {
194 addr = *(unsigned int *) elem_buf;
195 } else {
196 addr = *(kernel_ulong_t *) elem_buf;
197 }
198
199 if (!umove_or_printaddr(tcp, addr, &cb))
200 print_iocb(tcp, &cb);
201
202 return true;
203 }
204
205 SYS_FUNC(io_submit)
206 {
207 const kernel_ulong_t addr = tcp->u_arg[2];
208 kernel_ulong_t iocbp;
209
210 /* ctx_id */
211 printaddr(tcp->u_arg[0]);
212 tprint_arg_next();
213
214 /* nr */
215 const kernel_long_t nr =
216 truncate_klong_to_current_wordsize(tcp->u_arg[1]);
217 PRINT_VAL_D(nr);
218 tprint_arg_next();
219
220 /* iocbpp */
221 if (nr < 0)
222 printaddr(addr);
223 else
224 print_array(tcp, addr, nr, &iocbp, current_wordsize,
225 tfetch_mem, print_iocbp, 0);
226
227 return RVAL_DECODED;
228 }
229
230 static bool
231 print_io_event(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
232 {
233 struct io_event *event = elem_buf;
234
235 tprint_struct_begin();
236 PRINT_FIELD_X(*event, data);
237 tprint_struct_next();
238 PRINT_FIELD_X(*event, obj);
239 tprint_struct_next();
240 PRINT_FIELD_D(*event, res);
241 tprint_struct_next();
242 PRINT_FIELD_D(*event, res2);
243 tprint_struct_end();
244
245 return true;
246 }
247
248 SYS_FUNC(io_cancel)
249 {
250 if (entering(tcp)) {
251 /* ctx_id */
252 printaddr(tcp->u_arg[0]);
253 tprint_arg_next();
254
255 /* iocb */
256 struct iocb cb;
257 if (!umove_or_printaddr(tcp, tcp->u_arg[1], &cb)) {
258 tprint_struct_begin();
259 print_iocb_header(tcp, &cb);
260 tprint_struct_end();
261 }
262 tprint_arg_next();
263 } else {
264 /* result */
265 struct io_event event;
266 if (!umove_or_printaddr(tcp, tcp->u_arg[2], &event))
267 print_io_event(tcp, &event, sizeof(event), 0);
268 }
269 return 0;
270 }
271
272 static int
273 print_io_getevents(struct tcb *const tcp, const print_obj_by_addr_fn print_ts,
274 const bool has_sig)
275 {
276 if (entering(tcp)) {
277 kernel_long_t nr;
278
279 /* ctx_id */
280 printaddr(tcp->u_arg[0]);
281 tprint_arg_next();
282
283 /* min_nr */
284 nr = truncate_klong_to_current_wordsize(tcp->u_arg[1]);
285 PRINT_VAL_D(nr);
286 tprint_arg_next();
287
288 /* nr */
289 nr = truncate_klong_to_current_wordsize(tcp->u_arg[2]);
290 PRINT_VAL_D(nr);
291 tprint_arg_next();
292 } else {
293 /* events */
294 struct io_event buf;
295 print_array(tcp, tcp->u_arg[3], tcp->u_rval, &buf, sizeof(buf),
296 tfetch_mem, print_io_event, 0);
297 tprint_arg_next();
298
299 /*
300 * Since the timeout and sig parameters are read by the kernel
301 * on entering syscall, it has to be decoded the same way
302 * whether the syscall has failed or not.
303 */
304 temporarily_clear_syserror(tcp);
305
306 /* timeout */
307 print_ts(tcp, tcp->u_arg[4]);
308
309 if (has_sig) {
310 tprint_arg_next();
311
312 /* sig */
313 print_kernel_sigset(tcp, tcp->u_arg[5]);
314 }
315
316 restore_cleared_syserror(tcp);
317 }
318 return 0;
319 }
320
321 #if HAVE_ARCH_TIME32_SYSCALLS
322 SYS_FUNC(io_getevents_time32)
323 {
324 return print_io_getevents(tcp, print_timespec32, false);
325 }
326 #endif
327
328 #if HAVE_ARCH_OLD_TIME64_SYSCALLS
329 SYS_FUNC(io_getevents_time64)
330 {
331 return print_io_getevents(tcp, print_timespec64, false);
332 }
333 #endif
334
335 #if HAVE_ARCH_TIME32_SYSCALLS
336 SYS_FUNC(io_pgetevents_time32)
337 {
338 return print_io_getevents(tcp, print_timespec32, true);
339 }
340 #endif
341
342 SYS_FUNC(io_pgetevents_time64)
343 {
344 return print_io_getevents(tcp, print_timespec64, true);
345 }