diff options
author | David Herrmann <dh.herrmann@googlemail.com> | 2012-10-11 23:37:46 +0200 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2012-10-15 16:15:41 -0400 |
commit | 9bd41ed6a9f027d687e449ed020db848b28bb58a (patch) | |
tree | 39dec69cd022fad853da847c45bfa0d66aec119d /src | |
parent | cda89f3a42789771907a9d6a3159f7c22c99985e (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.c | 10 |
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; } |