]> granicus.if.org Git - strace/commitdiff
2005-05-31 Dmitry V. Levin <ldv@altlinux.org>
authorRoland McGrath <roland@redhat.com>
Wed, 1 Jun 2005 19:22:06 +0000 (19:22 +0000)
committerRoland McGrath <roland@redhat.com>
Wed, 1 Jun 2005 19:22:06 +0000 (19:22 +0000)
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.

defs.h
desc.c
file.c
io.c
mem.c
net.c
process.c
stream.c
system.c
util.c

diff --git a/defs.h b/defs.h
index 574a7d2f380d761c72798be23b3cfc05d3220e74..e32e3ed9fb35098ff95a1573d6bb8eba3881e865 100644 (file)
--- 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 2432b58f6446c5f17085ac4d6ee0b50c3de0f369..bb30b6f0082b3b796d6b057aa917b4517a789ed1 100644 (file)
--- 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 821d4a82b07a32075352d08d605f44caf70d9bbb..52c36312f30cd270728a198e356f2a3ddb63a55c 100644 (file)
--- 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 86f9abe0f79515f5d617756f9e26a967f9cb3a0f..414fbbb38b6ad7a88deee065a5fc5347a3a6d56e 100644 (file)
--- 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 08a5f926e06c8cee8e63e8cc5e843e88c129bab6..636644eb81317eb163b860945b966fb3cf0cebaf 100644 (file)
--- 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 103278d545a2c2b3e70e8169a5d2f33f7f6f6ad8..ab71106da195836193e003cfbba33fd985ed6a0d 100644 (file)
--- 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);
index badcba6fc679c7dea593d7f39d40521a601b3796..bc116a4778077e8f0d70fbad517cb6d0ea5d6d7a 100644 (file)
--- 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;
 }
index 998fd8ab4108c8ef5efae9b167ee15f99e8a0d52..f01fe999f95cf94dffee2119f233eb2663c67f6d 100644 (file)
--- 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)
index 7bbcdcd0229b1454757c701d3febcc8aa7efbb43..a1c057e34a3405bb682eff43c481db7d76fc0242 100644 (file)
--- 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 d92c0ea83821749f0f4af177121a26a7e36d2dc3..e477cf10e9ac0f52f894e866b20867d9f6a7aadc 100644 (file)
--- 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 */