summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2012-10-11 23:37:46 +0200
committerKristian Høgsberg <krh@bitplanet.net>2012-10-15 16:15:41 -0400
commit9bd41ed6a9f027d687e449ed020db848b28bb58a (patch)
tree39dec69cd022fad853da847c45bfa0d66aec119d /src
parentcda89f3a42789771907a9d6a3159f7c22c99985e (diff)
connection: fix buffer-overflow in close_fds()
If we push two messages via wl_connection_write() and both messages contain more than MAX_FDS_OUT file-descriptors combined, then wl_connection_flush() will write only MAX_FDS_OUT of them, but close all pending ones, too. Furthermore, close_fds() will copy more FDs out of the buffer than it can hold and cause a buffer overflow. Therefore, we simply pass a maximum limit to close_fds(). During shutdown, we simply close all available FDs. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
Diffstat (limited to 'src')
-rw-r--r--src/connection.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/connection.c b/src/connection.c
index 0df416a..7cf645c 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -168,9 +168,9 @@ wl_connection_create(int fd)
}
static void
-close_fds(struct wl_buffer *buffer)
+close_fds(struct wl_buffer *buffer, int max)
{
- int fds[MAX_FDS_OUT], i, count;
+ int32_t fds[sizeof(buffer->data) / sizeof(int32_t)], i, count;
size_t size;
size = buffer->head - buffer->tail;
@@ -179,6 +179,8 @@ close_fds(struct wl_buffer *buffer)
wl_buffer_copy(buffer, fds, size);
count = size / sizeof fds[0];
+ if (max > 0 && max < count)
+ count = max;
for (i = 0; i < count; i++)
close(fds[i]);
buffer->tail += size;
@@ -187,7 +189,7 @@ close_fds(struct wl_buffer *buffer)
void
wl_connection_destroy(struct wl_connection *connection)
{
- close_fds(&connection->fds_out);
+ close_fds(&connection->fds_out, -1);
close(connection->fd);
free(connection);
}
@@ -273,7 +275,7 @@ wl_connection_flush(struct wl_connection *connection)
if (len == -1)
return -1;
- close_fds(&connection->fds_out);
+ close_fds(&connection->fds_out, MAX_FDS_OUT);
connection->out.tail += len;
}