Date: Sat, 7 Apr 2018 21:05:39 +0000 (UTC) From: Michael Tuexen <tuexen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r332249 - stable/11/usr.bin/truss Message-ID: <201804072105.w37L5dbW009420@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tuexen Date: Sat Apr 7 21:05:39 2018 New Revision: 332249 URL: https://svnweb.freebsd.org/changeset/base/332249 Log: MFC r328015: Decode msghdr argument of sendmsg() and recvmsg(). Modified: stable/11/usr.bin/truss/syscall.h stable/11/usr.bin/truss/syscalls.c Directory Properties: stable/11/ (props changed) Modified: stable/11/usr.bin/truss/syscall.h ============================================================================== --- stable/11/usr.bin/truss/syscall.h Sat Apr 7 21:04:43 2018 (r332248) +++ stable/11/usr.bin/truss/syscall.h Sat Apr 7 21:05:39 2018 (r332249) @@ -81,7 +81,7 @@ enum Argtype { None = 1, Hex, Octal, Int, UInt, LongHe Sockoptname, Msgflags, CapRights, PUInt, PQuadHex, Acltype, Extattrnamespace, Minherit, Mlockall, Mountflags, Msync, Priowhich, Ptraceop, Quotactlcmd, Reboothowto, Rtpriofunc, Schedpolicy, Schedparam, - PSig, Siginfo, Kevent11, Iovec, Sctpsndrcvinfo, + PSig, Siginfo, Kevent11, Iovec, Sctpsndrcvinfo, Msghdr, CloudABIAdvice, CloudABIClockID, ClouduABIFDSFlags, CloudABIFDStat, CloudABIFileStat, CloudABIFileType, Modified: stable/11/usr.bin/truss/syscalls.c ============================================================================== --- stable/11/usr.bin/truss/syscalls.c Sat Apr 7 21:04:43 2018 (r332248) +++ stable/11/usr.bin/truss/syscalls.c Sat Apr 7 21:05:39 2018 (r332249) @@ -385,7 +385,7 @@ static struct syscall decoded_syscalls[] = { { Msgflags, 3 }, { Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } }, { .name = "recvmsg", .ret_type = 1, .nargs = 3, - .args = { { Int, 0 }, { Ptr, 1 }, { Msgflags, 2 } } }, + .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } }, { .name = "rename", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Name, 1 } } }, { .name = "renameat", .ret_type = 1, .nargs = 4, @@ -428,7 +428,7 @@ static struct syscall decoded_syscalls[] = { .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 }, { Timeval, 4 } } }, { .name = "sendmsg", .ret_type = 1, .nargs = 3, - .args = { { Int, 0 }, { Ptr, 1 }, { Msgflags, 2 } } }, + .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } }, { .name = "sendto", .ret_type = 1, .nargs = 6, .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 }, { Msgflags, 3 }, { Sockaddr | IN, 4 }, @@ -1142,6 +1142,378 @@ print_utrace(FILE *fp, void *utrace_addr, size_t len) fprintf(fp, " }"); } +static void +print_sockaddr(FILE *fp, struct trussinfo *trussinfo, void *arg, socklen_t len) +{ + char addr[64]; + struct sockaddr_in *lsin; + struct sockaddr_in6 *lsin6; + struct sockaddr_un *sun; + struct sockaddr *sa; + u_char *q; + pid_t pid = trussinfo->curthread->proc->pid; + + if (arg == NULL) { + fputs("NULL", fp); + return; + } + /* If the length is too small, just bail. */ + if (len < sizeof(*sa)) { + fprintf(fp, "0x%p", arg); + return; + } + + sa = calloc(1, len); + if (get_struct(pid, arg, sa, len) == -1) { + free(sa); + fprintf(fp, "0x%p", arg); + return; + } + + switch (sa->sa_family) { + case AF_INET: + if (len < sizeof(*lsin)) + goto sockaddr_short; + lsin = (struct sockaddr_in *)(void *)sa; + inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr)); + fprintf(fp, "{ AF_INET %s:%d }", addr, + htons(lsin->sin_port)); + break; + case AF_INET6: + if (len < sizeof(*lsin6)) + goto sockaddr_short; + lsin6 = (struct sockaddr_in6 *)(void *)sa; + inet_ntop(AF_INET6, &lsin6->sin6_addr, addr, + sizeof(addr)); + fprintf(fp, "{ AF_INET6 [%s]:%d }", addr, + htons(lsin6->sin6_port)); + break; + case AF_UNIX: + sun = (struct sockaddr_un *)sa; + fprintf(fp, "{ AF_UNIX \"%.*s\" }", + (int)(len - offsetof(struct sockaddr_un, sun_path)), + sun->sun_path); + break; + default: + sockaddr_short: + fprintf(fp, + "{ sa_len = %d, sa_family = %d, sa_data = {", + (int)sa->sa_len, (int)sa->sa_family); + for (q = (u_char *)sa->sa_data; + q < (u_char *)sa + len; q++) + fprintf(fp, "%s 0x%02x", + q == (u_char *)sa->sa_data ? "" : ",", + *q); + fputs(" } }", fp); + } + free(sa); +} + +#define IOV_LIMIT 16 + +static void +print_iovec(FILE *fp, struct trussinfo *trussinfo, void *arg, int iovcnt) +{ + struct iovec iov[IOV_LIMIT]; + size_t max_string = trussinfo->strsize; + char tmp2[max_string + 1], *tmp3; + size_t len; + pid_t pid = trussinfo->curthread->proc->pid; + int i; + bool buf_truncated, iov_truncated; + + if (iovcnt <= 0) { + fprintf(fp, "0x%p", arg); + return; + } + if (iovcnt > IOV_LIMIT) { + iovcnt = IOV_LIMIT; + iov_truncated = true; + } else { + iov_truncated = false; + } + if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) { + fprintf(fp, "0x%p", arg); + return; + } + + fputs("[", fp); + for (i = 0; i < iovcnt; i++) { + len = iov[i].iov_len; + if (len > max_string) { + len = max_string; + buf_truncated = true; + } else { + buf_truncated = false; + } + fprintf(fp, "%s{", (i > 0) ? "," : ""); + if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) != -1) { + tmp3 = malloc(len * 4 + 1); + while (len) { + if (strvisx(tmp3, tmp2, len, + VIS_CSTYLE|VIS_TAB|VIS_NL) <= + (int)max_string) + break; + len--; + buf_truncated = true; + } + fprintf(fp, "\"%s\"%s", tmp3, + buf_truncated ? "..." : ""); + free(tmp3); + } else { + fprintf(fp, "0x%p", iov[i].iov_base); + } + fprintf(fp, ",%zu}", iov[i].iov_len); + } + fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]"); +} + +static void +print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr) +{ + u_char *q; + + fputs("{", fp); + for (q = CMSG_DATA(cmsghdr); + q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) { + fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q); + } + fputs("}", fp); +} + +static void +print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init) +{ + fprintf(fp, "{out=%u,", init->sinit_num_ostreams); + fprintf(fp, "in=%u,", init->sinit_max_instreams); + fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts); + fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo); +} + +static void +print_sctp_sndrcvinfo(FILE *fp, bool recv, struct sctp_sndrcvinfo *info) +{ + fprintf(fp, "{sid=%u,", info->sinfo_stream); + if (recv) { + fprintf(fp, "ssn=%u,", info->sinfo_ssn); + } + fputs("flgs=", fp); + sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags); + fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid)); + if (!recv) { + fprintf(fp, "ctx=%u,", info->sinfo_context); + fprintf(fp, "ttl=%u,", info->sinfo_timetolive); + } + if (recv) { + fprintf(fp, "tsn=%u,", info->sinfo_tsn); + fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn); + } + fprintf(fp, "id=%u}", info->sinfo_assoc_id); +} + +static void +print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info) +{ + fprintf(fp, "{sid=%u,", info->snd_sid); + fputs("flgs=", fp); + print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags); + fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid)); + fprintf(fp, "ctx=%u,", info->snd_context); + fprintf(fp, "id=%u}", info->snd_assoc_id); +} + +static void +print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info) +{ + fprintf(fp, "{sid=%u,", info->rcv_sid); + fprintf(fp, "ssn=%u,", info->rcv_ssn); + fputs("flgs=", fp); + print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags); + fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid)); + fprintf(fp, "tsn=%u,", info->rcv_tsn); + fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn); + fprintf(fp, "ctx=%u,", info->rcv_context); + fprintf(fp, "id=%u}", info->rcv_assoc_id); +} + +static void +print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info) +{ + fprintf(fp, "{sid=%u,", info->nxt_sid); + fputs("flgs=", fp); + print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags); + fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid)); + fprintf(fp, "len=%u,", info->nxt_length); + fprintf(fp, "id=%u}", info->nxt_assoc_id); +} + +static void +print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info) +{ + fputs("{pol=", fp); + print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy); + fprintf(fp, ",val=%u}", info->pr_value); +} + +static void +print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info) +{ + fprintf(fp, "{num=%u}", info->auth_keynumber); +} + +static void +print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr) +{ + char buf[INET_ADDRSTRLEN]; + const char *s; + + s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN); + if (s != NULL) + fprintf(fp, "{addr=%s}", s); + else + fputs("{addr=???}", fp); +} + +static void +print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr) +{ + char buf[INET6_ADDRSTRLEN]; + const char *s; + + s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN); + if (s != NULL) + fprintf(fp, "{addr=%s}", s); + else + fputs("{addr=???}", fp); +} + +static void +print_sctp_cmsg(FILE *fp, bool recv, struct cmsghdr *cmsghdr) +{ + void *data; + socklen_t len; + + len = cmsghdr->cmsg_len; + data = CMSG_DATA(cmsghdr); + switch (cmsghdr->cmsg_type) { + case SCTP_INIT: + if (len == CMSG_LEN(sizeof(struct sctp_initmsg))) + print_sctp_initmsg(fp, (struct sctp_initmsg *)data); + else + print_gen_cmsg(fp, cmsghdr); + break; + case SCTP_SNDRCV: + if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo))) + print_sctp_sndrcvinfo(fp, recv, + (struct sctp_sndrcvinfo *)data); + else + print_gen_cmsg(fp, cmsghdr); + break; +#if 0 + case SCTP_EXTRCV: + if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo))) + print_sctp_extrcvinfo(fp, + (struct sctp_extrcvinfo *)data); + else + print_gen_cmsg(fp, cmsghdr); + break; +#endif + case SCTP_SNDINFO: + if (len == CMSG_LEN(sizeof(struct sctp_sndinfo))) + print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data); + else + print_gen_cmsg(fp, cmsghdr); + break; + case SCTP_RCVINFO: + if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo))) + print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data); + else + print_gen_cmsg(fp, cmsghdr); + break; + case SCTP_NXTINFO: + if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo))) + print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data); + else + print_gen_cmsg(fp, cmsghdr); + break; + case SCTP_PRINFO: + if (len == CMSG_LEN(sizeof(struct sctp_prinfo))) + print_sctp_prinfo(fp, (struct sctp_prinfo *)data); + else + print_gen_cmsg(fp, cmsghdr); + break; + case SCTP_AUTHINFO: + if (len == CMSG_LEN(sizeof(struct sctp_authinfo))) + print_sctp_authinfo(fp, (struct sctp_authinfo *)data); + else + print_gen_cmsg(fp, cmsghdr); + break; + case SCTP_DSTADDRV4: + if (len == CMSG_LEN(sizeof(struct in_addr))) + print_sctp_ipv4_addr(fp, (struct in_addr *)data); + else + print_gen_cmsg(fp, cmsghdr); + break; + case SCTP_DSTADDRV6: + if (len == CMSG_LEN(sizeof(struct in6_addr))) + print_sctp_ipv6_addr(fp, (struct in6_addr *)data); + else + print_gen_cmsg(fp, cmsghdr); + break; + default: + print_gen_cmsg(fp, cmsghdr); + } +} + +static void +print_cmsgs(FILE *fp, pid_t pid, bool recv, struct msghdr *msghdr) +{ + struct cmsghdr *cmsghdr; + char *cmsgbuf; + const char *temp; + socklen_t len; + int level, type; + bool first; + + len = msghdr->msg_controllen; + cmsgbuf = calloc(1, len); + if (get_struct(pid, msghdr->msg_control, cmsgbuf, len) == -1) { + fprintf(fp, "0x%p", msghdr); + free(cmsgbuf); + } + msghdr->msg_control = cmsgbuf; + first = true; + fputs("{", fp); + for (cmsghdr = CMSG_FIRSTHDR(msghdr); + cmsghdr != NULL; + cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) { + level = cmsghdr->cmsg_level; + type = cmsghdr->cmsg_type; + len = cmsghdr->cmsg_len; + fprintf(fp, "%s{level=", first ? "" : ","); + print_integer_arg(sysdecode_sockopt_level, fp, level); + fputs(",type=", fp); + temp = sysdecode_cmsg_type(level, type); + if (temp) { + fputs(temp, fp); + } else { + fprintf(fp, "%d", type); + } + fputs(",data=", fp); + switch (level) { + case IPPROTO_SCTP: + print_sctp_cmsg(fp, recv, cmsghdr); + break; + default: + print_gen_cmsg(fp, cmsghdr); + break; + } + fputs("}", fp); + } + fputs("}", fp); + free(cmsgbuf); +} + /* * Converts a syscall argument into a string. Said string is * allocated via malloc(), so needs to be free()'d. sc is @@ -1596,13 +1968,7 @@ print_arg(struct syscall_args *sc, unsigned long *args print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]); break; case Sockaddr: { - char addr[64]; - struct sockaddr_in *lsin; - struct sockaddr_in6 *lsin6; - struct sockaddr_un *sun; - struct sockaddr *sa; socklen_t len; - u_char *q; if (args[sc->offset] == 0) { fputs("NULL", fp); @@ -1624,56 +1990,7 @@ print_arg(struct syscall_args *sc, unsigned long *args } else len = args[sc->offset + 1]; - /* If the length is too small, just bail. */ - if (len < sizeof(*sa)) { - fprintf(fp, "0x%lx", args[sc->offset]); - break; - } - - sa = calloc(1, len); - if (get_struct(pid, (void *)args[sc->offset], sa, len) == -1) { - free(sa); - fprintf(fp, "0x%lx", args[sc->offset]); - break; - } - - switch (sa->sa_family) { - case AF_INET: - if (len < sizeof(*lsin)) - goto sockaddr_short; - lsin = (struct sockaddr_in *)(void *)sa; - inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr)); - fprintf(fp, "{ AF_INET %s:%d }", addr, - htons(lsin->sin_port)); - break; - case AF_INET6: - if (len < sizeof(*lsin6)) - goto sockaddr_short; - lsin6 = (struct sockaddr_in6 *)(void *)sa; - inet_ntop(AF_INET6, &lsin6->sin6_addr, addr, - sizeof(addr)); - fprintf(fp, "{ AF_INET6 [%s]:%d }", addr, - htons(lsin6->sin6_port)); - break; - case AF_UNIX: - sun = (struct sockaddr_un *)sa; - fprintf(fp, "{ AF_UNIX \"%.*s\" }", - (int)(len - offsetof(struct sockaddr_un, sun_path)), - sun->sun_path); - break; - default: - sockaddr_short: - fprintf(fp, - "{ sa_len = %d, sa_family = %d, sa_data = {", - (int)sa->sa_len, (int)sa->sa_family); - for (q = (u_char *)sa->sa_data; - q < (u_char *)sa + len; q++) - fprintf(fp, "%s 0x%02x", - q == (u_char *)sa->sa_data ? "" : ",", - *q); - fputs(" } }", fp); - } - free(sa); + print_sockaddr(fp, trussinfo, (void *)args[sc->offset], len); break; } case Sigaction: { @@ -2073,93 +2390,43 @@ print_arg(struct syscall_args *sc, unsigned long *args fprintf(fp, "0x%lx", args[sc->offset]); break; } -#define IOV_LIMIT 16 - case Iovec: { + case Iovec: /* * Print argument as an array of struct iovec, where the next * syscall argument is the number of elements of the array. */ - struct iovec iov[IOV_LIMIT]; - size_t max_string = trussinfo->strsize; - char tmp2[max_string + 1], *tmp3; - size_t len; - int i, iovcnt; - bool buf_truncated, iov_truncated; - iovcnt = args[sc->offset + 1]; - if (iovcnt <= 0) { - fprintf(fp, "0x%lx", args[sc->offset]); - break; - } - if (iovcnt > IOV_LIMIT) { - iovcnt = IOV_LIMIT; - iov_truncated = true; - } else { - iov_truncated = false; - } + print_iovec(fp, trussinfo, (void *)args[sc->offset], + (int)args[sc->offset + 1]); + break; + case Sctpsndrcvinfo: { + struct sctp_sndrcvinfo info; + if (get_struct(pid, (void *)args[sc->offset], - &iov, iovcnt * sizeof(struct iovec)) == -1) { + &info, sizeof(struct sctp_sndrcvinfo)) == -1) { fprintf(fp, "0x%lx", args[sc->offset]); break; } - - fprintf(fp, "%s", "["); - for (i = 0; i < iovcnt; i++) { - len = iov[i].iov_len; - if (len > max_string) { - len = max_string; - buf_truncated = true; - } else { - buf_truncated = false; - } - fprintf(fp, "%s{", (i > 0) ? "," : ""); - if (len && get_struct(pid, iov[i].iov_base, &tmp2, len) - != -1) { - tmp3 = malloc(len * 4 + 1); - while (len) { - if (strvisx(tmp3, tmp2, len, - VIS_CSTYLE|VIS_TAB|VIS_NL) <= - (int)max_string) - break; - len--; - buf_truncated = true; - } - fprintf(fp, "\"%s\"%s", tmp3, - buf_truncated ? "..." : ""); - free(tmp3); - } else { - fprintf(fp, "0x%p", iov[i].iov_base); - } - fprintf(fp, ",%zu}", iov[i].iov_len); - } - fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]"); + print_sctp_sndrcvinfo(fp, sc->type & OUT, &info); break; } - case Sctpsndrcvinfo: { - struct sctp_sndrcvinfo info; + case Msghdr: { + struct msghdr msghdr; if (get_struct(pid, (void *)args[sc->offset], - &info, sizeof(struct sctp_sndrcvinfo)) == -1) { + &msghdr, sizeof(struct msghdr)) == -1) { fprintf(fp, "0x%lx", args[sc->offset]); break; } - fprintf(fp, "{sid=%u,", info.sinfo_stream); - if (sc->type & OUT) { - fprintf(fp, "ssn=%u,", info.sinfo_ssn); - } - fputs("flgs=", fp); - sysdecode_sctp_sinfo_flags(fp, info.sinfo_flags); - fprintf(fp, ",ppid=%u,", ntohl(info.sinfo_ppid)); - /* Can't use IN here, since IN is 0 */ - if ((sc->type & OUT) == 0) { - fprintf(fp, "ctx=%u,", info.sinfo_context); - fprintf(fp, "ttl=%u,", info.sinfo_timetolive); - } - if (sc->type & OUT) { - fprintf(fp, "tsn=%u,", info.sinfo_tsn); - fprintf(fp, "cumtsn=%u,", info.sinfo_cumtsn); - } - fprintf(fp, "id=%u}", info.sinfo_assoc_id); + fputs("{", fp); + print_sockaddr(fp, trussinfo, msghdr.msg_name, msghdr.msg_namelen); + fprintf(fp, ",%d,", msghdr.msg_namelen); + print_iovec(fp, trussinfo, msghdr.msg_iov, msghdr.msg_iovlen); + fprintf(fp, ",%d,", msghdr.msg_iovlen); + print_cmsgs(fp, pid, sc->type & OUT, &msghdr); + fprintf(fp, ",%u,", msghdr.msg_controllen); + print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags); + fputs("}", fp); break; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804072105.w37L5dbW009420>