static int trace_syscall_exiting(struct tcb *tcp) { int sys_res; struct timeval tv; int res; long u_error; /* Measure the exit time as early as possible to avoid errors. */ if (Tflag || cflag) gettimeofday(&tv, NULL); #ifdef USE_LIBUNWIND if (stack_trace_enabled) { if (tcp->s_ent->sys_flags & STACKTRACE_INVALIDATE_CACHE) unwind_cache_invalidate(tcp); } #endif #if SUPPORTED_PERSONALITIES > 1 update_personality(tcp, tcp->currpers); #endif res = (get_regs_error ? -1 : get_syscall_result(tcp)); if (res == 1) { if (filtered(tcp) || hide_log_until_execve) goto ret; } if (cflag) { count_syscall(tcp, &tv); if (cflag == CFLAG_ONLY_STATS) { goto ret; } } /* If not in -ff mode, and printing_tcp != tcp, * then the log currently does not end with output * of _our syscall entry_, but with something else. * We need to say which syscall's return is this. * * Forced reprinting via TCB_REPRINT is used only by * "strace -ff -oLOG test/threaded_execve" corner case. * It's the only case when -ff mode needs reprinting. */ if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) { tcp->flags &= ~TCB_REPRINT; printleader(tcp); if (tcp->qual_flg & UNDEFINED_SCNO) tprintf("<... %s resumed> ", undefined_scno_name(tcp)); else tprintf("<... %s resumed> ", tcp->s_ent->sys_name); } printing_tcp = tcp; tcp->s_prev_ent = NULL; if (res != 1) { /* There was error in one of prior ptrace ops */ tprints(") "); tabto(); tprints("= ? <unavailable>\n"); line_ended(); tcp->flags &= ~TCB_INSYSCALL; return res; } tcp->s_prev_ent = tcp->s_ent; sys_res = 0; if (tcp->qual_flg & QUAL_RAW) { /* sys_res = printargs(tcp); - but it's nop on sysexit */ } else { /* FIXME: not_failing_only (IOW, option -z) is broken: * failure of syscall is known only after syscall return. * Thus we end up with something like this on, say, ENOENT: * open("doesnt_exist", O_RDONLY <unfinished ...> * {next syscall decode} * whereas the intended result is that open(...) line * is not shown at all. */ if (not_failing_only && tcp->u_error) goto ret; /* ignore failed syscalls */ sys_res = tcp->s_ent->sys_func(tcp); } tprints(") "); tabto(); u_error = tcp->u_error; if (tcp->qual_flg & QUAL_RAW) { if (u_error) tprintf("= -1 (errno %ld)", u_error); else tprintf("= %#lx", tcp->u_rval); } else if (!(sys_res & RVAL_NONE) && u_error) { switch (u_error) { /* Blocked signals do not interrupt any syscalls. * In this case syscalls don't return ERESTARTfoo codes. * * Deadly signals set to SIG_DFL interrupt syscalls * and kill the process regardless of which of the codes below * is returned by the interrupted syscall. * In some cases, kernel forces a kernel-generated deadly * signal to be unblocked and set to SIG_DFL (and thus cause * death) if it is blocked or SIG_IGNed: for example, SIGSEGV * or SIGILL. (The alternative is to leave process spinning * forever on the faulty instruction - not useful). * * SIG_IGNed signals and non-deadly signals set to SIG_DFL * (for example, SIGCHLD, SIGWINCH) interrupt syscalls, * but kernel will always restart them. */ case ERESTARTSYS: /* Most common type of signal-interrupted syscall exit code. * The system call will be restarted with the same arguments * if SA_RESTART is set; otherwise, it will fail with EINTR. */ tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)"); break; case ERESTARTNOINTR: /* Rare. For example, fork() returns this if interrupted. * SA_RESTART is ignored (assumed set): the restart is unconditional. */ tprints("= ? ERESTARTNOINTR (To be restarted)"); break; case ERESTARTNOHAND: /* pause(), rt_sigsuspend() etc use this code. * SA_RESTART is ignored (assumed not set): * syscall won't restart (will return EINTR instead) * even after signal with SA_RESTART set. However, * after SIG_IGN or SIG_DFL signal it will restart * (thus the name "restart only if has no handler"). */ tprints("= ? ERESTARTNOHAND (To be restarted if no handler)"); break; case ERESTART_RESTARTBLOCK: /* Syscalls like nanosleep(), poll() which can't be * restarted with their original arguments use this * code. Kernel will execute restart_syscall() instead, * which changes arguments before restarting syscall. * SA_RESTART is ignored (assumed not set) similarly * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART * since restart data is saved in "restart block" * in task struct, and if signal handler uses a syscall * which in turn saves another such restart block, * old data is lost and restart becomes impossible) */ tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)"); break; default: if ((unsigned long) u_error < nerrnos && errnoent[u_error]) tprintf("= -1 %s (%s)", errnoent[u_error], strerror(u_error)); else tprintf("= -1 ERRNO_%lu (%s)", u_error, strerror(u_error)); break; } if ((sys_res & RVAL_STR) && tcp->auxstr) tprintf(" (%s)", tcp->auxstr); } else { if (sys_res & RVAL_NONE) tprints("= ?"); else { switch (sys_res & RVAL_MASK) { case RVAL_HEX: #if SUPPORTED_PERSONALITIES > 1 if (current_wordsize < sizeof(long)) tprintf("= %#x", (unsigned int) tcp->u_rval); else #endif tprintf("= %#lx", tcp->u_rval); break; case RVAL_OCTAL: tprintf("= %#lo", tcp->u_rval); break; case RVAL_UDECIMAL: tprintf("= %lu", tcp->u_rval); break; case RVAL_DECIMAL: tprintf("= %ld", tcp->u_rval); break; case RVAL_FD: if (show_fd_path) { tprints("= "); printfd(tcp, tcp->u_rval); } else tprintf("= %ld", tcp->u_rval); break; #if defined(LINUX_MIPSN32) || defined(X32) /* case RVAL_LHEX: tprintf("= %#llx", tcp->u_lrval); break; case RVAL_LOCTAL: tprintf("= %#llo", tcp->u_lrval); break; */ case RVAL_LUDECIMAL: tprintf("= %llu", tcp->u_lrval); break; /* case RVAL_LDECIMAL: tprintf("= %lld", tcp->u_lrval); break; */ #endif default: fprintf(stderr, "invalid rval format\n"); break; } } if ((sys_res & RVAL_STR) && tcp->auxstr) tprintf(" (%s)", tcp->auxstr); } if (Tflag) { tv_sub(&tv, &tv, &tcp->etime); tprintf(" <%ld.%06ld>", (long) tv.tv_sec, (long) tv.tv_usec); } tprints("\n"); dumpio(tcp); line_ended(); #ifdef USE_LIBUNWIND if (stack_trace_enabled) unwind_print_stacktrace(tcp); #endif ret: tcp->flags &= ~TCB_INSYSCALL; return 0; }
int syscall_exiting_trace(struct tcb *tcp, struct timeval tv, int res) { if (syserror(tcp) && syscall_tampered(tcp)) tamper_with_syscall_exiting(tcp); if (cflag) { count_syscall(tcp, &tv); if (cflag == CFLAG_ONLY_STATS) { return 0; } } /* If not in -ff mode, and printing_tcp != tcp, * then the log currently does not end with output * of _our syscall entry_, but with something else. * We need to say which syscall's return is this. * * Forced reprinting via TCB_REPRINT is used only by * "strace -ff -oLOG test/threaded_execve" corner case. * It's the only case when -ff mode needs reprinting. */ if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) { tcp->flags &= ~TCB_REPRINT; printleader(tcp); tprintf("<... %s resumed> ", tcp->s_ent->sys_name); } printing_tcp = tcp; tcp->s_prev_ent = NULL; if (res != 1) { /* There was error in one of prior ptrace ops */ tprints(") "); tabto(); tprints("= ? <unavailable>\n"); line_ended(); return res; } tcp->s_prev_ent = tcp->s_ent; int sys_res = 0; if (raw(tcp)) { /* sys_res = printargs(tcp); - but it's nop on sysexit */ } else { /* FIXME: not_failing_only (IOW, option -z) is broken: * failure of syscall is known only after syscall return. * Thus we end up with something like this on, say, ENOENT: * open("does_not_exist", O_RDONLY <unfinished ...> * {next syscall decode} * whereas the intended result is that open(...) line * is not shown at all. */ if (not_failing_only && tcp->u_error) return 0; /* ignore failed syscalls */ if (tcp->sys_func_rval & RVAL_DECODED) sys_res = tcp->sys_func_rval; else sys_res = tcp->s_ent->sys_func(tcp); } tprints(") "); tabto(); unsigned long u_error = tcp->u_error; if (raw(tcp)) { if (u_error) { tprintf("= -1 (errno %lu)", u_error); } else { tprintf("= %#" PRI_klx, tcp->u_rval); } if (syscall_tampered(tcp)) tprints(" (INJECTED)"); } else if (!(sys_res & RVAL_NONE) && u_error) { const char *u_error_str; switch (u_error) { /* Blocked signals do not interrupt any syscalls. * In this case syscalls don't return ERESTARTfoo codes. * * Deadly signals set to SIG_DFL interrupt syscalls * and kill the process regardless of which of the codes below * is returned by the interrupted syscall. * In some cases, kernel forces a kernel-generated deadly * signal to be unblocked and set to SIG_DFL (and thus cause * death) if it is blocked or SIG_IGNed: for example, SIGSEGV * or SIGILL. (The alternative is to leave process spinning * forever on the faulty instruction - not useful). * * SIG_IGNed signals and non-deadly signals set to SIG_DFL * (for example, SIGCHLD, SIGWINCH) interrupt syscalls, * but kernel will always restart them. */ case ERESTARTSYS: /* Most common type of signal-interrupted syscall exit code. * The system call will be restarted with the same arguments * if SA_RESTART is set; otherwise, it will fail with EINTR. */ tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)"); break; case ERESTARTNOINTR: /* Rare. For example, fork() returns this if interrupted. * SA_RESTART is ignored (assumed set): the restart is unconditional. */ tprints("= ? ERESTARTNOINTR (To be restarted)"); break; case ERESTARTNOHAND: /* pause(), rt_sigsuspend() etc use this code. * SA_RESTART is ignored (assumed not set): * syscall won't restart (will return EINTR instead) * even after signal with SA_RESTART set. However, * after SIG_IGN or SIG_DFL signal it will restart * (thus the name "restart only if has no handler"). */ tprints("= ? ERESTARTNOHAND (To be restarted if no handler)"); break; case ERESTART_RESTARTBLOCK: /* Syscalls like nanosleep(), poll() which can't be * restarted with their original arguments use this * code. Kernel will execute restart_syscall() instead, * which changes arguments before restarting syscall. * SA_RESTART is ignored (assumed not set) similarly * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART * since restart data is saved in "restart block" * in task struct, and if signal handler uses a syscall * which in turn saves another such restart block, * old data is lost and restart becomes impossible) */ tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)"); break; default: u_error_str = err_name(u_error); if (u_error_str) tprintf("= -1 %s (%s)", u_error_str, strerror(u_error)); else tprintf("= -1 %lu (%s)", u_error, strerror(u_error)); break; } if (syscall_tampered(tcp)) tprints(" (INJECTED)"); if ((sys_res & RVAL_STR) && tcp->auxstr) tprintf(" (%s)", tcp->auxstr); } else { if (sys_res & RVAL_NONE) tprints("= ?"); else { switch (sys_res & RVAL_MASK) { case RVAL_HEX: #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG if (current_wordsize < sizeof(tcp->u_rval)) { tprintf("= %#x", (unsigned int) tcp->u_rval); } else #endif { tprintf("= %#" PRI_klx, tcp->u_rval); } break; case RVAL_OCTAL: tprints("= "); print_numeric_long_umask(tcp->u_rval); break; case RVAL_UDECIMAL: #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG if (current_wordsize < sizeof(tcp->u_rval)) { tprintf("= %u", (unsigned int) tcp->u_rval); } else #endif { tprintf("= %" PRI_klu, tcp->u_rval); } break; case RVAL_DECIMAL: tprintf("= %" PRI_kld, tcp->u_rval); break; case RVAL_FD: if (show_fd_path) { tprints("= "); printfd(tcp, tcp->u_rval); } else tprintf("= %" PRI_kld, tcp->u_rval); break; default: error_msg("invalid rval format"); break; } } if ((sys_res & RVAL_STR) && tcp->auxstr) tprintf(" (%s)", tcp->auxstr); if (syscall_tampered(tcp)) tprints(" (INJECTED)"); } if (Tflag) { tv_sub(&tv, &tv, &tcp->etime); tprintf(" <%ld.%06ld>", (long) tv.tv_sec, (long) tv.tv_usec); } tprints("\n"); dumpio(tcp); line_ended(); #ifdef USE_LIBUNWIND if (stack_trace_enabled) unwind_print_stacktrace(tcp); #endif return 0; }