Branch data Line data Source code
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 : : * All rights reserved.
10 : : *
11 : : * Redistribution and use in source and binary forms, with or without
12 : : * modification, are permitted provided that the following conditions
13 : : * are met:
14 : : * 1. Redistributions of source code must retain the above copyright
15 : : * notice, this list of conditions and the following disclaimer.
16 : : * 2. Redistributions in binary form must reproduce the above copyright
17 : : * notice, this list of conditions and the following disclaimer in the
18 : : * documentation and/or other materials provided with the distribution.
19 : : * 3. The name of the author may not be used to endorse or promote products
20 : : * derived from this software without specific prior written permission.
21 : : *
22 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 : : */
33 : :
34 : : #include "defs.h"
35 : : #include "native_defs.h"
36 : : #include "nsig.h"
37 : : #include <sys/param.h>
38 : :
39 : : /* for struct iovec */
40 : : #include <sys/uio.h>
41 : :
42 : : /* for __X32_SYSCALL_BIT */
43 : : #include <asm/unistd.h>
44 : :
45 : : #include "regs.h"
46 : : #include "ptrace.h"
47 : :
48 : : #if defined(SPARC64)
49 : : # undef PTRACE_GETREGS
50 : : # define PTRACE_GETREGS PTRACE_GETREGS64
51 : : # undef PTRACE_SETREGS
52 : : # define PTRACE_SETREGS PTRACE_SETREGS64
53 : : #endif
54 : :
55 : : #if defined SPARC64
56 : : # include <asm/psrcompat.h>
57 : : #elif defined SPARC
58 : : # include <asm/psr.h>
59 : : #endif
60 : :
61 : : #ifdef IA64
62 : : # include <asm/rse.h>
63 : : #endif
64 : :
65 : : #ifndef NT_PRSTATUS
66 : : # define NT_PRSTATUS 1
67 : : #endif
68 : :
69 : : #include "syscall.h"
70 : :
71 : : /* Define these shorthand notations to simplify the syscallent files. */
72 : : #define TD TRACE_DESC
73 : : #define TF TRACE_FILE
74 : : #define TI TRACE_IPC
75 : : #define TN TRACE_NETWORK
76 : : #define TP TRACE_PROCESS
77 : : #define TS TRACE_SIGNAL
78 : : #define TM TRACE_MEMORY
79 : : #define TSC TRACE_SCHED
80 : : #define TC TRACE_CLOCK
81 : : #define TST TRACE_STAT
82 : : #define NF SYSCALL_NEVER_FAILS
83 : : #define MA MAX_ARGS
84 : : #define SI STACKTRACE_INVALIDATE_CACHE
85 : : #define SE STACKTRACE_CAPTURE_ON_ENTER
86 : : #define CST COMPAT_SYSCALL_TYPES
87 : :
88 : : #define SEN(syscall_name) SEN_ ## syscall_name, SYS_FUNC_NAME(sys_ ## syscall_name)
89 : :
90 : : const struct_sysent sysent0[] = {
91 : : #include "syscallent.h"
92 : : };
93 : :
94 : : #if SUPPORTED_PERSONALITIES > 1
95 : : # include PERSONALITY1_INCLUDE_FUNCS
96 : : static const struct_sysent sysent1[] = {
97 : : # include "syscallent1.h"
98 : : };
99 : : #endif
100 : :
101 : : #if SUPPORTED_PERSONALITIES > 2
102 : : # include PERSONALITY2_INCLUDE_FUNCS
103 : : static const struct_sysent sysent2[] = {
104 : : # include "syscallent2.h"
105 : : };
106 : : #endif
107 : :
108 : : /* Now undef them since short defines cause wicked namespace pollution. */
109 : : #undef SEN
110 : : #undef TD
111 : : #undef TF
112 : : #undef TI
113 : : #undef TN
114 : : #undef TP
115 : : #undef TS
116 : : #undef TM
117 : : #undef TSC
118 : : #undef TC
119 : : #undef TST
120 : : #undef NF
121 : : #undef MA
122 : : #undef SI
123 : : #undef SE
124 : : #undef CST
125 : :
126 : : /*
127 : : * `ioctlent[012].h' files are automatically generated by the auxiliary
128 : : * program `ioctlsort', such that the list is sorted by the `code' field.
129 : : * This has the side-effect of resolving the _IO.. macros into
130 : : * plain integers, eliminating the need to include here everything
131 : : * in "/usr/include".
132 : : */
133 : :
134 : : const char *const errnoent0[] = {
135 : : #include "errnoent.h"
136 : : };
137 : : const char *const signalent0[] = {
138 : : #include "signalent.h"
139 : : };
140 : : const struct_ioctlent ioctlent0[] = {
141 : : #include "ioctlent0.h"
142 : : };
143 : :
144 : : #if SUPPORTED_PERSONALITIES > 1
145 : : static const char *const errnoent1[] = {
146 : : # include "errnoent1.h"
147 : : };
148 : : static const char *const signalent1[] = {
149 : : # include "signalent1.h"
150 : : };
151 : : static const struct_ioctlent ioctlent1[] = {
152 : : # include "ioctlent1.h"
153 : : };
154 : : # include PERSONALITY0_INCLUDE_PRINTERS_DECLS
155 : : static const struct_printers printers0 = {
156 : : # include PERSONALITY0_INCLUDE_PRINTERS_DEFS
157 : : };
158 : : # include PERSONALITY1_INCLUDE_PRINTERS_DECLS
159 : : static const struct_printers printers1 = {
160 : : # include PERSONALITY1_INCLUDE_PRINTERS_DEFS
161 : : };
162 : : #endif
163 : :
164 : : #if SUPPORTED_PERSONALITIES > 2
165 : : static const char *const errnoent2[] = {
166 : : # include "errnoent2.h"
167 : : };
168 : : static const char *const signalent2[] = {
169 : : # include "signalent2.h"
170 : : };
171 : : static const struct_ioctlent ioctlent2[] = {
172 : : # include "ioctlent2.h"
173 : : };
174 : : # include PERSONALITY2_INCLUDE_PRINTERS_DECLS
175 : : static const struct_printers printers2 = {
176 : : # include PERSONALITY2_INCLUDE_PRINTERS_DEFS
177 : : };
178 : : #endif
179 : :
180 : : enum {
181 : : nsyscalls0 = ARRAY_SIZE(sysent0)
182 : : #if SUPPORTED_PERSONALITIES > 1
183 : : , nsyscalls1 = ARRAY_SIZE(sysent1)
184 : : # if SUPPORTED_PERSONALITIES > 2
185 : : , nsyscalls2 = ARRAY_SIZE(sysent2)
186 : : # endif
187 : : #endif
188 : : };
189 : :
190 : : enum {
191 : : nerrnos0 = ARRAY_SIZE(errnoent0)
192 : : #if SUPPORTED_PERSONALITIES > 1
193 : : , nerrnos1 = ARRAY_SIZE(errnoent1)
194 : : # if SUPPORTED_PERSONALITIES > 2
195 : : , nerrnos2 = ARRAY_SIZE(errnoent2)
196 : : # endif
197 : : #endif
198 : : };
199 : :
200 : : enum {
201 : : nsignals0 = ARRAY_SIZE(signalent0)
202 : : #if SUPPORTED_PERSONALITIES > 1
203 : : , nsignals1 = ARRAY_SIZE(signalent1)
204 : : # if SUPPORTED_PERSONALITIES > 2
205 : : , nsignals2 = ARRAY_SIZE(signalent2)
206 : : # endif
207 : : #endif
208 : : };
209 : :
210 : : enum {
211 : : nioctlents0 = ARRAY_SIZE(ioctlent0)
212 : : #if SUPPORTED_PERSONALITIES > 1
213 : : , nioctlents1 = ARRAY_SIZE(ioctlent1)
214 : : # if SUPPORTED_PERSONALITIES > 2
215 : : , nioctlents2 = ARRAY_SIZE(ioctlent2)
216 : : # endif
217 : : #endif
218 : : };
219 : :
220 : : #if SUPPORTED_PERSONALITIES > 1
221 : : const struct_sysent *sysent = sysent0;
222 : : const char *const *errnoent = errnoent0;
223 : : const char *const *signalent = signalent0;
224 : : const struct_ioctlent *ioctlent = ioctlent0;
225 : : const struct_printers *printers = &printers0;
226 : : #endif
227 : :
228 : : unsigned nsyscalls = nsyscalls0;
229 : : unsigned nerrnos = nerrnos0;
230 : : unsigned nsignals = nsignals0;
231 : : unsigned nioctlents = nioctlents0;
232 : :
233 : : const unsigned int nsyscall_vec[SUPPORTED_PERSONALITIES] = {
234 : : nsyscalls0,
235 : : #if SUPPORTED_PERSONALITIES > 1
236 : : nsyscalls1,
237 : : #endif
238 : : #if SUPPORTED_PERSONALITIES > 2
239 : : nsyscalls2,
240 : : #endif
241 : : };
242 : : const struct_sysent *const sysent_vec[SUPPORTED_PERSONALITIES] = {
243 : : sysent0,
244 : : #if SUPPORTED_PERSONALITIES > 1
245 : : sysent1,
246 : : #endif
247 : : #if SUPPORTED_PERSONALITIES > 2
248 : : sysent2,
249 : : #endif
250 : : };
251 : :
252 : : #if SUPPORTED_PERSONALITIES > 1
253 : : unsigned current_personality;
254 : :
255 : : # ifndef current_wordsize
256 : : unsigned current_wordsize;
257 : : static const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
258 : : PERSONALITY0_WORDSIZE,
259 : : PERSONALITY1_WORDSIZE,
260 : : # if SUPPORTED_PERSONALITIES > 2
261 : : PERSONALITY2_WORDSIZE,
262 : : # endif
263 : : };
264 : : # endif
265 : :
266 : : # ifndef current_klongsize
267 : : unsigned current_klongsize;
268 : : static const int personality_klongsize[SUPPORTED_PERSONALITIES] = {
269 : : PERSONALITY0_KLONGSIZE,
270 : : PERSONALITY1_KLONGSIZE,
271 : : # if SUPPORTED_PERSONALITIES > 2
272 : : PERSONALITY2_KLONGSIZE,
273 : : # endif
274 : : };
275 : : # endif
276 : :
277 : : void
278 : 23958 : set_personality(int personality)
279 : : {
280 : 23958 : nsyscalls = nsyscall_vec[personality];
281 : 23958 : sysent = sysent_vec[personality];
282 : :
283 [ + + + - ]: 23958 : switch (personality) {
284 : : case 0:
285 : 15476 : errnoent = errnoent0;
286 : 15476 : nerrnos = nerrnos0;
287 : 15476 : ioctlent = ioctlent0;
288 : 15476 : nioctlents = nioctlents0;
289 : 15476 : signalent = signalent0;
290 : 15476 : nsignals = nsignals0;
291 : 15476 : printers = &printers0;
292 : 15476 : break;
293 : :
294 : : case 1:
295 : 8477 : errnoent = errnoent1;
296 : 8477 : nerrnos = nerrnos1;
297 : 8477 : ioctlent = ioctlent1;
298 : 8477 : nioctlents = nioctlents1;
299 : 8477 : signalent = signalent1;
300 : 8477 : nsignals = nsignals1;
301 : 8477 : printers = &printers1;
302 : 8477 : break;
303 : :
304 : : # if SUPPORTED_PERSONALITIES > 2
305 : : case 2:
306 : 5 : errnoent = errnoent2;
307 : 5 : nerrnos = nerrnos2;
308 : 5 : ioctlent = ioctlent2;
309 : 5 : nioctlents = nioctlents2;
310 : 5 : signalent = signalent2;
311 : 5 : nsignals = nsignals2;
312 : 5 : printers = &printers2;
313 : 5 : break;
314 : : # endif
315 : : }
316 : :
317 : 23958 : current_personality = personality;
318 : : # ifndef current_wordsize
319 : 23958 : current_wordsize = personality_wordsize[personality];
320 : : # endif
321 : : # ifndef current_klongsize
322 : 23958 : current_klongsize = personality_klongsize[personality];
323 : : # endif
324 : 23958 : }
325 : :
326 : : static void
327 : 23323302 : update_personality(struct tcb *tcp, unsigned int personality)
328 : : {
329 [ + + ]: 23323302 : if (personality == current_personality)
330 : 23307145 : return;
331 : 16157 : set_personality(personality);
332 : :
333 [ + + ]: 16157 : if (personality == tcp->currpers)
334 : 15351 : return;
335 : 806 : tcp->currpers = personality;
336 : :
337 : : # undef PERSONALITY_NAMES
338 : : # if defined POWERPC64
339 : : # define PERSONALITY_NAMES {"64 bit", "32 bit"}
340 : : # elif defined X86_64
341 : : # define PERSONALITY_NAMES {"64 bit", "32 bit", "x32"}
342 : : # elif defined X32
343 : : # define PERSONALITY_NAMES {"x32", "32 bit"}
344 : : # elif defined AARCH64
345 : : # define PERSONALITY_NAMES {"64 bit", "32 bit"}
346 : : # elif defined TILE
347 : : # define PERSONALITY_NAMES {"64-bit", "32-bit"}
348 : : # endif
349 : : # ifdef PERSONALITY_NAMES
350 [ + + ]: 806 : if (!qflag) {
351 : : static const char *const names[] = PERSONALITY_NAMES;
352 : 12 : error_msg("[ Process PID=%d runs in %s mode. ]",
353 : : tcp->pid, names[personality]);
354 : : }
355 : : # endif
356 : : }
357 : : #endif
358 : :
359 : : #ifdef SYS_socket_subcall
360 : : static void
361 : 28707 : decode_socket_subcall(struct tcb *tcp)
362 : 28707 : {
363 : 28707 : const int call = tcp->u_arg[0];
364 : :
365 [ + + ][ + + ]: 28707 : if (call < 1 || call >= SYS_socket_nsubcalls)
366 : 18 : return;
367 : :
368 : 28689 : const kernel_ulong_t scno = SYS_socket_subcall + call;
369 : 28689 : const unsigned int nargs = sysent[scno].nargs;
370 : 28689 : uint64_t buf[nargs];
371 : :
372 [ + + ]: 28689 : if (umoven(tcp, tcp->u_arg[1], nargs * current_wordsize, buf) < 0)
373 : 20 : return;
374 : :
375 : 28669 : tcp->scno = scno;
376 : 28669 : tcp->qual_flg = qual_flags(scno);
377 : 28669 : tcp->s_ent = &sysent[scno];
378 : :
379 : : unsigned int i;
380 [ + + ]: 114969 : for (i = 0; i < nargs; ++i)
381 : 172524 : tcp->u_arg[i] = (sizeof(uint32_t) == current_wordsize)
382 [ + - ]: 86262 : ? ((uint32_t *) (void *) buf)[i] : buf[i];
383 : : }
384 : : #endif
385 : :
386 : : #ifdef SYS_ipc_subcall
387 : : static void
388 : 63 : decode_ipc_subcall(struct tcb *tcp)
389 : : {
390 : 63 : unsigned int call = tcp->u_arg[0];
391 : 63 : const unsigned int version = call >> 16;
392 : :
393 [ + + ]: 63 : if (version) {
394 : : # if defined S390 || defined S390X
395 : : return;
396 : : # else
397 : : # ifdef SPARC64
398 : : if (current_wordsize == 8)
399 : : return;
400 : : # endif
401 : 7 : set_tcb_priv_ulong(tcp, version);
402 : 7 : call &= 0xffff;
403 : : # endif
404 : : }
405 : :
406 [ + + ]: 63 : switch (call) {
407 : : case 1: case 2: case 3: case 4:
408 : : case 11: case 12: case 13: case 14:
409 : : case 21: case 22: case 23: case 24:
410 : 53 : break;
411 : : default:
412 : 10 : return;
413 : : }
414 : :
415 : 53 : tcp->scno = SYS_ipc_subcall + call;
416 : 53 : tcp->qual_flg = qual_flags(tcp->scno);
417 : 53 : tcp->s_ent = &sysent[tcp->scno];
418 : :
419 : 53 : const unsigned int n = tcp->s_ent->nargs;
420 : : unsigned int i;
421 [ + + ]: 260 : for (i = 0; i < n; i++)
422 : 207 : tcp->u_arg[i] = tcp->u_arg[i + 1];
423 : : }
424 : : #endif
425 : :
426 : : #ifdef LINUX_MIPSO32
427 : : static void
428 : : decode_mips_subcall(struct tcb *tcp)
429 : : {
430 : : if (!scno_is_valid(tcp->u_arg[0]))
431 : : return;
432 : : tcp->scno = tcp->u_arg[0];
433 : : tcp->qual_flg = qual_flags(tcp->scno);
434 : : tcp->s_ent = &sysent[tcp->scno];
435 : : memmove(&tcp->u_arg[0], &tcp->u_arg[1],
436 : : sizeof(tcp->u_arg) - sizeof(tcp->u_arg[0]));
437 : : /*
438 : : * Fetching the last arg of 7-arg syscalls (fadvise64_64
439 : : * and sync_file_range) requires additional code,
440 : : * see linux/mips/get_syscall_args.c
441 : : */
442 : : if (tcp->s_ent->nargs == MAX_ARGS) {
443 : : if (umoven(tcp,
444 : : mips_REG_SP + MAX_ARGS * sizeof(tcp->u_arg[0]),
445 : : sizeof(tcp->u_arg[0]),
446 : : &tcp->u_arg[MAX_ARGS - 1]) < 0)
447 : : tcp->u_arg[MAX_ARGS - 1] = 0;
448 : : }
449 : : }
450 : : #endif /* LINUX_MIPSO32 */
451 : :
452 : : static void
453 : 262108 : dumpio(struct tcb *tcp)
454 : : {
455 [ + + ]: 262108 : if (syserror(tcp))
456 : 236748 : return;
457 : :
458 : 25360 : int fd = tcp->u_arg[0];
459 [ + + ]: 25360 : if (fd < 0)
460 : 1198 : return;
461 : :
462 [ + + ]: 24162 : if (is_number_in_set(fd, &read_set)) {
463 [ + + + + : 547 : switch (tcp->s_ent->sen) {
+ ]
464 : : case SEN_read:
465 : : case SEN_pread:
466 : : case SEN_recv:
467 : : case SEN_recvfrom:
468 : : case SEN_mq_timedreceive:
469 : 376 : dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
470 : 376 : return;
471 : : case SEN_readv:
472 : : case SEN_preadv:
473 : : case SEN_preadv2:
474 : 90 : dumpiov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1],
475 : 90 : tcp->u_rval);
476 : 90 : return;
477 : : case SEN_recvmsg:
478 : 10 : dumpiov_in_msghdr(tcp, tcp->u_arg[1], tcp->u_rval);
479 : 10 : return;
480 : : case SEN_recvmmsg:
481 : 5 : dumpiov_in_mmsghdr(tcp, tcp->u_arg[1]);
482 : 5 : return;
483 : : }
484 : : }
485 [ + + ]: 23681 : if (is_number_in_set(fd, &write_set)) {
486 [ + + + + : 481 : switch (tcp->s_ent->sen) {
+ ]
487 : : case SEN_write:
488 : : case SEN_pwrite:
489 : : case SEN_send:
490 : : case SEN_sendto:
491 : : case SEN_mq_timedsend:
492 : 366 : dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
493 : 366 : break;
494 : : case SEN_writev:
495 : : case SEN_pwritev:
496 : : case SEN_pwritev2:
497 : : case SEN_vmsplice:
498 : 95 : dumpiov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1], -1);
499 : 95 : break;
500 : : case SEN_sendmsg:
501 : 5 : dumpiov_in_msghdr(tcp, tcp->u_arg[1], -1);
502 : 5 : break;
503 : : case SEN_sendmmsg:
504 : 5 : dumpiov_in_mmsghdr(tcp, tcp->u_arg[1]);
505 : 5 : break;
506 : : }
507 : : }
508 : : }
509 : :
510 : : /*
511 : : * Shuffle syscall numbers so that we don't have huge gaps in syscall table.
512 : : * The shuffling should be an involution: shuffle_scno(shuffle_scno(n)) == n.
513 : : */
514 : : static kernel_ulong_t
515 : 12 : shuffle_scno(kernel_ulong_t scno)
516 : : {
517 : : #if defined(ARM) || defined(AARCH64) /* So far only 32-bit ARM needs this */
518 : : if (scno < ARM_FIRST_SHUFFLED_SYSCALL)
519 : : return scno;
520 : :
521 : : /* __ARM_NR_cmpxchg? Swap with LAST_ORDINARY+1 */
522 : : if (scno == ARM_FIRST_SHUFFLED_SYSCALL)
523 : : return 0x000ffff0;
524 : : if (scno == 0x000ffff0)
525 : : return ARM_FIRST_SHUFFLED_SYSCALL;
526 : :
527 : : # define ARM_SECOND_SHUFFLED_SYSCALL (ARM_FIRST_SHUFFLED_SYSCALL + 1)
528 : : /*
529 : : * Is it ARM specific syscall?
530 : : * Swap [0x000f0000, 0x000f0000 + LAST_SPECIAL] range
531 : : * with [SECOND_SHUFFLED, SECOND_SHUFFLED + LAST_SPECIAL] range.
532 : : */
533 : : if (scno >= 0x000f0000 &&
534 : : scno <= 0x000f0000 + ARM_LAST_SPECIAL_SYSCALL) {
535 : : return scno - 0x000f0000 + ARM_SECOND_SHUFFLED_SYSCALL;
536 : : }
537 : : if (scno <= ARM_SECOND_SHUFFLED_SYSCALL + ARM_LAST_SPECIAL_SYSCALL) {
538 : : return scno + 0x000f0000 - ARM_SECOND_SHUFFLED_SYSCALL;
539 : : }
540 : : #endif /* ARM || AARCH64 */
541 : :
542 : 12 : return scno;
543 : : }
544 : :
545 : : const char *
546 : 233406 : err_name(unsigned long err)
547 : : {
548 [ + + ][ + + ]: 233406 : if ((err < nerrnos) && errnoent[err])
549 : 233391 : return errnoent[err];
550 : :
551 : 15 : return NULL;
552 : : }
553 : :
554 : : static long get_regs_error;
555 : :
556 : : void
557 : 5606 : clear_regs(void)
558 : : {
559 : 5606 : get_regs_error = -1;
560 : 5606 : }
561 : :
562 : : static int get_syscall_args(struct tcb *);
563 : : static int get_syscall_result(struct tcb *);
564 : : static int arch_get_scno(struct tcb *tcp);
565 : : static int arch_set_scno(struct tcb *, kernel_ulong_t);
566 : : static void get_error(struct tcb *, const bool);
567 : : static int arch_set_error(struct tcb *);
568 : : static int arch_set_success(struct tcb *);
569 : :
570 : : struct inject_opts *inject_vec[SUPPORTED_PERSONALITIES];
571 : :
572 : : static struct inject_opts *
573 : 43607 : tcb_inject_opts(struct tcb *tcp)
574 : : {
575 [ + - ]: 87214 : return (scno_in_range(tcp->scno) && tcp->inject_vec[current_personality])
576 [ + - ]: 87214 : ? &tcp->inject_vec[current_personality][tcp->scno] : NULL;
577 : : }
578 : :
579 : :
580 : : static long
581 : 31149 : tamper_with_syscall_entering(struct tcb *tcp, unsigned int *signo)
582 : : {
583 [ + + ]: 31149 : if (!tcp->inject_vec[current_personality]) {
584 : 3968 : tcp->inject_vec[current_personality] =
585 : 1984 : xcalloc(nsyscalls, sizeof(**inject_vec));
586 : 1984 : memcpy(tcp->inject_vec[current_personality],
587 : 1984 : inject_vec[current_personality],
588 : : nsyscalls * sizeof(**inject_vec));
589 : : }
590 : :
591 : 31149 : struct inject_opts *opts = tcb_inject_opts(tcp);
592 : :
593 [ + - ][ + + ]: 31149 : if (!opts || opts->first == 0)
594 : 3004 : return 0;
595 : :
596 : 28145 : --opts->first;
597 : :
598 [ + + ]: 28145 : if (opts->first != 0)
599 : 15682 : return 0;
600 : :
601 : 12463 : opts->first = opts->step;
602 : :
603 [ + + ]: 12463 : if (opts->signo > 0)
604 : 10 : *signo = opts->signo;
605 [ + + ][ + - ]: 12463 : if (opts->rval != INJECT_OPTS_RVAL_DEFAULT && !arch_set_scno(tcp, -1))
606 : 12458 : tcp->flags |= TCB_TAMPERED;
607 : :
608 : 12463 : return 0;
609 : : }
610 : :
611 : : static long
612 : 12458 : tamper_with_syscall_exiting(struct tcb *tcp)
613 : : {
614 : 12458 : struct inject_opts *opts = tcb_inject_opts(tcp);
615 : :
616 [ - + ]: 12458 : if (!opts)
617 : 0 : return 0;
618 : :
619 [ + + ]: 12458 : if (opts->rval >= 0) {
620 : 10 : kernel_long_t u_rval = tcp->u_rval;
621 : :
622 : 10 : tcp->u_rval = opts->rval;
623 [ - + ]: 10 : if (arch_set_success(tcp)) {
624 : 0 : tcp->u_rval = u_rval;
625 : : } else {
626 : 10 : tcp->u_error = 0;
627 : : }
628 : : } else {
629 : 12448 : unsigned long new_error = -opts->rval;
630 : :
631 [ + + ][ + - ]: 12448 : if (new_error != tcp->u_error && new_error <= MAX_ERRNO_VALUE) {
632 : 5463 : unsigned long u_error = tcp->u_error;
633 : :
634 : 5463 : tcp->u_error = new_error;
635 [ - + ]: 5463 : if (arch_set_error(tcp)) {
636 : 0 : tcp->u_error = u_error;
637 : : }
638 : : }
639 : : }
640 : :
641 : 12458 : return 0;
642 : : }
643 : :
644 : : static int
645 : 11661614 : trace_syscall_entering(struct tcb *tcp, unsigned int *sig)
646 : : {
647 : : int res, scno_good;
648 : :
649 : 11661614 : scno_good = res = get_scno(tcp);
650 [ - + ]: 11661614 : if (res == 0)
651 : 0 : return res;
652 [ + - ]: 11661614 : if (res == 1)
653 : 11661614 : res = get_syscall_args(tcp);
654 : :
655 [ - + ]: 11661614 : if (res != 1) {
656 : 0 : printleader(tcp);
657 [ # # ]: 0 : tprintf("%s(", scno_good == 1 ? tcp->s_ent->sys_name : "????");
658 : : /*
659 : : * " <unavailable>" will be added later by the code which
660 : : * detects ptrace errors.
661 : : */
662 : 0 : goto ret;
663 : : }
664 : :
665 : : #ifdef LINUX_MIPSO32
666 : : if (SEN_syscall == tcp->s_ent->sen)
667 : : decode_mips_subcall(tcp);
668 : : #endif
669 : :
670 : : #if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
671 [ + + + ]: 11661614 : switch (tcp->s_ent->sen) {
672 : : # ifdef SYS_socket_subcall
673 : : case SEN_socketcall:
674 : 28707 : decode_socket_subcall(tcp);
675 : 28707 : break;
676 : : # endif
677 : : # ifdef SYS_ipc_subcall
678 : : case SEN_ipc:
679 : 63 : decode_ipc_subcall(tcp);
680 : 63 : break;
681 : : # endif
682 : : }
683 : : #endif
684 : :
685 : : /* Restrain from fault injection while the trace executes strace code. */
686 [ + + ]: 11661614 : if (hide_log(tcp)) {
687 : 11035665 : tcp->qual_flg &= ~QUAL_INJECT;
688 : : }
689 : :
690 [ + + ]: 11661614 : switch (tcp->s_ent->sen) {
691 : : case SEN_execve:
692 : : case SEN_execveat:
693 : : #if defined SPARC || defined SPARC64
694 : : case SEN_execv:
695 : : #endif
696 : 5001 : tcp->flags &= ~TCB_HIDE_LOG;
697 : 5001 : break;
698 : : }
699 : :
700 [ + + ]: 11661614 : if (!(tcp->qual_flg & QUAL_TRACE)
701 [ + + ][ + + ]: 390575 : || (tracing_paths && !pathtrace_match(tcp))
702 : : ) {
703 : 11283459 : tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
704 : 11283459 : tcp->sys_func_rval = 0;
705 : 11283459 : return 0;
706 : : }
707 : :
708 : 378155 : tcp->flags &= ~TCB_FILTERED;
709 : :
710 [ + + ]: 378155 : if (hide_log(tcp)) {
711 : 102840 : res = 0;
712 : 102840 : goto ret;
713 : : }
714 : :
715 [ + + ]: 275315 : if (tcp->qual_flg & QUAL_INJECT)
716 : 31149 : tamper_with_syscall_entering(tcp, sig);
717 : :
718 [ + + ]: 275315 : if (cflag == CFLAG_ONLY_STATS) {
719 : 13137 : res = 0;
720 : 13137 : goto ret;
721 : : }
722 : :
723 : : #ifdef USE_LIBUNWIND
724 : : if (stack_trace_enabled) {
725 : : if (tcp->s_ent->sys_flags & STACKTRACE_CAPTURE_ON_ENTER)
726 : : unwind_capture_stacktrace(tcp);
727 : : }
728 : : #endif
729 : :
730 : 262178 : printleader(tcp);
731 : 262178 : tprintf("%s(", tcp->s_ent->sys_name);
732 [ + + ]: 262178 : if (tcp->qual_flg & QUAL_RAW)
733 : 8222 : res = printargs(tcp);
734 : : else
735 : 253956 : res = tcp->s_ent->sys_func(tcp);
736 : :
737 : 262178 : fflush(tcp->outf);
738 : : ret:
739 : 378155 : tcp->flags |= TCB_INSYSCALL;
740 : 378155 : tcp->sys_func_rval = res;
741 : : /* Measure the entrance time as late as possible to avoid errors. */
742 [ + + ][ + + ]: 378155 : if (Tflag || cflag)
743 : 71622 : gettimeofday(&tcp->etime, NULL);
744 : 378155 : return res;
745 : : }
746 : :
747 : : static bool
748 : 504077 : syscall_tampered(struct tcb *tcp)
749 : : {
750 : 504077 : return tcp->flags & TCB_TAMPERED;
751 : : }
752 : :
753 : : static int
754 : 11656047 : trace_syscall_exiting(struct tcb *tcp)
755 : : {
756 : : int sys_res;
757 : : struct timeval tv;
758 : : int res;
759 : : unsigned long u_error;
760 : : const char *u_error_str;
761 : :
762 : : /* Measure the exit time as early as possible to avoid errors. */
763 [ + + ][ + + ]: 11656047 : if (Tflag || cflag)
764 : 118613 : gettimeofday(&tv, NULL);
765 : :
766 : : #ifdef USE_LIBUNWIND
767 : : if (stack_trace_enabled) {
768 : : if (tcp->s_ent->sys_flags & STACKTRACE_INVALIDATE_CACHE)
769 : : unwind_cache_invalidate(tcp);
770 : : }
771 : : #endif
772 : :
773 : : #if SUPPORTED_PERSONALITIES > 1
774 : 11656047 : update_personality(tcp, tcp->currpers);
775 : : #endif
776 [ + + ]: 11656047 : res = (get_regs_error ? -1 : get_syscall_result(tcp));
777 [ + + ][ + + ]: 11656047 : if (filtered(tcp) || hide_log(tcp))
778 : : goto ret;
779 : :
780 [ + + ][ + + ]: 275020 : if (syserror(tcp) && syscall_tampered(tcp))
781 : 12458 : tamper_with_syscall_exiting(tcp);
782 : :
783 [ + + ]: 275020 : if (cflag) {
784 : 12917 : count_syscall(tcp, &tv);
785 [ + + ]: 12917 : if (cflag == CFLAG_ONLY_STATS) {
786 : 12912 : goto ret;
787 : : }
788 : : }
789 : :
790 : : /* If not in -ff mode, and printing_tcp != tcp,
791 : : * then the log currently does not end with output
792 : : * of _our syscall entry_, but with something else.
793 : : * We need to say which syscall's return is this.
794 : : *
795 : : * Forced reprinting via TCB_REPRINT is used only by
796 : : * "strace -ff -oLOG test/threaded_execve" corner case.
797 : : * It's the only case when -ff mode needs reprinting.
798 : : */
799 [ + + ][ + + ]: 262108 : if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
[ - + ]
800 : 20 : tcp->flags &= ~TCB_REPRINT;
801 : 20 : printleader(tcp);
802 : 20 : tprintf("<... %s resumed> ", tcp->s_ent->sys_name);
803 : : }
804 : 262108 : printing_tcp = tcp;
805 : :
806 : 262108 : tcp->s_prev_ent = NULL;
807 [ - + ]: 262108 : if (res != 1) {
808 : : /* There was error in one of prior ptrace ops */
809 : 0 : tprints(") ");
810 : 0 : tabto();
811 : 0 : tprints("= ? <unavailable>\n");
812 : 0 : line_ended();
813 : 0 : tcp->flags &= ~(TCB_INSYSCALL | TCB_TAMPERED);
814 : 0 : tcp->sys_func_rval = 0;
815 : 0 : free_tcb_priv_data(tcp);
816 : 0 : return res;
817 : : }
818 : 262108 : tcp->s_prev_ent = tcp->s_ent;
819 : :
820 : 262108 : sys_res = 0;
821 [ + + ]: 262108 : if (tcp->qual_flg & QUAL_RAW) {
822 : : /* sys_res = printargs(tcp); - but it's nop on sysexit */
823 : : } else {
824 : : /* FIXME: not_failing_only (IOW, option -z) is broken:
825 : : * failure of syscall is known only after syscall return.
826 : : * Thus we end up with something like this on, say, ENOENT:
827 : : * open("doesnt_exist", O_RDONLY <unfinished ...>
828 : : * {next syscall decode}
829 : : * whereas the intended result is that open(...) line
830 : : * is not shown at all.
831 : : */
832 [ - + ][ # # ]: 253886 : if (not_failing_only && tcp->u_error)
833 : 0 : goto ret; /* ignore failed syscalls */
834 [ + + ]: 253886 : if (tcp->sys_func_rval & RVAL_DECODED)
835 : 242460 : sys_res = tcp->sys_func_rval;
836 : : else
837 : 11426 : sys_res = tcp->s_ent->sys_func(tcp);
838 : : }
839 : :
840 : 262108 : tprints(") ");
841 : 262108 : tabto();
842 : 262108 : u_error = tcp->u_error;
843 : :
844 [ + + ]: 262108 : if (tcp->qual_flg & QUAL_RAW) {
845 [ + + ]: 8222 : if (u_error) {
846 : 3287 : tprintf("= -1 (errno %lu)", u_error);
847 : : } else {
848 : 4935 : tprintf("= %#" PRI_klx, tcp->u_rval);
849 : : }
850 [ + + ]: 8222 : if (syscall_tampered(tcp))
851 : 8222 : tprints(" (INJECTED)");
852 : : }
853 [ + - ][ + + ]: 253886 : else if (!(sys_res & RVAL_NONE) && u_error) {
854 [ + - + + : 233461 : switch (u_error) {
+ ]
855 : : /* Blocked signals do not interrupt any syscalls.
856 : : * In this case syscalls don't return ERESTARTfoo codes.
857 : : *
858 : : * Deadly signals set to SIG_DFL interrupt syscalls
859 : : * and kill the process regardless of which of the codes below
860 : : * is returned by the interrupted syscall.
861 : : * In some cases, kernel forces a kernel-generated deadly
862 : : * signal to be unblocked and set to SIG_DFL (and thus cause
863 : : * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
864 : : * or SIGILL. (The alternative is to leave process spinning
865 : : * forever on the faulty instruction - not useful).
866 : : *
867 : : * SIG_IGNed signals and non-deadly signals set to SIG_DFL
868 : : * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
869 : : * but kernel will always restart them.
870 : : */
871 : : case ERESTARTSYS:
872 : : /* Most common type of signal-interrupted syscall exit code.
873 : : * The system call will be restarted with the same arguments
874 : : * if SA_RESTART is set; otherwise, it will fail with EINTR.
875 : : */
876 : 5 : tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
877 : 5 : break;
878 : : case ERESTARTNOINTR:
879 : : /* Rare. For example, fork() returns this if interrupted.
880 : : * SA_RESTART is ignored (assumed set): the restart is unconditional.
881 : : */
882 : 0 : tprints("= ? ERESTARTNOINTR (To be restarted)");
883 : 0 : break;
884 : : case ERESTARTNOHAND:
885 : : /* pause(), rt_sigsuspend() etc use this code.
886 : : * SA_RESTART is ignored (assumed not set):
887 : : * syscall won't restart (will return EINTR instead)
888 : : * even after signal with SA_RESTART set. However,
889 : : * after SIG_IGN or SIG_DFL signal it will restart
890 : : * (thus the name "restart only if has no handler").
891 : : */
892 : 50 : tprints("= ? ERESTARTNOHAND (To be restarted if no handler)");
893 : 50 : break;
894 : : case ERESTART_RESTARTBLOCK:
895 : : /* Syscalls like nanosleep(), poll() which can't be
896 : : * restarted with their original arguments use this
897 : : * code. Kernel will execute restart_syscall() instead,
898 : : * which changes arguments before restarting syscall.
899 : : * SA_RESTART is ignored (assumed not set) similarly
900 : : * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
901 : : * since restart data is saved in "restart block"
902 : : * in task struct, and if signal handler uses a syscall
903 : : * which in turn saves another such restart block,
904 : : * old data is lost and restart becomes impossible)
905 : : */
906 : 20 : tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
907 : 20 : break;
908 : : default:
909 : 233386 : u_error_str = err_name(u_error);
910 [ + - ]: 233386 : if (u_error_str)
911 : 233386 : tprintf("= -1 %s (%s)",
912 : : u_error_str, strerror(u_error));
913 : : else
914 : 0 : tprintf("= -1 %lu (%s)",
915 : : u_error, strerror(u_error));
916 : 233386 : break;
917 : : }
918 [ + + ]: 233461 : if (syscall_tampered(tcp))
919 : 9168 : tprints(" (INJECTED)");
920 [ - + ][ # # ]: 233461 : if ((sys_res & RVAL_STR) && tcp->auxstr)
921 : 0 : tprintf(" (%s)", tcp->auxstr);
922 : : }
923 : : else {
924 [ - + ]: 20425 : if (sys_res & RVAL_NONE)
925 : 0 : tprints("= ?");
926 : : else {
927 [ + + + + : 20425 : switch (sys_res & RVAL_MASK) {
+ - ]
928 : : case RVAL_HEX:
929 : : #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
930 [ + + ]: 379 : if (current_wordsize < sizeof(tcp->u_rval)) {
931 : 71 : tprintf("= %#x",
932 : 71 : (unsigned int) tcp->u_rval);
933 : : } else
934 : : #endif
935 : : {
936 : 308 : tprintf("= %#" PRI_klx, tcp->u_rval);
937 : : }
938 : 379 : break;
939 : : case RVAL_OCTAL:
940 : 35 : tprints("= ");
941 : 35 : print_numeric_long_umask(tcp->u_rval);
942 : 35 : break;
943 : : case RVAL_UDECIMAL:
944 : : #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
945 [ + + ]: 246 : if (current_wordsize < sizeof(tcp->u_rval)) {
946 : 82 : tprintf("= %u",
947 : 82 : (unsigned int) tcp->u_rval);
948 : : } else
949 : : #endif
950 : : {
951 : 164 : tprintf("= %" PRI_klu, tcp->u_rval);
952 : : }
953 : 246 : break;
954 : : case RVAL_DECIMAL:
955 : 19540 : tprintf("= %" PRI_kld, tcp->u_rval);
956 : 19540 : break;
957 : : case RVAL_FD:
958 [ + + ]: 225 : if (show_fd_path) {
959 : 70 : tprints("= ");
960 : 70 : printfd(tcp, tcp->u_rval);
961 : : }
962 : : else
963 : 155 : tprintf("= %" PRI_kld, tcp->u_rval);
964 : 225 : break;
965 : : default:
966 : 0 : error_msg("invalid rval format");
967 : 0 : break;
968 : : }
969 : : }
970 [ + + ][ + - ]: 20425 : if ((sys_res & RVAL_STR) && tcp->auxstr)
971 : 358 : tprintf(" (%s)", tcp->auxstr);
972 [ + + ]: 20425 : if (syscall_tampered(tcp))
973 : 10 : tprints(" (INJECTED)");
974 : : }
975 [ + + ]: 262108 : if (Tflag) {
976 : 5 : tv_sub(&tv, &tv, &tcp->etime);
977 : 5 : tprintf(" <%ld.%06ld>",
978 : 5 : (long) tv.tv_sec, (long) tv.tv_usec);
979 : : }
980 : 262108 : tprints("\n");
981 : 262108 : dumpio(tcp);
982 : 262108 : line_ended();
983 : :
984 : : #ifdef USE_LIBUNWIND
985 : : if (stack_trace_enabled)
986 : : unwind_print_stacktrace(tcp);
987 : : #endif
988 : :
989 : : ret:
990 : 11656047 : tcp->flags &= ~(TCB_INSYSCALL | TCB_TAMPERED);
991 : 11656047 : tcp->sys_func_rval = 0;
992 : 11656047 : free_tcb_priv_data(tcp);
993 : 11656047 : return 0;
994 : : }
995 : :
996 : : int
997 : 23317661 : trace_syscall(struct tcb *tcp, unsigned int *signo)
998 : : {
999 : 23317661 : return exiting(tcp) ?
1000 [ + + ]: 23317661 : trace_syscall_exiting(tcp) : trace_syscall_entering(tcp, signo);
1001 : : }
1002 : :
1003 : : bool
1004 : 110 : is_erestart(struct tcb *tcp)
1005 : : {
1006 [ + + ]: 110 : switch (tcp->u_error) {
1007 : : case ERESTARTSYS:
1008 : : case ERESTARTNOINTR:
1009 : : case ERESTARTNOHAND:
1010 : : case ERESTART_RESTARTBLOCK:
1011 : 20 : return true;
1012 : : default:
1013 : 90 : return false;
1014 : : }
1015 : : }
1016 : :
1017 : : static unsigned long saved_u_error;
1018 : :
1019 : : void
1020 : 145 : temporarily_clear_syserror(struct tcb *tcp)
1021 : : {
1022 : 145 : saved_u_error = tcp->u_error;
1023 : 145 : tcp->u_error = 0;
1024 : 145 : }
1025 : :
1026 : : void
1027 : 145 : restore_cleared_syserror(struct tcb *tcp)
1028 : : {
1029 : 145 : tcp->u_error = saved_u_error;
1030 : 145 : }
1031 : :
1032 : : /*
1033 : : * Check the syscall return value register value for whether it is
1034 : : * a negated errno code indicating an error, or a success return value.
1035 : : */
1036 : : static inline bool
1037 : 11653646 : is_negated_errno(kernel_ulong_t val)
1038 : : {
1039 : : /* Linux kernel defines MAX_ERRNO to 4095. */
1040 : 11653646 : kernel_ulong_t max = -(kernel_long_t) 4095;
1041 : :
1042 : : #ifndef current_klongsize
1043 [ + + ]: 11653646 : if (current_klongsize < sizeof(val)) {
1044 : 101790 : val = (uint32_t) val;
1045 : 101790 : max = (uint32_t) max;
1046 : : }
1047 : : #endif /* !current_klongsize */
1048 : :
1049 : 11653646 : return val >= max;
1050 : : }
1051 : :
1052 : : #include "arch_regs.c"
1053 : :
1054 : : #ifdef HAVE_GETRVAL2
1055 : : # include "arch_getrval2.c"
1056 : : #endif
1057 : :
1058 : : void
1059 : 218 : print_pc(struct tcb *tcp)
1060 : : {
1061 : : #if defined ARCH_PC_REG
1062 : : # define ARCH_GET_PC 0
1063 : : #elif defined ARCH_PC_PEEK_ADDR
1064 : : kernel_ulong_t pc;
1065 : : # define ARCH_PC_REG pc
1066 : : # define ARCH_GET_PC upeek(tcp->pid, ARCH_PC_PEEK_ADDR, &pc)
1067 : : #else
1068 : : # error Neither ARCH_PC_REG nor ARCH_PC_PEEK_ADDR is defined
1069 : : #endif
1070 [ + + ]: 218 : if (get_regs_error || ARCH_GET_PC)
1071 [ + + ]: 10 : tprints(current_wordsize == 4 ? "[????????] "
1072 : : : "[????????????????] ");
1073 : : else
1074 [ + + ][ + + ]: 208 : tprintf(current_wordsize == 4
1075 : : ? "[%08" PRI_klx "] " : "[%016" PRI_klx "] ",
1076 : 247 : (kernel_ulong_t) ARCH_PC_REG);
1077 : 218 : }
1078 : :
1079 : : #include "getregs_old.h"
1080 : :
1081 : : #undef ptrace_getregset_or_getregs
1082 : : #undef ptrace_setregset_or_setregs
1083 : : #ifdef ARCH_REGS_FOR_GETREGSET
1084 : :
1085 : : # define ptrace_getregset_or_getregs ptrace_getregset
1086 : : static long
1087 : 23345458 : ptrace_getregset(pid_t pid)
1088 : : {
1089 : : # ifdef ARCH_IOVEC_FOR_GETREGSET
1090 : : /* variable iovec */
1091 : 23345458 : ARCH_IOVEC_FOR_GETREGSET.iov_len = sizeof(ARCH_REGS_FOR_GETREGSET);
1092 : 23345458 : return ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS,
1093 : : &ARCH_IOVEC_FOR_GETREGSET);
1094 : : # else
1095 : : /* constant iovec */
1096 : : static struct iovec io = {
1097 : : .iov_base = &ARCH_REGS_FOR_GETREGSET,
1098 : : .iov_len = sizeof(ARCH_REGS_FOR_GETREGSET)
1099 : : };
1100 : : return ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &io);
1101 : :
1102 : : # endif
1103 : : }
1104 : :
1105 : : # ifndef HAVE_GETREGS_OLD
1106 : : # define ptrace_setregset_or_setregs ptrace_setregset
1107 : : static int
1108 : : ptrace_setregset(pid_t pid)
1109 : : {
1110 : : # ifdef ARCH_IOVEC_FOR_GETREGSET
1111 : : /* variable iovec */
1112 : : return ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS,
1113 : : &ARCH_IOVEC_FOR_GETREGSET);
1114 : : # else
1115 : : /* constant iovec */
1116 : : static struct iovec io = {
1117 : : .iov_base = &ARCH_REGS_FOR_GETREGSET,
1118 : : .iov_len = sizeof(ARCH_REGS_FOR_GETREGSET)
1119 : : };
1120 : : return ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &io);
1121 : : # endif
1122 : : }
1123 : : # endif /* !HAVE_GETREGS_OLD */
1124 : :
1125 : : #elif defined ARCH_REGS_FOR_GETREGS
1126 : :
1127 : : # define ptrace_getregset_or_getregs ptrace_getregs
1128 : : static long
1129 : : ptrace_getregs(pid_t pid)
1130 : : {
1131 : : # if defined SPARC || defined SPARC64
1132 : : /* SPARC systems have the meaning of data and addr reversed */
1133 : : return ptrace(PTRACE_GETREGS, pid, (void *) &ARCH_REGS_FOR_GETREGS, 0);
1134 : : # else
1135 : : return ptrace(PTRACE_GETREGS, pid, NULL, &ARCH_REGS_FOR_GETREGS);
1136 : : # endif
1137 : : }
1138 : :
1139 : : # ifndef HAVE_GETREGS_OLD
1140 : : # define ptrace_setregset_or_setregs ptrace_setregs
1141 : : static int
1142 : : ptrace_setregs(pid_t pid)
1143 : : {
1144 : : # if defined SPARC || defined SPARC64
1145 : : /* SPARC systems have the meaning of data and addr reversed */
1146 : : return ptrace(PTRACE_SETREGS, pid, (void *) &ARCH_REGS_FOR_GETREGS, 0);
1147 : : # else
1148 : : return ptrace(PTRACE_SETREGS, pid, NULL, &ARCH_REGS_FOR_GETREGS);
1149 : : # endif
1150 : : }
1151 : : # endif /* !HAVE_GETREGS_OLD */
1152 : :
1153 : : #endif /* ARCH_REGS_FOR_GETREGSET || ARCH_REGS_FOR_GETREGS */
1154 : :
1155 : : void
1156 : 23345458 : get_regs(pid_t pid)
1157 : : {
1158 : : #undef USE_GET_SYSCALL_RESULT_REGS
1159 : : #ifdef ptrace_getregset_or_getregs
1160 : :
1161 : : # ifdef HAVE_GETREGS_OLD
1162 : : /*
1163 : : * Try PTRACE_GETREGSET/PTRACE_GETREGS first,
1164 : : * fallback to getregs_old.
1165 : : */
1166 : : static int use_getregs_old;
1167 [ + + ]: 23345458 : if (use_getregs_old < 0) {
1168 : 23340722 : get_regs_error = ptrace_getregset_or_getregs(pid);
1169 : 23340722 : return;
1170 [ + - ]: 4736 : } else if (use_getregs_old == 0) {
1171 : 4736 : get_regs_error = ptrace_getregset_or_getregs(pid);
1172 [ + - ]: 4736 : if (get_regs_error >= 0) {
1173 : 4736 : use_getregs_old = -1;
1174 : 4736 : return;
1175 : : }
1176 [ # # ][ # # ]: 0 : if (errno == EPERM || errno == ESRCH)
1177 : 0 : return;
1178 : 0 : use_getregs_old = 1;
1179 : : }
1180 : 0 : get_regs_error = getregs_old(pid);
1181 : : # else /* !HAVE_GETREGS_OLD */
1182 : : /* Assume that PTRACE_GETREGSET/PTRACE_GETREGS works. */
1183 : : get_regs_error = ptrace_getregset_or_getregs(pid);
1184 : : # endif /* !HAVE_GETREGS_OLD */
1185 : :
1186 : : #else /* !ptrace_getregset_or_getregs */
1187 : :
1188 : : # define USE_GET_SYSCALL_RESULT_REGS 1
1189 : : # warning get_regs is not implemented for this architecture yet
1190 : : get_regs_error = 0;
1191 : :
1192 : : #endif /* !ptrace_getregset_or_getregs */
1193 : : }
1194 : :
1195 : : #ifdef ptrace_setregset_or_setregs
1196 : : static int
1197 : : set_regs(pid_t pid)
1198 : : {
1199 : : return ptrace_setregset_or_setregs(pid);
1200 : : }
1201 : : #endif /* ptrace_setregset_or_setregs */
1202 : :
1203 : : struct sysent_buf {
1204 : : struct tcb *tcp;
1205 : : struct_sysent ent;
1206 : : char buf[sizeof("syscall_%lu") + sizeof(kernel_ulong_t) * 3];
1207 : : };
1208 : :
1209 : : static void
1210 : 12 : free_sysent_buf(void *ptr)
1211 : : {
1212 : 12 : struct sysent_buf *s = ptr;
1213 : 12 : s->tcp->s_prev_ent = s->tcp->s_ent = NULL;
1214 : 12 : free(ptr);
1215 : 12 : }
1216 : :
1217 : : /*
1218 : : * Returns:
1219 : : * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1220 : : * 1: ok, continue in trace_syscall_entering().
1221 : : * other: error, trace_syscall_entering() should print error indicator
1222 : : * ("????" etc) and bail out.
1223 : : */
1224 : : int
1225 : 11667255 : get_scno(struct tcb *tcp)
1226 : : {
1227 [ - + ]: 11667255 : if (get_regs_error)
1228 : 0 : return -1;
1229 : :
1230 : 11667255 : int rc = arch_get_scno(tcp);
1231 [ - + ]: 11667255 : if (rc != 1)
1232 : 0 : return rc;
1233 : :
1234 [ + + ]: 11667255 : if (scno_is_valid(tcp->scno)) {
1235 : 11667243 : tcp->s_ent = &sysent[tcp->scno];
1236 : 11667243 : tcp->qual_flg = qual_flags(tcp->scno);
1237 : : } else {
1238 : 12 : struct sysent_buf *s = xcalloc(1, sizeof(*s));
1239 : :
1240 : 12 : s->tcp = tcp;
1241 : 12 : s->ent.nargs = MAX_ARGS;
1242 : 12 : s->ent.sen = SEN_printargs;
1243 : 12 : s->ent.sys_func = printargs;
1244 : 12 : s->ent.sys_name = s->buf;
1245 : 12 : sprintf(s->buf, "syscall_%" PRI_klu, shuffle_scno(tcp->scno));
1246 : :
1247 : 12 : tcp->s_ent = &s->ent;
1248 : 12 : tcp->qual_flg = QUAL_RAW | DEFAULT_QUAL_FLAGS;
1249 : :
1250 : 12 : set_tcb_priv_data(tcp, s, free_sysent_buf);
1251 : :
1252 [ - + ]: 12 : if (debug_flag)
1253 : 0 : error_msg("pid %d invalid syscall %" PRI_kld,
1254 : : tcp->pid, tcp->scno);
1255 : : }
1256 : 11667255 : return 1;
1257 : : }
1258 : :
1259 : : #ifdef USE_GET_SYSCALL_RESULT_REGS
1260 : : static int get_syscall_result_regs(struct tcb *);
1261 : : #endif
1262 : :
1263 : : /* Returns:
1264 : : * 1: ok, continue in trace_syscall_exiting().
1265 : : * -1: error, trace_syscall_exiting() should print error indicator
1266 : : * ("????" etc) and bail out.
1267 : : */
1268 : : static int
1269 : 11655995 : get_syscall_result(struct tcb *tcp)
1270 : : {
1271 : : #ifdef USE_GET_SYSCALL_RESULT_REGS
1272 : : if (get_syscall_result_regs(tcp))
1273 : : return -1;
1274 : : #endif
1275 : 11655995 : tcp->u_error = 0;
1276 : 11655995 : get_error(tcp, !(tcp->s_ent->sys_flags & SYSCALL_NEVER_FAILS));
1277 : :
1278 : 11655995 : return 1;
1279 : : }
1280 : :
1281 : : #include "get_scno.c"
1282 : : #include "set_scno.c"
1283 : : #include "get_syscall_args.c"
1284 : : #ifdef USE_GET_SYSCALL_RESULT_REGS
1285 : : # include "get_syscall_result.c"
1286 : : #endif
1287 : : #include "get_error.c"
1288 : : #include "set_error.c"
1289 : : #ifdef HAVE_GETREGS_OLD
1290 : : # include "getregs_old.c"
1291 : : #endif
1292 : :
1293 : : const char *
1294 : 10 : syscall_name(kernel_ulong_t scno)
1295 : : {
1296 : : #if defined X32_PERSONALITY_NUMBER && defined __X32_SYSCALL_BIT
1297 [ - + ]: 10 : if (current_personality == X32_PERSONALITY_NUMBER)
1298 : 0 : scno &= ~__X32_SYSCALL_BIT;
1299 : : #endif
1300 [ + + ]: 10 : return scno_is_valid(scno) ? sysent[scno].sys_name: NULL;
1301 : : }
|