2005-05-31 Dmitry V. Levin <ldv@altlinux.org>
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 574a7d2..e32e3ed 100644
--- a/defs.h
+++ b/defs.h
@@ -458,7 +458,7 @@
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 2432b58..bb30b6f 100644
--- a/desc.c
+++ b/desc.c
@@ -680,20 +680,29 @@
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 821d4a8..52c3631 100644
--- a/file.c
+++ b/file.c
@@ -2347,10 +2347,11 @@
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 86f9abe..414fbbb 100644
--- a/io.c
+++ b/io.c
@@ -78,38 +78,50 @@
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);
- }
- tprintf("]");
+ abbrev_end = end;
}
- free((char *) iov);
+ 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("{");
+ printstr(tcp, (long) iov.iov_base, iov.iov_len);
+ tprintf(", %lu}", (unsigned long)iov.iov_len);
+ }
+ tprintf("]");
+ if (failed)
+ tprintf(" %#lx", addr);
}
int
diff --git a/mem.c b/mem.c
index 08a5f92..636644e 100644
--- a/mem.c
+++ b/mem.c
@@ -692,26 +692,43 @@
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]);
- }
- tprintf("}");
+ 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("%#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 103278d..ab71106 100644
--- a/net.c
+++ b/net.c
@@ -1082,44 +1082,51 @@
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;
- if (u.cmsg.cmsg_type == SCM_RIGHTS) {
- int *fds = (int *) CMSG_DATA (&u.cmsg);
+ 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;
+
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 @@
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 badcba6..bc116a4 100644
--- a/process.c
+++ b/process.c
@@ -1225,34 +1225,53 @@
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;
}
- free((char *) gidset);
+ 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);
+ }
+ tprintf("]");
+ if (failed)
+ tprintf(" %#lx", tcp->u_arg[1]);
}
return 0;
}
@@ -1261,38 +1280,62 @@
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;
}
- free((char *)gidset);
+ 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);
+ }
+ tprintf("]");
+ if (failed)
+ tprintf(" %#lx", tcp->u_arg[1]);
}
return 0;
}
@@ -1302,34 +1345,53 @@
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;
}
- free((char *) gidset);
+ 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);
+ }
+ tprintf("]");
+ if (failed)
+ tprintf(" %#lx", tcp->u_arg[1]);
}
return 0;
}
@@ -1338,38 +1400,58 @@
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;
}
- free((char *)gidset);
+ 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);
+ }
+ tprintf("]");
+ if (failed)
+ tprintf(" %#lx", tcp->u_arg[1]);
}
return 0;
}
diff --git a/stream.c b/stream.c
index 998fd8a..f01fe99 100644
--- a/stream.c
+++ b/stream.c
@@ -298,61 +298,69 @@
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;
- }
- 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, tcp->u_arg[0],
- (nfds * sizeof(*pollp)), (char *) pollp) < 0) {
- tprintf("%#lx", tcp->u_arg[0]);
- }
- 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(", %d, ", nfds);
-#ifdef INFTIM
- if (tcp->u_arg[2] == INFTIM)
- tprintf("INFTIM");
- else
-#endif
- tprintf("%ld", tcp->u_arg[2]);
- free(pollp);
+ 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;
+ }
+ if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
+ tprintf("?");
+ failed = 1;
+ break;
+ }
+ if (fds.fd < 0) {
+ tprintf("{fd=%d}", fds.fd);
+ continue;
+ }
+ tprintf("{fd=%d, events=", fds.fd);
+ printflags(pollflags, fds.events, "POLL???");
+ if (!syserror(tcp) && fds.revents) {
+ tprintf(", revents=");
+ printflags(pollflags, fds.revents, "POLL???");
+ }
+ tprintf("}");
+ }
+ tprintf("]");
+ if (failed)
+ tprintf(" %#lx", start);
+ tprintf(", %d, ", nfds);
+#ifdef INFTIM
+ if (tcp->u_arg[2] == INFTIM)
+ tprintf("INFTIM");
+ else
+#endif
+ 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 7bbcdcd..a1c057e 100644
--- a/system.c
+++ b/system.c
@@ -1813,23 +1813,25 @@
{
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 @@
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 d92c0ea..e477cf1 100644
--- a/util.c
+++ b/util.c
@@ -532,15 +532,15 @@
{
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 */