From: Roland McGrath Date: Wed, 1 Jun 2005 19:22:06 +0000 (+0000) Subject: 2005-05-31 Dmitry V. Levin X-Git-Tag: v4.5.18~375 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aa524c88c49814863cb7f19e5c8a8eeca6ce22fe;p=strace 2005-05-31 Dmitry V. Levin Deal with memory management issues. * defs.h (tprint_iov): Update prototype. * desc.c (sys_epoll_wait) [HAVE_SYS_EPOLL_H]: Do not allocate epoll_event array of arbitrary size on the stack, to avoid stack overflow. * file.c (print_xattr_val): Check for integer overflow during malloc size calculation, to avoid heap corruption. * io.c (tprint_iov) [HAVE_SYS_UIO_H]: Check for integer overflow during malloc size calculation, to avoid heap corruption. Change iovec array handling to avoid heap memory allocation. * mem.c (get_nodes) [LINUX]: Check for integer overflow during size calculation and do not allocate array of arbitrary size on the stack, to avoid stack overflow. * net.c (printcmsghdr) [HAVE_SENDMSG]: Do not allocate array of arbitrary size on the stack, to avoid stack overflow. Do not trust cmsg.cmsg_len to avoid read beyond the end of allocated object. (printmsghdr) [HAVE_SENDMSG]: Update tprint_iov() usage. * process.c (sys_setgroups): Check for integer overflow during malloc size calculation, to avoid heap corruption. Change gid_t array handling to avoid heap memory allocation. (sys_getgroups): Likewise. (sys_setgroups32) [LINUX]: Likewise. (sys_getgroups32) [LINUX]: Likewise. * stream.c (sys_poll) [HAVE_SYS_POLL_H]: Check for integer overflow during malloc size calculation, to avoid heap corruption. Change pollfd array handling to avoid heap memory allocation. * system.c (sys_sysctl) [LINUX]: Check for integer overflow during malloc size calculation, to avoid heap corruption. * util.c (dumpiov) [HAVE_SYS_UIO_H]: Check for integer overflow during malloc size calculation, to avoid heap corruption. Fixes RH#159196. --- diff --git a/defs.h b/defs.h index 574a7d2f..e32e3ed9 100644 --- a/defs.h +++ b/defs.h @@ -458,7 +458,7 @@ extern void printtrailer P((struct tcb *)); extern void tabto P((int)); extern void call_summary P((FILE *)); extern void printtv32 P((struct tcb*, long)); -extern void tprint_iov P((struct tcb *, int, long)); +extern void tprint_iov P((struct tcb *, unsigned long, unsigned long)); #ifdef LINUX extern int internal_clone P((struct tcb *)); diff --git a/desc.c b/desc.c index 2432b58f..bb30b6f0 100644 --- a/desc.c +++ b/desc.c @@ -680,20 +680,29 @@ struct tcb *tcp; tprintf("{}"); else { #ifdef HAVE_SYS_EPOLL_H - struct epoll_event evs[tcp->u_rval]; - if (umove(tcp, tcp->u_arg[1], evs) == 0) { - unsigned long i; - tprintf("{"); - for (i = 0; i < tcp->u_rval; ++i) { - if (i > 0) - tprintf(", "); - print_epoll_event(&evs[i]); + struct epoll_event ev, *start, *cur, *end; + int failed = 0; + + tprintf("{"); + start = (struct epoll_event *) tcp->u_arg[1]; + end = start + tcp->u_rval; + for (cur = start; cur < end; ++cur) { + if (cur > start) + tprintf(", "); + if (umove(tcp, (long) cur, &ev) == 0) + print_epoll_event(&ev); + else { + tprintf("?"); + failed = 1; + break; } - tprintf("}"); } - else + tprintf("}"); + if (failed) + tprintf(" %#lx", (long) start); +#else + tprintf("{...}"); #endif - tprintf("{...}"); } tprintf(", %ld, %ld", tcp->u_arg[2], tcp->u_arg[3]); } diff --git a/file.c b/file.c index 821d4a82..52c36312 100644 --- a/file.c +++ b/file.c @@ -2347,10 +2347,11 @@ print_xattr_val(tcp, failed, arg, insize, size) struct tcb *tcp; int failed; unsigned long arg; -long insize, size; +unsigned long insize, size; { if (!failed) { - unsigned char *buf = malloc(4 * size + 1); + unsigned long capacity = 4 * size + 1; + unsigned char *buf = (capacity < size) ? NULL : malloc(capacity); if (buf == NULL || /* probably a bogus size argument */ umoven(tcp, arg, size, (char *) &buf[3 * size]) < 0) { failed = 1; diff --git a/io.c b/io.c index 86f9abe0..414fbbb3 100644 --- a/io.c +++ b/io.c @@ -78,38 +78,50 @@ struct tcb *tcp; void tprint_iov(tcp, len, addr) struct tcb * tcp; -int len; -long addr; +unsigned long len; +unsigned long addr; { - struct iovec *iov; - int i; - + struct iovec iov; + unsigned long size, cur, end, abbrev_end; + int failed = 0; if (!len) { tprintf("[]"); return; } - - if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) { - fprintf(stderr, "No memory"); + size = len * sizeof(iov); + end = addr + size; + if (!verbose(tcp) || size / sizeof(iov) != len || end < addr) { + tprintf("%#lx", addr); return; } - if (umoven(tcp, addr, - len * sizeof *iov, (char *) iov) < 0) { - tprintf("%#lx", tcp->u_arg[1]); + if (abbrev(tcp)) { + abbrev_end = addr + max_strlen * sizeof(iov); + if (abbrev_end < addr) + abbrev_end = end; } else { - tprintf("["); - for (i = 0; i < len; i++) { - if (i) - tprintf(", "); - tprintf("{"); - printstr(tcp, (long) iov[i].iov_base, - iov[i].iov_len); - tprintf(", %lu}", (unsigned long)iov[i].iov_len); + abbrev_end = end; + } + tprintf("["); + for (cur = addr; cur < end; cur += sizeof(iov)) { + if (cur > addr) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; + } + if (umoven(tcp, cur, sizeof iov, (char *) &iov) < 0) { + tprintf("?"); + failed = 1; + break; } - tprintf("]"); + tprintf("{"); + printstr(tcp, (long) iov.iov_base, iov.iov_len); + tprintf(", %lu}", (unsigned long)iov.iov_len); } - free((char *) iov); + tprintf("]"); + if (failed) + tprintf(" %#lx", addr); } int diff --git a/mem.c b/mem.c index 08a5f926..636644eb 100644 --- a/mem.c +++ b/mem.c @@ -692,26 +692,43 @@ unsigned long ptr; unsigned long maxnodes; int err; { - int nlongs = (maxnodes + 8 * sizeof(long) - 1) / (8 * sizeof(long)); - if (err || !abbrev(tcp) || nlongs > getpagesize() / sizeof(long) - || nlongs == 0) { - long buf[nlongs]; - if (umoven(tcp, ptr, nlongs * sizeof(long), - (char *) buf) < 0) - tprintf(", %lx", ptr); - else { - int i; - tprintf(", {"); - for (i = 0; i < nlongs; ++i) { - if (i > 0) - tprintf(", "); - tprintf("%#0*lx", (int) sizeof(long) * 2 + 2, - buf[i]); + 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; + } + tprintf(", {"); + for (cur = ptr; cur < end; cur += sizeof(long)) { + if (cur > ptr) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; + } + if (umoven(tcp, cur, sizeof(n), (char *) &n) < 0) { + tprintf("?"); + failed = 1; + break; } - tprintf("}"); + tprintf("%#0*lx", (int) sizeof(long) * 2 + 2, n); } + tprintf("}"); + if (failed) + tprintf(" %#lx", ptr); } else - tprintf(", %lx", ptr); + tprintf(", %#lx", ptr); tprintf(", %lu", maxnodes); } diff --git a/net.c b/net.c index 103278d5..ab71106d 100644 --- a/net.c +++ b/net.c @@ -1082,44 +1082,51 @@ struct tcb *tcp; unsigned long addr; unsigned long len; { - union { - char msg_control[len]; - struct cmsghdr cmsg; - } u; - if (umoven(tcp, addr, len, u.msg_control) < 0) { + 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=%zu, cmsg_level=", u.cmsg.cmsg_len); - printxval(socketlayers, u.cmsg.cmsg_level, "SOL_???"); + tprintf(", {cmsg_len=%zu, cmsg_level=", cmsg->cmsg_len); + printxval(socketlayers, cmsg->cmsg_level, "SOL_???"); tprintf(", cmsg_type="); - if (u.cmsg.cmsg_level == SOL_SOCKET) { - printxval(scmvals, u.cmsg.cmsg_type, "SCM_???"); + 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 (u.cmsg.cmsg_type == SCM_RIGHTS) { - int *fds = (int *) CMSG_DATA (&u.cmsg); + if (cmsg->cmsg_type == SCM_RIGHTS + && CMSG_LEN(sizeof(int)) <= cmsg_len) { + int *fds = (int *) CMSG_DATA (cmsg); int first = 1; + tprintf(", {"); - while ((char *) fds < (u.msg_control - + u.cmsg.cmsg_len)) { + while ((char *) fds < ((char *) cmsg + cmsg_len)) { if (!first) tprintf(", "); tprintf("%d", *fds++); first = 0; } tprintf("}}"); + free(cmsg); return; } - if (u.cmsg.cmsg_type == SCM_CREDENTIALS - && CMSG_LEN(sizeof(struct ucred)) <= u.cmsg.cmsg_len) { - struct ucred *uc = (struct ucred *) CMSG_DATA (&u.cmsg); + 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); tprintf(", ...}"); } @@ -1138,7 +1145,8 @@ long addr; printsock(tcp, (long)msg.msg_name, msg.msg_namelen); tprintf(", msg_iov(%lu)=", (unsigned long)msg.msg_iovlen); - tprint_iov(tcp, msg.msg_iovlen, (long) msg.msg_iov); + tprint_iov(tcp, (unsigned long)msg.msg_iovlen, + (unsigned long)msg.msg_iov); #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL tprintf(", msg_controllen=%lu", (unsigned long)msg.msg_controllen); diff --git a/process.c b/process.c index badcba6f..bc116a47 100644 --- a/process.c +++ b/process.c @@ -1225,34 +1225,53 @@ int sys_setgroups(tcp) struct tcb *tcp; { - int i, len; - GETGROUPS_T *gidset; - if (entering(tcp)) { + unsigned long len, size, start, cur, end, abbrev_end; + GETGROUPS_T gid; + int failed = 0; + len = tcp->u_arg[0]; - tprintf("%u, ", len); - if (len <= 0) { + tprintf("%lu, ", len); + if (len == 0) { tprintf("[]"); return 0; } - gidset = (GETGROUPS_T *) malloc(len * sizeof(GETGROUPS_T)); - if (gidset == NULL) { - fprintf(stderr, "sys_setgroups: out of memory\n"); - return -1; + start = tcp->u_arg[1]; + if (start == 0) { + tprintf("NULL"); + return 0; } - if (!verbose(tcp)) - tprintf("%#lx", tcp->u_arg[1]); - else if (umoven(tcp, tcp->u_arg[1], - len * sizeof(GETGROUPS_T), (char *) gidset) < 0) - tprintf("[?]"); - else { - tprintf("["); - for (i = 0; i < len; i++) - tprintf("%s%lu", i ? ", " : "", - (unsigned long) gidset[i]); - tprintf("]"); + size = len * sizeof(gid); + end = start + size; + if (!verbose(tcp) || 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; + } + tprintf("["); + for (cur = start; cur < end; cur += sizeof(gid)) { + if (cur > start) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; + } + if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) { + tprintf("?"); + failed = 1; + break; + } + tprintf("%lu", (unsigned long) gid); } - free((char *) gidset); + tprintf("]"); + if (failed) + tprintf(" %#lx", tcp->u_arg[1]); } return 0; } @@ -1261,38 +1280,62 @@ int sys_getgroups(tcp) struct tcb *tcp; { - int i, len; - GETGROUPS_T *gidset; + unsigned long len; if (entering(tcp)) { len = tcp->u_arg[0]; - tprintf("%u, ", len); + tprintf("%lu, ", len); } else { + unsigned long size, start, cur, end, abbrev_end; + GETGROUPS_T gid; + int failed = 0; + len = tcp->u_rval; - if (len <= 0) { + if (len == 0) { tprintf("[]"); return 0; } - gidset = (GETGROUPS_T *) malloc(len * sizeof(GETGROUPS_T)); - if (gidset == NULL) { - fprintf(stderr, "sys_getgroups: out of memory\n"); - return -1; - } - if (!tcp->u_arg[1]) + start = tcp->u_arg[1]; + if (start == 0) { tprintf("NULL"); - else if (!verbose(tcp) || tcp->u_arg[0] == 0) - tprintf("%#lx", tcp->u_arg[1]); - else if (umoven(tcp, tcp->u_arg[1], - len * sizeof(GETGROUPS_T), (char *) gidset) < 0) - tprintf("[?]"); - else { - tprintf("["); - for (i = 0; i < len; i++) - tprintf("%s%lu", i ? ", " : "", - (unsigned long) gidset[i]); - tprintf("]"); + return 0; + } + if (tcp->u_arg[0] == 0) { + tprintf("%#lx", start); + 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; + } + tprintf("["); + for (cur = start; cur < end; cur += sizeof(gid)) { + if (cur > start) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; + } + if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) { + tprintf("?"); + failed = 1; + break; + } + tprintf("%lu", (unsigned long) gid); } - free((char *)gidset); + tprintf("]"); + if (failed) + tprintf(" %#lx", tcp->u_arg[1]); } return 0; } @@ -1302,34 +1345,53 @@ int sys_setgroups32(tcp) struct tcb *tcp; { - int i, len; - GETGROUPS32_T *gidset; - if (entering(tcp)) { + unsigned long len, size, start, cur, end, abbrev_end; + GETGROUPS32_T gid; + int failed = 0; + len = tcp->u_arg[0]; - tprintf("%u, ", len); - if (len <= 0) { + tprintf("%lu, ", len); + if (len == 0) { tprintf("[]"); return 0; } - gidset = (GETGROUPS32_T *) malloc(len * sizeof(GETGROUPS32_T)); - if (gidset == NULL) { - fprintf(stderr, "sys_setgroups32: out of memory\n"); - return -1; + start = tcp->u_arg[1]; + if (start == 0) { + tprintf("NULL"); + return 0; } - if (!verbose(tcp)) - tprintf("%#lx", tcp->u_arg[1]); - else if (umoven(tcp, tcp->u_arg[1], - len * sizeof(GETGROUPS32_T), (char *) gidset) < 0) - tprintf("[?]"); - else { - tprintf("["); - for (i = 0; i < len; i++) - tprintf("%s%lu", i ? ", " : "", - (unsigned long) gidset[i]); - tprintf("]"); + size = len * sizeof(gid); + end = start + size; + if (!verbose(tcp) || 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; } - free((char *) gidset); + tprintf("["); + for (cur = start; cur < end; cur += sizeof(gid)) { + if (cur > start) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; + } + if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) { + tprintf("?"); + failed = 1; + break; + } + tprintf("%lu", (unsigned long) gid); + } + tprintf("]"); + if (failed) + tprintf(" %#lx", tcp->u_arg[1]); } return 0; } @@ -1338,38 +1400,58 @@ int sys_getgroups32(tcp) struct tcb *tcp; { - int i, len; - GETGROUPS32_T *gidset; + unsigned long len; if (entering(tcp)) { len = tcp->u_arg[0]; - tprintf("%u, ", len); + tprintf("%lu, ", len); } else { + unsigned long size, start, cur, end, abbrev_end; + GETGROUPS32_T gid; + int failed = 0; + len = tcp->u_rval; - if (len <= 0) { + if (len == 0) { tprintf("[]"); return 0; } - gidset = (GETGROUPS32_T *) malloc(len * sizeof(GETGROUPS32_T)); - if (gidset == NULL) { - fprintf(stderr, "sys_getgroups32: out of memory\n"); - return -1; - } - if (!tcp->u_arg[1]) + start = tcp->u_arg[1]; + if (start == 0) { tprintf("NULL"); - else if (!verbose(tcp) || tcp->u_arg[0] == 0) - tprintf("%#lx", tcp->u_arg[1]); - else if (umoven(tcp, tcp->u_arg[1], - len * sizeof(GETGROUPS32_T), (char *) gidset) < 0) - tprintf("[?]"); - else { - tprintf("["); - for (i = 0; i < len; i++) - tprintf("%s%lu", i ? ", " : "", - (unsigned long) gidset[i]); - tprintf("]"); + 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; } - free((char *)gidset); + tprintf("["); + for (cur = start; cur < end; cur += sizeof(gid)) { + if (cur > start) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; + } + if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) { + tprintf("?"); + failed = 1; + break; + } + tprintf("%lu", (unsigned long) gid); + } + tprintf("]"); + if (failed) + tprintf(" %#lx", tcp->u_arg[1]); } return 0; } diff --git a/stream.c b/stream.c index 998fd8ab..f01fe999 100644 --- a/stream.c +++ b/stream.c @@ -298,61 +298,69 @@ int sys_poll(tcp) struct tcb *tcp; { - struct pollfd *pollp; + struct pollfd fds; + unsigned nfds; + unsigned long size, start, cur, end, abbrev_end; + int failed = 0; - if (exiting(tcp)) { - int i; - int nfds = tcp->u_arg[1]; + if (entering(tcp)) + return 0; - if (nfds <= 0) { - tprintf("%#lx, %d, %ld\n", - tcp->u_arg[0], nfds, tcp->u_arg[2]); - return 0; + nfds = tcp->u_arg[1]; + size = sizeof(fds) * nfds; + start = tcp->u_arg[0]; + end = start + size; + if (nfds == 0 || size / sizeof(fds) != nfds || end < start) { + tprintf("%#lx, %d, %ld", + tcp->u_arg[0], nfds, tcp->u_arg[2]); + return 0; + } + if (abbrev(tcp)) { + abbrev_end = start + max_strlen * sizeof(fds); + if (abbrev_end < start) + abbrev_end = end; + } else { + abbrev_end = end; + } + tprintf("["); + for (cur = start; cur < end; cur += sizeof(fds)) { + if (cur > start) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; } - pollp = (struct pollfd *) malloc(nfds * sizeof(*pollp)); - if (pollp == NULL) { - fprintf(stderr, "sys_poll: no memory\n"); - tprintf("%#lx, %d, %ld", - tcp->u_arg[0], nfds, tcp->u_arg[2]); - return 0; + if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) { + tprintf("?"); + failed = 1; + break; } - if (umoven(tcp, tcp->u_arg[0], - (nfds * sizeof(*pollp)), (char *) pollp) < 0) { - tprintf("%#lx", tcp->u_arg[0]); + if (fds.fd < 0) { + tprintf("{fd=%d}", fds.fd); + continue; } - else { - tprintf("["); - for (i = 0; i < nfds; i++) { - if (i) - tprintf(", "); - if (pollp[i].fd < 0) { - tprintf("{fd=%d}", pollp[i].fd); - continue; - } - tprintf("{fd=%d, events=", pollp[i].fd); - printflags(pollflags, pollp[i].events, - "POLL???"); - if (!syserror(tcp) && pollp[i].revents) { - tprintf(", revents="); - printflags(pollflags, pollp[i].revents, - "POLL???"); - } - tprintf("}"); - } - tprintf("]"); + tprintf("{fd=%d, events=", fds.fd); + printflags(pollflags, fds.events, "POLL???"); + if (!syserror(tcp) && fds.revents) { + tprintf(", revents="); + printflags(pollflags, fds.revents, "POLL???"); } - tprintf(", %d, ", nfds); + tprintf("}"); + } + tprintf("]"); + if (failed) + tprintf(" %#lx", start); + tprintf(", %d, ", nfds); #ifdef INFTIM - if (tcp->u_arg[2] == INFTIM) - tprintf("INFTIM"); - else + if (tcp->u_arg[2] == INFTIM) + tprintf("INFTIM"); + else #endif - tprintf("%ld", tcp->u_arg[2]); - free(pollp); - } + tprintf("%ld", tcp->u_arg[2]); return 0; } + #else /* !HAVE_SYS_POLL_H */ int sys_poll(tcp) diff --git a/system.c b/system.c index 7bbcdcd0..a1c057e3 100644 --- a/system.c +++ b/system.c @@ -1813,23 +1813,25 @@ struct tcb *tcp; { struct __sysctl_args info; int *name; + unsigned long size; + if (umove (tcp, tcp->u_arg[0], &info) < 0) return printargs(tcp); - name = malloc (sizeof (int) * info.nlen); + size = sizeof (int) * (unsigned long) info.nlen; + name = (size / sizeof (int) != info.nlen) ? NULL : malloc (size); if (name == NULL || - umoven(tcp, (unsigned long) info.name, - sizeof (int) * info.nlen, (char *) name) < 0) { - if (name != NULL) - free(name); - tprintf("{%p, %d, %p, %p, %p, %Zu}", - info.name, info.nlen, info.oldval, info.oldlenp, - info.newval, info.newlen); + umoven(tcp, (unsigned long) info.name, size, (char *) name) < 0) { + free(name); + if (entering(tcp)) + tprintf("{%p, %d, %p, %p, %p, %Zu}", + info.name, info.nlen, info.oldval, + info.oldlenp, info.newval, info.newlen); return 0; } if (entering(tcp)) { - int cnt = 0; + int cnt = 0, max_cnt; tprintf("{{"); @@ -1919,13 +1921,16 @@ struct tcb *tcp; goto out; } out: - while (cnt < info.nlen) + max_cnt = abbrev(tcp) ? max_strlen : info.nlen; + while (cnt < max_cnt) tprintf(", %x", name[cnt++]); + if (cnt < info.nlen) + tprintf(", ..."); tprintf("}, %d, ", info.nlen); } else { size_t oldlen; - umove(tcp, (size_t)info.oldlenp, &oldlen); - if (info.nlen >= 2 + if (umove(tcp, (size_t)info.oldlenp, &oldlen) >= 0 + && info.nlen >= 2 && ((name[0] == CTL_KERN && (name[1] == KERN_OSRELEASE || name[1] == KERN_OSTYPE diff --git a/util.c b/util.c index d92c0ea8..e477cf10 100644 --- a/util.c +++ b/util.c @@ -532,15 +532,15 @@ long addr; { struct iovec *iov; int i; + unsigned long size; - - if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) { - fprintf(stderr, "dump: No memory"); + size = sizeof(*iov) * (unsigned long) len; + if (size / sizeof(*iov) != len + || (iov = (struct iovec *) malloc(size)) == NULL) { + fprintf(stderr, "out of memory\n"); return; } - if (umoven(tcp, addr, - len * sizeof *iov, (char *) iov) >= 0) { - + if (umoven(tcp, addr, size, (char *) iov) >= 0) { for (i = 0; i < len; i++) { /* include the buffer number to make it easy to * match up the trace with the source */