mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
connection: fix leaking FDs on buffer-overflow during read
If we read more FDs than we have room for, we currently leak FDs because we overwrite previous still pending FDs. Instead, we do now close incoming FDs if the buffer is full and return EOVERFLOW. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
0b399b8d68
commit
a9dd3badb5
1 changed files with 26 additions and 7 deletions
|
|
@ -229,20 +229,37 @@ build_cmsg(struct wl_buffer *buffer, char *data, int *clen)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg)
|
||||
{
|
||||
struct cmsghdr *cmsg;
|
||||
size_t size;
|
||||
size_t size, max, i;
|
||||
int overflow = 0;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
size = cmsg->cmsg_len - CMSG_LEN(0);
|
||||
if (cmsg->cmsg_level != SOL_SOCKET ||
|
||||
cmsg->cmsg_type != SCM_RIGHTS)
|
||||
continue;
|
||||
|
||||
size = cmsg->cmsg_len - CMSG_LEN(0);
|
||||
max = sizeof(buffer->data) - wl_buffer_size(buffer);
|
||||
if (size > max || overflow) {
|
||||
overflow = 1;
|
||||
size /= sizeof(int32_t);
|
||||
for (i = 0; i < size; ++i)
|
||||
close(((int*)CMSG_DATA(cmsg))[i]);
|
||||
} else {
|
||||
wl_buffer_put(buffer, CMSG_DATA(cmsg), size);
|
||||
}
|
||||
}
|
||||
|
||||
if (overflow) {
|
||||
errno = EOVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -295,7 +312,7 @@ wl_connection_read(struct wl_connection *connection)
|
|||
struct iovec iov[2];
|
||||
struct msghdr msg;
|
||||
char cmsg[CLEN];
|
||||
int len, count;
|
||||
int len, count, ret;
|
||||
|
||||
wl_buffer_put_iov(&connection->in, iov, &count);
|
||||
|
||||
|
|
@ -314,7 +331,9 @@ wl_connection_read(struct wl_connection *connection)
|
|||
if (len <= 0)
|
||||
return len;
|
||||
|
||||
decode_cmsg(&connection->fds_in, &msg);
|
||||
ret = decode_cmsg(&connection->fds_in, &msg);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
connection->in.head += len;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue