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/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)