/* Params are pointed to by u_arg[0], offset is in bytes */ int sys_old_mmap(struct tcb *tcp) { long u_arg[6]; #if defined(IA64) /* * IA64 processes never call this routine, they only use the * new 'sys_mmap' interface. Only IA32 processes come here. */ int i; unsigned narrow_arg[6]; if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1) return 0; for (i = 0; i < 6; i++) u_arg[i] = (unsigned long) narrow_arg[i]; #elif defined(X86_64) /* We are here only in personality 1 (i386) */ int i; unsigned narrow_arg[6]; if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1) return 0; for (i = 0; i < 6; ++i) u_arg[i] = (unsigned long) narrow_arg[i]; #else if (umoven(tcp, tcp->u_arg[0], sizeof(u_arg), (char *) u_arg) == -1) return 0; #endif return print_mmap(tcp, u_arg, (unsigned long) u_arg[5]); }
static void printargv(struct tcb *tcp, long addr) { union { unsigned int p32; unsigned long p64; char data[sizeof(long)]; } cp; const char *sep; unsigned int n = 0; unsigned wordsize = current_wordsize; cp.p64 = 1; for (sep = ""; !abbrev(tcp) || n < max_strlen / 2; sep = ", ", ++n) { if (umoven(tcp, addr, wordsize, cp.data) < 0) { tprintf("%#lx", addr); return; } if (wordsize == 4) cp.p64 = cp.p32; if (cp.p64 == 0) break; tprints(sep); printstr(tcp, cp.p64, -1); addr += wordsize; } if (cp.p64) tprintf("%s...", sep); }
void print_sigset_addr_len(struct tcb *tcp, long addr, long len) { char mask[NSIG / 8]; 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; else len = (len + 3) & ~3; if (umoven(tcp, addr, len, mask) < 0) goto bad; tprints(sprintsigmask_n("", mask, len)); }
static void decode_socket_subcall(struct tcb *tcp) { unsigned long addr; unsigned int n; if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls) return; tcp->scno = SYS_socket_subcall + tcp->u_arg[0]; tcp->qual_flg = qual_flags[tcp->scno]; tcp->s_ent = &sysent[tcp->scno]; addr = tcp->u_arg[1]; n = tcp->s_ent->nargs; if (sizeof(tcp->u_arg[0]) == current_wordsize) { memset(tcp->u_arg, 0, n * sizeof(tcp->u_arg[0])); (void) umoven(tcp, addr, n * sizeof(tcp->u_arg[0]), tcp->u_arg); } else { unsigned int args[n]; unsigned int i; memset(args, 0, sizeof(args)); (void) umove(tcp, addr, &args); for (i = 0; i < n; ++i) tcp->u_arg[i] = args[i]; } }
static int do_pipe(struct tcb *tcp, int flags_arg) { if (exiting(tcp)) { if (syserror(tcp)) { tprintf("%#lx", tcp->u_arg[0]); } else { #if !defined(SPARC) && !defined(SPARC64) && !defined(SH) && !defined(IA64) int fds[2]; if (umoven(tcp, tcp->u_arg[0], sizeof fds, (char *) fds) < 0) tprints("[...]"); else tprintf("[%u, %u]", fds[0], fds[1]); #elif defined(SPARC) || defined(SPARC64) || defined(SH) || defined(IA64) tprintf("[%lu, %lu]", tcp->u_rval, getrval2(tcp)); #else tprintf("%#lx", tcp->u_arg[0]); #endif } if (flags_arg >= 0) { tprints(", "); printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); } } return 0; }
int sys_mincore(struct tcb *tcp) { if (entering(tcp)) { tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); } else { unsigned long i, len; char *vec = NULL; len = tcp->u_arg[1]; if (syserror(tcp) || tcp->u_arg[2] == 0 || (vec = malloc(len)) == NULL || umoven(tcp, tcp->u_arg[2], len, vec) < 0) tprintf("%#lx", tcp->u_arg[2]); else { tprints("["); for (i = 0; i < len; i++) { if (abbrev(tcp) && i >= max_strlen) { tprints("..."); break; } tprints((vec[i] & 1) ? "1" : "0"); } tprints("]"); } free(vec); } return 0; }
int sys_getgroups(struct tcb *tcp) { unsigned long len; if (entering(tcp)) { len = tcp->u_arg[0]; tprintf("%lu, ", len); } else { unsigned long size, start, cur, end, abbrev_end; uid_t gid; int failed = 0; start = tcp->u_arg[1]; if (start == 0) { tprints("NULL"); return 0; } len = tcp->u_rval; if (len == 0) { tprints("[]"); return 0; } size = len * sizeof(gid); end = start + size; if (!verbose(tcp) || tcp->u_arg[0] == 0 || size / sizeof(gid) != len || end < start) { tprintf("%#lx", start); return 0; } if (abbrev(tcp)) { abbrev_end = start + max_strlen * sizeof(gid); if (abbrev_end < start) abbrev_end = end; } else { abbrev_end = end; } tprints("["); for (cur = start; cur < end; cur += sizeof(gid)) { if (cur > start) tprints(", "); if (cur >= abbrev_end) { tprints("..."); break; } if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) { tprints("?"); failed = 1; break; } tprintf("%u", (unsigned int) gid); } tprints("]"); if (failed) tprintf(" %#lx", tcp->u_arg[1]); } return 0; }
static int copy_sigset_len(struct tcb *tcp, long addr, sigset_t *s, int len) { if (len > sizeof(*s)) len = sizeof(*s); sigemptyset(s); if (umoven(tcp, addr, len, (char *)s) < 0) return -1; return 0; }
int sys_oldselect(struct tcb *tcp) { long args[5]; if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) { tprints("[...]"); return 0; } return decode_select(tcp, args, BITNESS_CURRENT); }
static void printargc(const char *fmt, struct tcb *tcp, long addr) { int count; char *cp = NULL; for (count = 0; !umoven(tcp, addr, current_wordsize, &cp) && cp; count++) { addr += current_wordsize; } tprintf(fmt, count, count == 1 ? "" : "s"); }
static void printcmsghdr(struct tcb *tcp, unsigned long addr, unsigned long len) { struct cmsghdr *cmsg = len < sizeof(struct cmsghdr) ? NULL : malloc(len); if (cmsg == NULL || umoven(tcp, addr, len, (char *) cmsg) < 0) { tprintf(", msg_control=%#lx", addr); free(cmsg); return; } tprintf(", {cmsg_len=%u, cmsg_level=", (unsigned) cmsg->cmsg_len); printxval(socketlayers, cmsg->cmsg_level, "SOL_???"); tprints(", cmsg_type="); if (cmsg->cmsg_level == SOL_SOCKET) { unsigned long cmsg_len; printxval(scmvals, cmsg->cmsg_type, "SCM_???"); cmsg_len = (len < cmsg->cmsg_len) ? len : cmsg->cmsg_len; if (cmsg->cmsg_type == SCM_RIGHTS && CMSG_LEN(sizeof(int)) <= cmsg_len) { int *fds = (int *) CMSG_DATA(cmsg); int first = 1; tprints(", {"); while ((char *) fds < ((char *) cmsg + cmsg_len)) { if (!first) tprints(", "); printfd(tcp, *fds++); first = 0; } tprints("}}"); free(cmsg); return; } if (cmsg->cmsg_type == SCM_CREDENTIALS && CMSG_LEN(sizeof(struct ucred)) <= cmsg_len) { struct ucred *uc = (struct ucred *) CMSG_DATA(cmsg); tprintf("{pid=%ld, uid=%ld, gid=%ld}}", (long)uc->pid, (long)uc->uid, (long)uc->gid); free(cmsg); return; } } free(cmsg); tprints(", ...}"); }
/* Params are pointed to by u_arg[0], offset is in pages */ int sys_old_mmap_pgoff(struct tcb *tcp) { long u_arg[5]; int i; unsigned narrow_arg[6]; unsigned long long offset; if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1) return 0; for (i = 0; i < 5; i++) u_arg[i] = (unsigned long) narrow_arg[i]; offset = narrow_arg[5]; offset *= get_pagesize(); return print_mmap(tcp, u_arg, offset); }
// int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); // on connection or binding succeeds, zero is returned; on error, -1 is returned. void CDEnet_begin_bindconnect(struct tcb* tcp, int isConnect) { vb(1); if (CDE_nw_mode) { char addrbuf[KEYLEN]; if (umoven(tcp, tcp->u_arg[1], tcp->u_arg[2], addrbuf) < 0) return; if (isConnect) { int port = getPort((void*)addrbuf); vbp(3, "Port %d\n", port); if (port == 53 || port == 22) return; } db_setCapturedSock(currdb, tcp->u_arg[0]); denySyscall(tcp->pid); } }
/* Returns the total bytes dumped */ unsigned long dump_iov(struct tcb *tcp, unsigned long len, unsigned long addr) { unsigned long toret = 0; #if SUPPORTED_PERSONALITIES > 1 union { struct { u_int32_t base; u_int32_t len; } iov32; struct { u_int64_t base; u_int64_t len; } iov64; } iov; #define sizeof_iov \ (current_wordsize == 4 ? sizeof(iov.iov32) : sizeof(iov.iov64)) #define iov_iov_base \ (current_wordsize == 4 ? (uint64_t) iov.iov32.base : iov.iov64.base) #define iov_iov_len \ (current_wordsize == 4 ? (uint64_t) iov.iov32.len : iov.iov64.len) #else struct iovec iov; #define sizeof_iov sizeof(iov) #define iov_iov_base iov.iov_base #define iov_iov_len iov.iov_len #endif unsigned long size, cur, end; if (!len) { return 0; } size = len * sizeof_iov; end = addr + size; if (size / sizeof_iov != len || end < addr) { assert(0); } for (cur = addr; cur < end; cur += sizeof_iov) { if (umoven(tcp, cur, sizeof_iov, (char *) &iov) < 0) { assert(0); } unsigned long len = iov_iov_len; dump_bytes(tcp, (long) iov_iov_base, len); toret += len; } #undef sizeof_iov #undef iov_iov_base #undef iov_iov_len return toret; }
int socket_data_handle(struct tcb* tcp, int action) { int sockfd = tcp->u_arg[0]; if (CDE_provenance_mode) { long len = tcp->u_rval; char *buf = NULL; if (len >0) { buf = malloc(len); if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) { free(buf); return -1; } } print_sock_action(tcp, sockfd, buf, tcp->u_arg[2], tcp->u_arg[3], len, action, NULL); if (buf != NULL) free(buf); } return 0; }
void CDEnet_end_send(struct tcb* tcp) { int sockfd = tcp->u_arg[0]; if (CDE_provenance_mode && CDE_network_content_mode && isProvCapturedSock(sockfd)) { vb(2); if (socket_data_handle(tcp, SOCK_SEND) < 0) { // TODO } } if (CDE_nw_mode && db_isCapturedSock(currdb, sockfd)) { vb(2); if (CDE_verbose_mode >= 3) { char buff[KEYLEN]; size_t buflength = tcp->u_arg[2]; if (umoven(tcp, tcp->u_arg[1], buflength, buff) < 0) { return; } buff[tcp->u_arg[2]] = '\0'; vbp(3, "action %d [%ld] checksum %u ", SOCK_SEND, tcp->u_arg[2], checksum(buff, buflength)); if (CDE_verbose_mode >= 3) printbuf(buff, buflength); } long pid = tcp->pid; char *pidkey, *sockid; db_get_pid_sock(currdb, pid, sockfd, &pidkey, &sockid); if (pidkey == NULL || sockid == NULL) { vbp(0, "error"); return; } ull_t sendid = db_getPkgCounterInc(currdb, pidkey, sockid, SOCK_SEND); char* prov_pid = getMappedPid(pidkey); // convert this pid to corresponding prov_pid ull_t u_rval; db_getSendRecvResult(netdb, SOCK_SEND, prov_pid, sockid, sendid, &u_rval, NULL); // get recorded result struct user_regs_struct regs; EXITIF(ptrace(PTRACE_GETREGS, pid, NULL, ®s)<0); SET_RETURN_CODE(®s, u_rval); if (u_rval < 0) { // set errno? TODO } EXITIF(ptrace(PTRACE_SETREGS, pid, NULL, ®s)<0); free(prov_pid); free(sockid); free(pidkey); } }
/* Return -1 on error or 1 on success (never 0!). */ static int get_syscall_args(struct tcb *tcp) { if (!ia64_ia32mode) { unsigned long *rbs_end = (unsigned long *) ia64_regs.ar[PT_AUR_BSP]; unsigned long sof = (ia64_regs.cfm >> 0) & 0x7f; unsigned long sol = (ia64_regs.cfm >> 7) & 0x7f; unsigned long *out0 = ia64_rse_skip_regs(rbs_end, -sof + sol); unsigned int i; for (i = 0; i < tcp->s_ent->nargs; ++i) { if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i), sizeof(long), &tcp->u_arg[i]) < 0) return -1; } } else {
static void print_cap_header(struct tcb *tcp, unsigned long addr) { union { cap_user_header_t p; long *a; char *c; } arg; long a[sizeof(*arg.p) / sizeof(long) + 1]; arg.a = a; if (!addr) tprints("NULL"); else if (!verbose(tcp) || umoven(tcp, addr, sizeof(*arg.p), arg.c) < 0) tprintf("%#lx", addr); else { tprints("{"); printxval(cap_version, arg.p->version, "_LINUX_CAPABILITY_VERSION_???"); tprintf(", %d}", arg.p->pid); } }
static void get_nodes(struct tcb *tcp, unsigned long ptr, unsigned long maxnodes, int err) { unsigned long nlongs, size, end; nlongs = (maxnodes + 8 * sizeof(long) - 1) / (8 * sizeof(long)); size = nlongs * sizeof(long); end = ptr + size; if (nlongs == 0 || ((err || verbose(tcp)) && (size * 8 == maxnodes) && (end > ptr))) { unsigned long n, cur, abbrev_end; int failed = 0; if (abbrev(tcp)) { abbrev_end = ptr + max_strlen * sizeof(long); if (abbrev_end < ptr) abbrev_end = end; } else { abbrev_end = end; } tprints(", {"); for (cur = ptr; cur < end; cur += sizeof(long)) { if (cur > ptr) tprints(", "); if (cur >= abbrev_end) { tprints("..."); break; } if (umoven(tcp, cur, sizeof(n), (char *) &n) < 0) { tprints("?"); failed = 1; break; } tprintf("%#0*lx", (int) sizeof(long) * 2 + 2, n); } tprints("}"); if (failed) tprintf(" %#lx", ptr); } else tprintf(", %#lx", ptr); tprintf(", %lu", maxnodes); }
int sys_socketpair(struct tcb *tcp) { int fds[2]; if (entering(tcp)) { printxval(domains, tcp->u_arg[0], "PF_???"); tprints(", "); tprint_sock_type(tcp, tcp->u_arg[1]); tprintf(", %lu", tcp->u_arg[2]); } else { if (syserror(tcp)) { tprintf(", %#lx", tcp->u_arg[3]); return 0; } if (umoven(tcp, tcp->u_arg[3], sizeof fds, (char *) fds) < 0) tprints(", [...]"); else tprintf(", [%u, %u]", fds[0], fds[1]); } return 0; }
static void decode_mips_subcall(struct tcb *tcp) { if (!scno_is_valid(tcp->u_arg[0])) return; tcp->scno = tcp->u_arg[0]; tcp->qual_flg = qual_flags(tcp->scno); tcp->s_ent = &sysent[tcp->scno]; memmove(&tcp->u_arg[0], &tcp->u_arg[1], sizeof(tcp->u_arg) - sizeof(tcp->u_arg[0])); /* * Fetching the last arg of 7-arg syscalls (fadvise64_64 * and sync_file_range) requires additional code, * see linux/mips/get_syscall_args.c */ if (tcp->s_ent->nargs == MAX_ARGS) { if (umoven(tcp, mips_REG_SP + MAX_ARGS * sizeof(tcp->u_arg[0]), sizeof(tcp->u_arg[0]), &tcp->u_arg[MAX_ARGS - 1]) < 0) tcp->u_arg[MAX_ARGS - 1] = 0; } }
static void print_cap_data(struct tcb *tcp, unsigned long addr) { union { cap_user_data_t p; long *a; char *c; } arg; long a[sizeof(*arg.p) / sizeof(long) + 1]; arg.a = a; if (!addr) tprints("NULL"); else if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) || umoven(tcp, addr, sizeof(*arg.p), arg.c) < 0) tprintf("%#lx", addr); else { tprints("{"); printflags(capabilities, arg.p->effective, "CAP_???"); tprints(", "); printflags(capabilities, arg.p->permitted, "CAP_???"); tprints(", "); printflags(capabilities, arg.p->inheritable, "CAP_???"); tprints("}"); } }
void CDEnet_end_bindconnect(struct tcb* tcp, int isConnect) { int sockfd = tcp->u_arg[0]; long addr = tcp->u_arg[1]; int addrlen = tcp->u_arg[2]; union sockaddr_t addrbuf; vb(2); if (addr == 0) return; if (addrlen < 2 || addrlen > sizeof(addrbuf)) addrlen = sizeof(addrbuf); if (umoven(tcp, addr, addrlen, addrbuf.pad) < 0) return; addrbuf.pad[sizeof(addrbuf.pad) - 1] = '\0'; //~ printf("sock %d, family %d inet %d\n", sockfd, addrbuf.sa.sa_family, AF_INET); //~ if (CDE_provenance_mode && addrbuf.sa.sa_family == AF_INET) { if (CDE_provenance_mode) { int port = getPort((void*)addrbuf.pad); char buf[KEYLEN]; bzero(buf, sizeof(buf)); vbp(3, "Port %d return %ld\n", port, tcp->u_rval); if (port == 53 || port == 22) return; if (isConnect) { if (addrbuf.sa.sa_family == AF_INET) { get_ip_info(tcp->pid, sockfd, buf); } else if (addrbuf.sa.sa_family == AF_LOCAL) { sprintf(buf, "..%s", addrbuf.sau.sun_path); } } print_connect_prov(tcp, sockfd, addrbuf.pad, tcp->u_arg[2], tcp->u_rval, buf); } if (CDE_nw_mode) { // return my own network socket connect result from netdb if (isConnect) if (!isCurrCapturedSock(sockfd)) return; setBindConnectReturnValue(tcp); } }
static void decode_socket_subcall(struct tcb *tcp) { const int call = tcp->u_arg[0]; if (call < 1 || call >= SYS_socket_nsubcalls) return; const kernel_ulong_t scno = SYS_socket_subcall + call; const unsigned int nargs = sysent[scno].nargs; uint64_t buf[nargs]; if (umoven(tcp, tcp->u_arg[1], nargs * current_wordsize, buf) < 0) return; tcp->scno = scno; tcp->qual_flg = qual_flags(scno); tcp->s_ent = &sysent[scno]; unsigned int i; for (i = 0; i < nargs; ++i) tcp->u_arg[i] = (sizeof(uint32_t) == current_wordsize) ? ((uint32_t *) (void *) buf)[i] : buf[i]; }
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); }
static void print_sg_io_buffer(struct tcb *tcp, unsigned long addr, const unsigned int len) { unsigned char *buf = NULL; unsigned int allocated, i; tprints("["); if (len == 0) goto out; allocated = (len > max_strlen) ? max_strlen : len; if ((buf = malloc(allocated)) == NULL || umoven(tcp, addr, allocated, buf) < 0) { tprintf("%#lx", addr); goto out; } tprintf("%02x", buf[0]); for (i = 1; i < allocated; ++i) tprintf(", %02x", buf[i]); if (allocated != len) tprints(", ..."); out: free(buf); tprints("]"); }
void printsock(struct tcb *tcp, long addr, int addrlen) { union { char pad[128]; struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_un sau; #ifdef HAVE_INET_NTOP struct sockaddr_in6 sa6; #endif #if defined(LINUX) && defined(AF_IPX) struct sockaddr_ipx sipx; #endif #ifdef AF_PACKET struct sockaddr_ll ll; #endif #ifdef AF_NETLINK struct sockaddr_nl nl; #endif } addrbuf; char string_addr[100]; if (addr == 0) { tprintf("NULL"); return; } if (!verbose(tcp)) { tprintf("%#lx", addr); return; } if (addrlen < 2 || addrlen > sizeof(addrbuf)) addrlen = sizeof(addrbuf); memset(&addrbuf, 0, sizeof(addrbuf)); if (umoven(tcp, addr, addrlen, addrbuf.pad) < 0) { tprintf("{...}"); return; } addrbuf.pad[sizeof(addrbuf.pad) - 1] = '\0'; tprintf("{sa_family="); printxval(addrfams, addrbuf.sa.sa_family, "AF_???"); tprintf(", "); switch (addrbuf.sa.sa_family) { case AF_UNIX: if (addrlen == 2) { tprintf("NULL"); } else if (addrbuf.sau.sun_path[0]) { tprintf("path="); printpathn(tcp, addr + 2, strlen(addrbuf.sau.sun_path)); } else { tprintf("path=@"); printpathn(tcp, addr + 3, strlen(addrbuf.sau.sun_path + 1)); } break; case AF_INET: tprintf("sin_port=htons(%u), sin_addr=inet_addr(\"%s\")", ntohs(addrbuf.sin.sin_port), inet_ntoa(addrbuf.sin.sin_addr)); break; #ifdef HAVE_INET_NTOP case AF_INET6: inet_ntop(AF_INET6, &addrbuf.sa6.sin6_addr, string_addr, sizeof(string_addr)); tprintf("sin6_port=htons(%u), inet_pton(AF_INET6, \"%s\", &sin6_addr), sin6_flowinfo=%u", ntohs(addrbuf.sa6.sin6_port), string_addr, addrbuf.sa6.sin6_flowinfo); #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID { #if defined(HAVE_IF_INDEXTONAME) && defined(IN6_IS_ADDR_LINKLOCAL) && defined(IN6_IS_ADDR_MC_LINKLOCAL) int numericscope = 0; if (IN6_IS_ADDR_LINKLOCAL (&addrbuf.sa6.sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL (&addrbuf.sa6.sin6_addr)) { char scopebuf[IFNAMSIZ + 1]; if (if_indextoname (addrbuf.sa6.sin6_scope_id, scopebuf) == NULL) numericscope++; else tprintf(", sin6_scope_id=if_nametoindex(\"%s\")", scopebuf); } else numericscope++; if (numericscope) #endif tprintf(", sin6_scope_id=%u", addrbuf.sa6.sin6_scope_id); } #endif break; #endif #if defined(AF_IPX) && defined(linux) case AF_IPX: { int i; tprintf("sipx_port=htons(%u), ", ntohs(addrbuf.sipx.sipx_port)); /* Yes, I know, this does not look too * strace-ish, but otherwise the IPX * addresses just look monstrous... * Anyways, feel free if you don't like * this way.. :) */ tprintf("%08lx:", (unsigned long)ntohl(addrbuf.sipx.sipx_network)); for (i = 0; i<IPX_NODE_LEN; i++) tprintf("%02x", addrbuf.sipx.sipx_node[i]); tprintf("/[%02x]", addrbuf.sipx.sipx_type); } break; #endif /* AF_IPX && linux */ #ifdef AF_PACKET case AF_PACKET: { int i; tprintf("proto=%#04x, if%d, pkttype=", ntohs(addrbuf.ll.sll_protocol), addrbuf.ll.sll_ifindex); printxval(af_packet_types, addrbuf.ll.sll_pkttype, "?"); tprintf(", addr(%d)={%d, ", addrbuf.ll.sll_halen, addrbuf.ll.sll_hatype); for (i=0; i<addrbuf.ll.sll_halen; i++) tprintf("%02x", addrbuf.ll.sll_addr[i]); } break; #endif /* AF_APACKET */ #ifdef AF_NETLINK case AF_NETLINK: tprintf("pid=%d, groups=%08x", addrbuf.nl.nl_pid, addrbuf.nl.nl_groups); break; #endif /* AF_NETLINK */ /* AF_AX25 AF_APPLETALK AF_NETROM AF_BRIDGE AF_AAL5 AF_X25 AF_ROSE etc. still need to be done */ default: tprintf("sa_data="); printstr(tcp, (long) &((struct sockaddr *) addr)->sa_data, sizeof addrbuf.sa.sa_data); break; } tprintf("}"); }
static void printcmsghdr(struct tcb *tcp, unsigned long addr, size_t len) { const size_t cmsg_size = #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 (current_wordsize < sizeof(long)) ? sizeof(struct cmsghdr32) : #endif sizeof(struct cmsghdr); char *buf = len < cmsg_size ? NULL : malloc(len); if (!buf || umoven(tcp, addr, len, buf) < 0) { tprints(", msg_control="); printaddr(addr); free(buf); return; } union_cmsghdr u = { .ptr = buf }; tprints(", ["); while (len >= cmsg_size) { size_t cmsg_len = #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_len : #endif u.cmsg->cmsg_len; int cmsg_level = #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_level : #endif u.cmsg->cmsg_level; int cmsg_type = #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_type : #endif u.cmsg->cmsg_type; if (u.ptr != buf) tprints(", "); tprintf("{cmsg_len=%lu, cmsg_level=", (unsigned long) cmsg_len); printxval(socketlayers, cmsg_level, "SOL_???"); tprints(", cmsg_type="); if (cmsg_len > len) cmsg_len = len; print_cmsg_type_data(tcp, cmsg_level, cmsg_type, (const void *) (u.ptr + cmsg_size), cmsg_len > cmsg_size ? cmsg_len - cmsg_size: 0); tprints("}"); if (cmsg_len < cmsg_size) { len -= cmsg_size; break; } cmsg_len = (cmsg_len + current_wordsize - 1) & (size_t) ~(current_wordsize - 1); if (cmsg_len >= len) { len = 0; break; } u.ptr += cmsg_len; len -= cmsg_len; } if (len) tprints(", ..."); tprints("]"); free(buf); }
/* * data_size limits the cumulative size of printed data. * Example: recvmsg returing a short read. */ void tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov, unsigned long data_size) { #if SUPPORTED_PERSONALITIES > 1 union { struct { u_int32_t base; u_int32_t len; } iov32; struct { u_int64_t base; u_int64_t len; } iov64; } iov; #define sizeof_iov \ (current_wordsize == 4 ? sizeof(iov.iov32) : sizeof(iov.iov64)) #define iov_iov_base \ (current_wordsize == 4 ? (uint64_t) iov.iov32.base : iov.iov64.base) #define iov_iov_len \ (current_wordsize == 4 ? (uint64_t) iov.iov32.len : iov.iov64.len) #else struct iovec iov; #define sizeof_iov sizeof(iov) #define iov_iov_base iov.iov_base #define iov_iov_len iov.iov_len #endif unsigned long size, cur, end, abbrev_end; int failed = 0; if (!len) { tprints("[]"); return; } size = len * sizeof_iov; end = addr + size; if (!verbose(tcp) || size / sizeof_iov != len || end < addr) { tprintf("%#lx", addr); return; } if (abbrev(tcp)) { abbrev_end = addr + max_strlen * sizeof_iov; if (abbrev_end < addr) abbrev_end = end; } else { abbrev_end = end; } tprints("["); for (cur = addr; cur < end; cur += sizeof_iov) { if (cur > addr) tprints(", "); if (cur >= abbrev_end) { tprints("..."); break; } if (umoven(tcp, cur, sizeof_iov, (char *) &iov) < 0) { tprints("?"); failed = 1; break; } tprints("{"); if (decode_iov) { unsigned long len = iov_iov_len; if (len > data_size) len = data_size; data_size -= len; printstr(tcp, (long) iov_iov_base, len); } else tprintf("%#lx", (long) iov_iov_base); tprintf(", %lu}", (unsigned long)iov_iov_len); } tprints("]"); if (failed) tprintf(" %#lx", addr); #undef sizeof_iov #undef iov_iov_base #undef iov_iov_len }
/* * Return true if syscall accesses a selected path * (or if no paths have been specified for tracing). */ int pathtrace_match(struct tcb *tcp) { const struct_sysent *s; s = tcp->s_ent; if (!(s->sys_flags & (TRACE_FILE | TRACE_DESC | TRACE_NETWORK))) return 0; /* * Check for special cases where we need to do something * other than test arg[0]. */ if (s->sys_func == sys_dup2 || s->sys_func == sys_dup3 || s->sys_func == sys_sendfile || s->sys_func == sys_sendfile64 || s->sys_func == sys_tee) { /* fd, fd */ return fdmatch(tcp, tcp->u_arg[0]) || fdmatch(tcp, tcp->u_arg[1]); } if (s->sys_func == sys_inotify_add_watch || s->sys_func == sys_faccessat || s->sys_func == sys_fchmodat || s->sys_func == sys_futimesat || s->sys_func == sys_unlinkat || s->sys_func == sys_newfstatat || s->sys_func == sys_mknodat || s->sys_func == sys_openat || s->sys_func == sys_readlinkat || s->sys_func == sys_utimensat || s->sys_func == sys_fchownat || s->sys_func == sys_pipe2) { /* fd, path */ return fdmatch(tcp, tcp->u_arg[0]) || upathmatch(tcp, tcp->u_arg[1]); } if (s->sys_func == sys_link || s->sys_func == sys_mount) { /* path, path */ return upathmatch(tcp, tcp->u_arg[0]) || upathmatch(tcp, tcp->u_arg[1]); } if (s->sys_func == sys_quotactl) { /* x, path */ return upathmatch(tcp, tcp->u_arg[1]); } if (s->sys_func == sys_renameat || s->sys_func == sys_renameat2 || s->sys_func == sys_linkat) { /* fd, path, fd, path */ return fdmatch(tcp, tcp->u_arg[0]) || fdmatch(tcp, tcp->u_arg[2]) || upathmatch(tcp, tcp->u_arg[1]) || upathmatch(tcp, tcp->u_arg[3]); } if ( s->sys_func == sys_old_mmap || #if defined(S390) s->sys_func == sys_old_mmap_pgoff || #endif s->sys_func == sys_mmap || s->sys_func == sys_mmap_pgoff || s->sys_func == sys_mmap_4koff ) { /* x, x, x, x, fd */ return fdmatch(tcp, tcp->u_arg[4]); } if (s->sys_func == sys_symlinkat) { /* path, fd, path */ return fdmatch(tcp, tcp->u_arg[1]) || upathmatch(tcp, tcp->u_arg[0]) || upathmatch(tcp, tcp->u_arg[2]); } if (s->sys_func == sys_splice) { /* fd, x, fd, x, x */ return fdmatch(tcp, tcp->u_arg[0]) || fdmatch(tcp, tcp->u_arg[2]); } if (s->sys_func == sys_epoll_ctl) { /* x, x, fd, x */ return fdmatch(tcp, tcp->u_arg[2]); } if (s->sys_func == sys_fanotify_mark) { /* x, x, x, fd, path */ return fdmatch(tcp, tcp->u_arg[3]) || upathmatch(tcp, tcp->u_arg[4]); } if (s->sys_func == sys_select || s->sys_func == sys_oldselect || s->sys_func == sys_pselect6) { int i, j; int nfds; long *args, oldargs[5]; unsigned fdsize; fd_set *fds; args = tcp->u_arg; if (s->sys_func == sys_oldselect) { if (umoven(tcp, tcp->u_arg[0], sizeof oldargs, oldargs) < 0) { fprintf(stderr, "umoven() failed\n"); return 0; } args = oldargs; } /* Kernel truncates arg[0] to int, we do the same. */ nfds = (int) args[0]; /* Kernel rejects negative nfds, so we don't parse it either. */ if (nfds <= 0) return 0; /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */ if (nfds > 1024*1024) nfds = 1024*1024; fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize; fds = malloc(fdsize); if (!fds) die_out_of_memory(); for (i = 1; i <= 3; ++i) { if (args[i] == 0) continue; if (umoven(tcp, args[i], fdsize, fds) < 0) { fprintf(stderr, "umoven() failed\n"); continue; } for (j = 0;; j++) { j = next_set_bit(fds, j, nfds); if (j < 0) break; if (fdmatch(tcp, j)) { free(fds); return 1; } } } free(fds); return 0; } if (s->sys_func == sys_poll || s->sys_func == sys_ppoll) { struct pollfd fds; unsigned nfds; unsigned long start, cur, end; start = tcp->u_arg[0]; nfds = tcp->u_arg[1]; end = start + sizeof(fds) * nfds; if (nfds == 0 || end < start) return 0; for (cur = start; cur < end; cur += sizeof(fds)) if ((umoven(tcp, cur, sizeof fds, &fds) == 0) && fdmatch(tcp, fds.fd)) return 1; return 0; } if (s->sys_func == printargs || s->sys_func == sys_pipe || s->sys_func == sys_pipe2 || s->sys_func == sys_eventfd2 || s->sys_func == sys_eventfd || s->sys_func == sys_inotify_init1 || s->sys_func == sys_timerfd_create || s->sys_func == sys_timerfd_settime || s->sys_func == sys_timerfd_gettime || s->sys_func == sys_epoll_create || s->sys_func == sys_socket || s->sys_func == sys_socketpair || s->sys_func == sys_fanotify_init) { /* * These have TRACE_FILE or TRACE_DESCRIPTOR or TRACE_NETWORK set, * but they don't have any file descriptor or path args to test. */ return 0; } /* * Our fallback position for calls that haven't already * been handled is to just check arg[0]. */ if (s->sys_flags & TRACE_FILE) return upathmatch(tcp, tcp->u_arg[0]); if (s->sys_flags & (TRACE_DESC | TRACE_NETWORK)) return fdmatch(tcp, tcp->u_arg[0]); return 0; }