int sys_rt_sigprocmask(struct tcb *tcp) { sigset_t sigset; /* Note: arg[3] is the length of the sigset. */ if (entering(tcp)) { printxval(sigprocmaskcmds, tcp->u_arg[0], "SIG_???"); tprints(", "); if (!tcp->u_arg[1]) tprints("NULL, "); else if (copy_sigset_len(tcp, tcp->u_arg[1], &sigset, tcp->u_arg[3]) < 0) tprintf("%#lx, ", tcp->u_arg[1]); else { printsigmask(&sigset, 1); tprints(", "); } } else { if (!tcp->u_arg[2]) tprints("NULL"); else if (syserror(tcp)) tprintf("%#lx", tcp->u_arg[2]); else if (copy_sigset_len(tcp, tcp->u_arg[2], &sigset, tcp->u_arg[3]) < 0) tprints("[?]"); else printsigmask(&sigset, 1); tprintf(", %lu", tcp->u_arg[3]); } return 0; }
int sys_rt_sigtimedwait(struct tcb *tcp) { if (entering(tcp)) { sigset_t sigset; if (copy_sigset_len(tcp, tcp->u_arg[0], &sigset, tcp->u_arg[3]) < 0) tprints("[?]"); else printsigmask(&sigset, 1); tprints(", "); /* This is the only "return" parameter, */ if (tcp->u_arg[1] != 0) return 0; /* ... if it's NULL, can decode all on entry */ tprints("NULL, "); } else if (tcp->u_arg[1] != 0) { /* syscall exit, and u_arg[1] wasn't NULL */ printsiginfo_at(tcp, tcp->u_arg[1]); tprints(", "); } else { /* syscall exit, and u_arg[1] was NULL */ return 0; } print_timespec(tcp, tcp->u_arg[2]); tprintf(", %d", (int) tcp->u_arg[3]); return 0; };
int sys_sigsuspend(struct tcb *tcp) { if (entering(tcp)) { sigset_t sigm; long_to_sigset(tcp->u_arg[2], &sigm); printsigmask(&sigm, 0); } return 0; }
void print_sigset(struct tcb *tcp, long addr, int rt) { sigset_t ss; if (!addr) tprints("NULL"); else if (copy_sigset(tcp, addr, &ss) < 0) tprintf("%#lx", addr); else printsigmask(&ss, rt); }
int sys_rt_sigsuspend(struct tcb *tcp) { if (entering(tcp)) { sigset_t sigm; if (copy_sigset_len(tcp, tcp->u_arg[0], &sigm, tcp->u_arg[1]) < 0) tprints("[?]"); else printsigmask(&sigm, 1); } return 0; }
int sys_sigaction(struct tcb *tcp) { long addr; sigset_t sigset; struct old_sigaction sa; if (entering(tcp)) { printsignal(tcp->u_arg[0]); tprints(", "); addr = tcp->u_arg[1]; } else addr = tcp->u_arg[2]; if (addr == 0) tprints("NULL"); else if (!verbose(tcp)) tprintf("%#lx", addr); else if (umove(tcp, addr, &sa) < 0) tprints("{...}"); else { /* Architectures using function pointers, like * hppa, may need to manipulate the function pointer * to compute the result of a comparison. However, * the __sa_handler function pointer exists only in * the address space of the traced process, and can't * be manipulated by strace. In order to prevent the * compiler from generating code to manipulate * __sa_handler we cast the function pointers to long. */ if ((long)sa.__sa_handler == (long)SIG_ERR) tprints("{SIG_ERR, "); else if ((long)sa.__sa_handler == (long)SIG_DFL) tprints("{SIG_DFL, "); else if ((long)sa.__sa_handler == (long)SIG_IGN) tprints("{SIG_IGN, "); else tprintf("{%#lx, ", (long) sa.__sa_handler); long_to_sigset(sa.sa_mask, &sigset); printsigmask(&sigset, 0); tprints(", "); printflags(sigact_flags, sa.sa_flags, "SA_???"); #ifdef SA_RESTORER if (sa.sa_flags & SA_RESTORER) tprintf(", %p", sa.sa_restorer); #endif tprints("}"); } if (entering(tcp)) tprints(", "); else tprintf(", %#lx", (unsigned long) sa.sa_restorer); return 0; }
int sys_sigpending(struct tcb *tcp) { sigset_t sigset; if (exiting(tcp)) { if (syserror(tcp)) tprintf("%#lx", tcp->u_arg[0]); else if (copy_sigset(tcp, tcp->u_arg[0], &sigset) < 0) tprints("[?]"); else printsigmask(&sigset, 0); } return 0; }
int sys_sigsetmask(struct tcb *tcp) { if (entering(tcp)) { sigset_t sigm; long_to_sigset(tcp->u_arg[0], &sigm); printsigmask(&sigm, 0); } else if (!syserror(tcp)) { sigset_t sigm; long_to_sigset(tcp->u_rval, &sigm); tcp->auxstr = sprintsigmask("old mask ", &sigm, 0); return RVAL_HEX | RVAL_STR; } return 0; }
int sys_sigprocmask(struct tcb *tcp) { #ifdef ALPHA sigset_t ss; if (entering(tcp)) { /* * Alpha/OSF is different: it doesn't pass in two pointers, * but rather passes in the new bitmask as an argument and * then returns the old bitmask. This "works" because we * only have 64 signals to worry about. If you want more, * use of the rt_sigprocmask syscall is required. * Alpha: * old = osf_sigprocmask(how, new); * Everyone else: * ret = sigprocmask(how, &new, &old, ...); */ memcpy(&ss, &tcp->u_arg[1], sizeof(long)); printxval(sigprocmaskcmds, tcp->u_arg[0], "SIG_???"); tprints(", "); printsigmask(&ss, 0); } else if (!syserror(tcp)) { memcpy(&ss, &tcp->u_rval, sizeof(long)); tcp->auxstr = sprintsigmask("old mask ", &ss, 0); return RVAL_HEX | RVAL_STR; } #else /* !ALPHA */ if (entering(tcp)) { printxval(sigprocmaskcmds, tcp->u_arg[0], "SIG_???"); tprints(", "); print_sigset(tcp, tcp->u_arg[1], 0); tprints(", "); } else { if (!tcp->u_arg[2]) tprints("NULL"); else if (syserror(tcp)) tprintf("%#lx", tcp->u_arg[2]); else print_sigset(tcp, tcp->u_arg[2], 0); } #endif /* !ALPHA */ return 0; }
void print_sigset_addr_len(struct tcb *tcp, long addr, long len) { sigset_t ss; if (!addr) { tprints("NULL"); return; } /* Here len is usually equals NSIG / 8 or current_wordsize. * But we code this defensively: */ if (len < 0) { bad: tprintf("%#lx", addr); return; } if (len > NSIG / 8) len = NSIG / 8; sigemptyset(&ss); if (umoven(tcp, addr, len, (char *)&ss) < 0) goto bad; printsigmask(&ss); }
int sys_rt_sigaction(struct tcb *tcp) { struct new_sigaction sa; sigset_t sigset; long addr; int r; if (entering(tcp)) { printsignal(tcp->u_arg[0]); tprints(", "); addr = tcp->u_arg[1]; } else addr = tcp->u_arg[2]; if (addr == 0) { tprints("NULL"); goto after_sa; } if (!verbose(tcp)) { tprintf("%#lx", addr); goto after_sa; } #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 if (current_wordsize != sizeof(sa.sa_flags) && current_wordsize == 4) { struct new_sigaction32 sa32; r = umove(tcp, addr, &sa32); if (r >= 0) { memset(&sa, 0, sizeof(sa)); sa.__sa_handler = (void*)(unsigned long)sa32.__sa_handler; sa.sa_flags = sa32.sa_flags; sa.sa_restorer = (void*)(unsigned long)sa32.sa_restorer; /* Kernel treats sa_mask as an array of longs. * For 32-bit process, "long" is uint32_t, thus, for example, * 32th bit in sa_mask will end up as bit 0 in sa_mask[1]. * But for (64-bit) kernel, 32th bit in sa_mask is * 32th bit in 0th (64-bit) long! * For little-endian, it's the same. * For big-endian, we swap 32-bit words. */ sa.sa_mask[0] = sa32.sa_mask[0] + ((long)(sa32.sa_mask[1]) << 32); } } else #endif { r = umove(tcp, addr, &sa); } if (r < 0) { tprints("{...}"); goto after_sa; } /* Architectures using function pointers, like * hppa, may need to manipulate the function pointer * to compute the result of a comparison. However, * the __sa_handler function pointer exists only in * the address space of the traced process, and can't * be manipulated by strace. In order to prevent the * compiler from generating code to manipulate * __sa_handler we cast the function pointers to long. */ if ((long)sa.__sa_handler == (long)SIG_ERR) tprints("{SIG_ERR, "); else if ((long)sa.__sa_handler == (long)SIG_DFL) tprints("{SIG_DFL, "); else if ((long)sa.__sa_handler == (long)SIG_IGN) tprints("{SIG_IGN, "); else tprintf("{%#lx, ", (long) sa.__sa_handler); /* Questionable code below. * Kernel won't handle sys_rt_sigaction * with wrong sigset size (just returns EINVAL) * therefore tcp->u_arg[3(4)] _must_ be NSIG / 8 here, * and we always use smaller memcpy. */ sigemptyset(&sigset); #if defined(SPARC) || defined(SPARC64) if (tcp->u_arg[4] <= sizeof(sigset)) memcpy(&sigset, &sa.sa_mask, tcp->u_arg[4]); #else if (tcp->u_arg[3] <= sizeof(sigset)) memcpy(&sigset, &sa.sa_mask, tcp->u_arg[3]); #endif else memcpy(&sigset, &sa.sa_mask, sizeof(sigset)); printsigmask(&sigset, 1); tprints(", "); printflags(sigact_flags, sa.sa_flags, "SA_???"); #ifdef SA_RESTORER if (sa.sa_flags & SA_RESTORER) tprintf(", %p", sa.sa_restorer); #endif tprints("}"); after_sa: if (entering(tcp)) tprints(", "); else #if defined(SPARC) || defined(SPARC64) tprintf(", %#lx, %lu", tcp->u_arg[3], tcp->u_arg[4]); #elif defined(ALPHA) tprintf(", %lu, %#lx", tcp->u_arg[3], tcp->u_arg[4]); #else tprintf(", %lu", tcp->u_arg[3]); #endif return 0; }
static void decode_new_sigaction(struct tcb *tcp, long addr) { struct new_sigaction sa; sigset_t sigset; int r; if (!addr) { tprints("NULL"); return; } if (!verbose(tcp) || (exiting(tcp) && syserror(tcp))) { tprintf("%#lx", addr); return; } #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 if (current_wordsize != sizeof(sa.sa_flags) && current_wordsize == 4) { struct new_sigaction32 sa32; r = umove(tcp, addr, &sa32); if (r >= 0) { memset(&sa, 0, sizeof(sa)); sa.__sa_handler = (void*)(unsigned long)sa32.__sa_handler; sa.sa_flags = sa32.sa_flags; sa.sa_restorer = (void*)(unsigned long)sa32.sa_restorer; /* Kernel treats sa_mask as an array of longs. * For 32-bit process, "long" is uint32_t, thus, for example, * 32th bit in sa_mask will end up as bit 0 in sa_mask[1]. * But for (64-bit) kernel, 32th bit in sa_mask is * 32th bit in 0th (64-bit) long! * For little-endian, it's the same. * For big-endian, we swap 32-bit words. */ sa.sa_mask[0] = sa32.sa_mask[0] + ((long)(sa32.sa_mask[1]) << 32); } } else #endif { r = umove(tcp, addr, &sa); } if (r < 0) { tprints("{...}"); return; } /* Architectures using function pointers, like * hppa, may need to manipulate the function pointer * to compute the result of a comparison. However, * the __sa_handler function pointer exists only in * the address space of the traced process, and can't * be manipulated by strace. In order to prevent the * compiler from generating code to manipulate * __sa_handler we cast the function pointers to long. */ if ((long)sa.__sa_handler == (long)SIG_ERR) tprints("{SIG_ERR, "); else if ((long)sa.__sa_handler == (long)SIG_DFL) tprints("{SIG_DFL, "); else if ((long)sa.__sa_handler == (long)SIG_IGN) tprints("{SIG_IGN, "); else tprintf("{%#lx, ", (long) sa.__sa_handler); /* * Sigset size is in tcp->u_arg[4] (SPARC) * or in tcp->u_arg[3] (all other), * but kernel won't handle sys_rt_sigaction * with wrong sigset size (just returns EINVAL instead). * We just fetch the right size, which is NSIG / 8. */ sigemptyset(&sigset); memcpy(&sigset, &sa.sa_mask, NSIG / 8); printsigmask(&sigset); tprints(", "); printflags(sigact_flags, sa.sa_flags, "SA_???"); #ifdef SA_RESTORER if (sa.sa_flags & SA_RESTORER) tprintf(", %p", sa.sa_restorer); #endif tprints("}"); }