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 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
9 * Copyright (c) 2000 PocketPenguins Inc. Linux for Hitachi SuperH
10 * port by Greg Banks <gbanks@pocketpenguins.com>
11 * Copyright (c) 1999-2022 The strace developers.
12 *
13 * All rights reserved.
14 *
15 * SPDX-License-Identifier: LGPL-2.1-or-later
16 */
17
18 #include "defs.h"
19
20 #ifdef HAVE_ELF_H
21 # include <elf.h>
22 #endif
23
24 #include "iovec.h"
25 #include "ptrace.h"
26 #include "ptrace_syscall_info.h"
27 #include "regs.h"
28
29 #include "xlat/nt_descriptor_types.h"
30 #include "xlat/ptrace_cmds.h"
31 #include "xlat/compat_ptrace_cmds.h"
32 #include "xlat/ptrace_setoptions_flags.h"
33 #include "xlat/ptrace_peeksiginfo_flags.h"
34
35 #define uoff(member) offsetof(struct user, member)
36 #define XLAT_UOFF(member) { uoff(member), "offsetof(struct user, " #member ")" }
37
38 #ifdef COMPAT_PTRACE_GETREGS
39 # define HAVE_COMPAT_PTRACE_MACROS 1
40 #else
41 # define HAVE_COMPAT_PTRACE_MACROS 0
42 #endif
43
44 static const struct xlat_data struct_user_offsets_data[] = {
45 #include "userent.h"
46 { 0, 0 }
47 };
48
49 static const struct xlat struct_user_offsets = {
50 .type = XT_SORTED,
51 .size = ARRAY_SIZE(struct_user_offsets_data) - 1,
52 .data = struct_user_offsets_data,
53 };
54
55 static void
56 print_user_offset_addr(const kernel_ulong_t addr)
57 {
58 const uint64_t last_user_offset = struct_user_offsets.size ?
59 struct_user_offsets.data[struct_user_offsets.size - 1].val : 0;
60
61 uint64_t base_addr = addr;
62 const char *str = xlookup_le(&struct_user_offsets, &base_addr);
63
64 /* We don't want to pretty print addresses beyond struct user */
65 if (addr > base_addr && base_addr == last_user_offset)
66 str = NULL;
67
68 if (!str || xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
69 printaddr(addr);
70 if (!str || xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
71 return;
72
73 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
74 tprint_comment_begin();
75
76 tprints_string(str);
77 if (base_addr != addr) {
78 tprint_plus();
79 PRINT_VAL_U(addr - (kernel_ulong_t) base_addr);
80 }
81
82 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
83 tprint_comment_end();
84 }
85
86 static void
87 decode_peeksiginfo_args(struct tcb *const tcp, const kernel_ulong_t addr)
88 {
89 struct {
90 uint64_t off;
91 uint32_t flags;
92 uint32_t nr;
93 } psi;
94
95 if (!umove_or_printaddr(tcp, addr, &psi)) {
96 tprint_struct_begin();
97 PRINT_FIELD_U(psi, off);
98 tprint_struct_next();
99
100 PRINT_FIELD_FLAGS(psi, flags, ptrace_peeksiginfo_flags,
101 "PTRACE_PEEKSIGINFO_???");
102 tprint_struct_next();
103
104 PRINT_FIELD_U(psi, nr);
105 tprint_struct_end();
106 }
107 }
108
109 static int
110 decode_seccomp_metadata(struct tcb *const tcp,
111 const kernel_ulong_t addr,
112 const kernel_ulong_t size)
113 {
114 struct {
115 uint64_t filter_off;
116 uint64_t flags;
117 } md;
118
119 if (entering(tcp)) {
120 if (size < sizeof(md.filter_off)) {
121 printaddr(addr);
122 return RVAL_DECODED;
123 }
124
125 if (umove_or_printaddr(tcp, addr, &md.filter_off)) {
126 return RVAL_DECODED;
127 }
128
129 tprint_struct_begin();
130 PRINT_FIELD_U(md, filter_off);
131 } else {
132 const size_t offset = sizeof(md.filter_off);
133
134 if (!syserror(tcp) && size > offset) {
135 tprint_struct_next();
136
137 if (size < sizeof(md) ||
138 !tfetch_mem(tcp, addr + offset,
139 sizeof(md.flags), &md.flags)) {
140 tprint_unavailable();
141 } else {
142 PRINT_FIELD_FLAGS(md, flags,
143 seccomp_filter_flags,
144 "SECCOMP_FILTER_FLAG_???");
145 if (size > sizeof(md)) {
146 tprint_struct_next();
147 tprint_more_data_follows();
148 }
149 }
150 }
151
152 tprint_struct_end();
153 }
154
155 return 0;
156 }
157
158 static void
159 decode_regset(struct tcb *const tcp, const strace_iovec *iov,
160 const unsigned int nt)
161 {
162 switch (nt) {
163 case NT_PRSTATUS:
164 decode_prstatus_regset(tcp, iov->iov_base, iov->iov_len);
165 break;
166 case NT_FPREGSET:
167 decode_fpregset(tcp, iov->iov_base, iov->iov_len);
168 break;
169 default:
170 printaddr(iov->iov_base);
171 break;
172 }
173 }
174
175 static int
176 decode_getregset(struct tcb *const tcp, const kernel_ulong_t addr,
177 const unsigned int nt)
178 {
179 strace_iovec iov;
180
181 if (!fetch_struct_iovec(tcp, addr, &iov)) {
182 printaddr(addr);
183 return RVAL_DECODED;
184 }
185
186 if (entering(tcp)) {
187 set_tcb_priv_ulong(tcp, iov.iov_len);
188 } else {
189 const unsigned long old_len = get_tcb_priv_ulong(tcp);
190
191 tprint_struct_begin();
192 tprints_field_name("iov_base");
193 decode_regset(tcp, &iov, nt);
194 tprint_struct_next();
195
196 if (old_len == iov.iov_len) {
197 PRINT_FIELD_U(iov, iov_len);
198 } else {
199 tprints_field_name("iov_len");
200 PRINT_VAL_U(old_len);
201 tprint_value_changed();
202 PRINT_VAL_U(iov.iov_len);
203 }
204 tprint_struct_end();
205 }
206
207 return 0;
208 }
209
210 static int
211 decode_setregset(struct tcb *const tcp, const kernel_ulong_t addr,
212 const unsigned int nt)
213 {
214 strace_iovec iov;
215
216 if (entering(tcp)) {
217 if (!fetch_struct_iovec(tcp, addr, &iov)) {
218 printaddr(addr);
219 return RVAL_DECODED;
220 }
221
222 tprint_struct_begin();
223 tprints_field_name("iov_base");
224 decode_regset(tcp, &iov, nt);
225 tprint_struct_next();
226
227 PRINT_FIELD_U(iov, iov_len);
228
229 set_tcb_priv_ulong(tcp, iov.iov_len);
230 } else {
231 if (fetch_struct_iovec(tcp, addr, &iov) &&
232 get_tcb_priv_ulong(tcp) != iov.iov_len) {
233 tprint_value_changed();
234 PRINT_VAL_U(iov.iov_len);
235 }
236
237 tprint_struct_end();
238 }
239
240 return 0;
241 }
242
243 #ifdef PTRACE_GETREGS64
244 # include "arch_pt_regs64.c"
245 #endif
246
247 static int
248 decode_ptrace_entering(struct tcb *const tcp)
249 {
250 const kernel_ulong_t request = tcp->u_arg[0];
251 const int pid = tcp->u_arg[1];
252 const kernel_ulong_t addr = tcp->u_arg[2];
253 const kernel_ulong_t data = tcp->u_arg[3];
254
255 /*
256 * SPARC systems have the meaning of data and addr reversed
257 * for PTRACE_[GS]ETREGS and PTRACE_[GS]ETFPREGS:
258 * data is ignored and the registers are copied from/to the address addr.
259 */
260 #if defined SPARC || defined SPARC64
261 # define regs_addr addr
262 #else
263 # define regs_addr data
264 #endif
265
266 /* COMPAT_PTRACE_* */
267 #if HAVE_COMPAT_PTRACE_MACROS
268 if (current_personality != 1) {
269 switch (request) {
270 case COMPAT_PTRACE_GETREGS:
271 case COMPAT_PTRACE_SETREGS:
272 case COMPAT_PTRACE_GETFPREGS:
273 case COMPAT_PTRACE_SETFPREGS:
274 case COMPAT_PTRACE_GET_THREAD_AREA:
275 case COMPAT_PTRACE_SET_SYSCALL:
276 case COMPAT_PTRACE_GETVFPREGS:
277 case COMPAT_PTRACE_SETVFPREGS:
278 case COMPAT_PTRACE_GETHBPREGS:
279 case COMPAT_PTRACE_SETHBPREGS:
280 printxvals_ex(request, "COMPAT_PTRACE_???",
281 xlat_verbose(xlat_verbosity)
282 == XLAT_STYLE_RAW ? XLAT_STYLE_RAW
283 : XLAT_STYLE_VERBOSE,
284 compat_ptrace_cmds, NULL);
285 tprint_arg_next();
286 printpid(tcp, pid, PT_TGID);
287 tprint_arg_next();
288 printaddr(addr);
289 tprint_arg_next();
290 printaddr(data);
291 return RVAL_DECODED;
292 }
293 }
294 #endif /* HAVE_COMPAT_PTRACE_MACROS */
295
296 /* request */
297 printxval64(ptrace_cmds, request, "PTRACE_???");
298
299 if (request == PTRACE_TRACEME) {
300 /* pid, addr, and data are ignored. */
301 return RVAL_DECODED;
302 }
303
304 /* pid */
305 tprint_arg_next();
306 printpid(tcp, pid, PT_TGID);
307
308 switch (request) {
309 case PTRACE_ATTACH:
310 case PTRACE_INTERRUPT:
311 case PTRACE_KILL:
312 case PTRACE_LISTEN:
313 /* addr and data are ignored */
314 return RVAL_DECODED;
315 }
316
317 /* addr */
318 tprint_arg_next();
319 switch (request) {
320 case PTRACE_PEEKUSER:
321 #ifdef IA64
322 print_user_offset_addr(addr);
323 /* data is ignored */
324 return RVAL_DECODED | RVAL_HEX;
325 #endif
326 case PTRACE_POKEUSER:
327 print_user_offset_addr(addr);
328 break;
329 case PTRACE_GETREGSET:
330 case PTRACE_SETREGSET:
331 printxval(nt_descriptor_types, addr, "NT_???");
332 break;
333 case PTRACE_GETSIGMASK:
334 case PTRACE_SETSIGMASK:
335 case PTRACE_SECCOMP_GET_FILTER:
336 case PTRACE_SECCOMP_GET_METADATA:
337 case PTRACE_GET_SYSCALL_INFO:
338 PRINT_VAL_U(addr);
339 break;
340 case PTRACE_PEEKSIGINFO:
341 decode_peeksiginfo_args(tcp, addr);
342 break;
343 #ifdef PTRACE_SETREGS
344 case PTRACE_SETREGS:
345 decode_pt_regs(tcp, regs_addr);
346 return RVAL_DECODED;
347 #endif
348 #ifdef PTRACE_SETREGS64
349 case PTRACE_SETREGS64:
350 decode_pt_regs64(tcp, regs_addr);
351 return RVAL_DECODED;
352 #endif
353 #ifdef PTRACE_SETFPREGS
354 case PTRACE_SETFPREGS:
355 decode_pt_fpregs(tcp, regs_addr);
356 return RVAL_DECODED;
357 #endif
358 #ifdef PTRACE_GETREGS
359 case PTRACE_GETREGS:
360 /* print regs_addr on exiting syscall */
361 return 0;
362 #endif
363 #ifdef PTRACE_GETREGS64
364 case PTRACE_GETREGS64:
365 /* print regs_addr on exiting syscall */
366 return 0;
367 #endif
368 #ifdef PTRACE_GETFPREGS
369 case PTRACE_GETFPREGS:
370 /* print regs_addr on exiting syscall */
371 return 0;
372 #endif
373 #ifdef IA64
374 case PTRACE_PEEKDATA:
375 case PTRACE_PEEKTEXT:
376 printaddr(addr);
377 /* data is ignored */
378 return RVAL_DECODED | RVAL_HEX;
379 #endif /* IA64 */
380 default:
381 printaddr(addr);
382 }
383
384 /* data */
385 tprint_arg_next();
386 switch (request) {
387 case PTRACE_CONT:
388 case PTRACE_DETACH:
389 case PTRACE_SYSCALL:
390 #ifdef PTRACE_SINGLESTEP
391 case PTRACE_SINGLESTEP:
392 #endif
393 #ifdef PTRACE_SINGLEBLOCK
394 case PTRACE_SINGLEBLOCK:
395 #endif
396 #ifdef PTRACE_SYSEMU
397 case PTRACE_SYSEMU:
398 #endif
399 #ifdef PTRACE_SYSEMU_SINGLESTEP
400 case PTRACE_SYSEMU_SINGLESTEP:
401 #endif
402 printsignal(data);
403 break;
404 case PTRACE_SEIZE:
405 case PTRACE_SETOPTIONS:
406 #ifdef PTRACE_OLDSETOPTIONS
407 case PTRACE_OLDSETOPTIONS:
408 #endif
409 printflags64(ptrace_setoptions_flags, data, "PTRACE_O_???");
410 break;
411 case PTRACE_SETSIGINFO:
412 printsiginfo_at(tcp, data);
413 break;
414 case PTRACE_SETSIGMASK:
415 print_sigset_addr_len(tcp, data, addr);
416 break;
417 case PTRACE_GETREGSET:
418 return decode_getregset(tcp, data, addr);
419 case PTRACE_SETREGSET:
420 return decode_setregset(tcp, data, addr);
421 break;
422 case PTRACE_SECCOMP_GET_METADATA:
423 return decode_seccomp_metadata(tcp, data, addr);
424 #ifndef IA64
425 case PTRACE_PEEKDATA:
426 case PTRACE_PEEKTEXT:
427 case PTRACE_PEEKUSER:
428 #endif
429 case PTRACE_GETEVENTMSG:
430 case PTRACE_GETSIGINFO:
431 case PTRACE_GETSIGMASK:
432 case PTRACE_PEEKSIGINFO:
433 case PTRACE_SECCOMP_GET_FILTER:
434 case PTRACE_GET_SYSCALL_INFO:
435 if (verbose(tcp)) {
436 /* print data on exiting syscall */
437 return 0;
438 }
439 ATTRIBUTE_FALLTHROUGH;
440 default:
441 printaddr(data);
442 break;
443 }
444
445 return RVAL_DECODED;
446 }
447
448 static int
449 decode_ptrace_exiting(struct tcb *const tcp)
450 {
451 const kernel_ulong_t request = tcp->u_arg[0];
452 const kernel_ulong_t addr = tcp->u_arg[2];
453 const kernel_ulong_t data = tcp->u_arg[3];
454
455 switch (request) {
456 #ifndef IA64
457 case PTRACE_PEEKDATA:
458 case PTRACE_PEEKTEXT:
459 case PTRACE_PEEKUSER:
460 printnum_ptr(tcp, data);
461 break;
462 #endif
463 case PTRACE_GETEVENTMSG:
464 printnum_ulong(tcp, data);
465 break;
466 case PTRACE_GETREGSET:
467 return decode_getregset(tcp, data, addr);
468 case PTRACE_SETREGSET:
469 return decode_setregset(tcp, data, addr);
470 case PTRACE_GETSIGINFO:
471 printsiginfo_at(tcp, data);
472 break;
473 case PTRACE_GETSIGMASK:
474 print_sigset_addr_len(tcp, data, addr);
475 break;
476 case PTRACE_PEEKSIGINFO:
477 print_siginfo_array(tcp, data, tcp->u_rval);
478 break;
479 case PTRACE_SECCOMP_GET_FILTER:
480 print_seccomp_fprog(tcp, data, tcp->u_rval);
481 break;
482 case PTRACE_SECCOMP_GET_METADATA:
483 return decode_seccomp_metadata(tcp, data, tcp->u_rval);
484 case PTRACE_GET_SYSCALL_INFO:
485 print_ptrace_syscall_info(tcp, data, addr);
486 break;
487 #ifdef PTRACE_GETREGS
488 case PTRACE_GETREGS:
489 decode_pt_regs(tcp, regs_addr);
490 break;
491 #endif
492 #ifdef PTRACE_GETREGS64
493 case PTRACE_GETREGS64:
494 decode_pt_regs64(tcp, regs_addr);
495 break;
496 #endif
497 #ifdef PTRACE_GETFPREGS
498 case PTRACE_GETFPREGS:
499 decode_pt_fpregs(tcp, regs_addr);
500 break;
501 #endif
502 }
503
504 return 0;
505 }
506
507 SYS_FUNC(ptrace)
508 {
509 return entering(tcp) ? decode_ptrace_entering(tcp)
510 : decode_ptrace_exiting(tcp);
511 }