mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-01 22:58:40 -04:00
Flush the connection if we have to many marshaled fds
The buffer used by wl_connection_data to receive a cmsg is 128 bytes long. This can hold at most 28 fds but when a cmsg is generated for sending the fds, there is no check for this limitation. The man page for recvmsg does not show any way of recovering from MSG_CTRUNC, that happens when the buffer supplied for cmsg is too short. Fix this by flushing the data to be written instead of generating a cmsg buffer longer than the maximum.
This commit is contained in:
parent
46df9232fa
commit
73d4a53672
1 changed files with 26 additions and 4 deletions
|
|
@ -56,9 +56,13 @@ struct wl_closure {
|
||||||
uint32_t *start;
|
uint32_t *start;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAX_FDS_OUT 28
|
||||||
|
#define CLEN (CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t)))
|
||||||
|
|
||||||
struct wl_connection {
|
struct wl_connection {
|
||||||
struct wl_buffer in, out;
|
struct wl_buffer in, out;
|
||||||
struct wl_buffer fds_in, fds_out;
|
struct wl_buffer fds_in, fds_out;
|
||||||
|
int n_fds_out;
|
||||||
int fd;
|
int fd;
|
||||||
void *data;
|
void *data;
|
||||||
wl_connection_update_func_t update;
|
wl_connection_update_func_t update;
|
||||||
|
|
@ -217,7 +221,7 @@ build_cmsg(struct wl_buffer *buffer, char *data, int *clen)
|
||||||
static void
|
static void
|
||||||
close_fds(struct wl_buffer *buffer)
|
close_fds(struct wl_buffer *buffer)
|
||||||
{
|
{
|
||||||
int fds[32], i, count;
|
int fds[MAX_FDS_OUT], i, count;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
size = buffer->head - buffer->tail;
|
size = buffer->head - buffer->tail;
|
||||||
|
|
@ -252,7 +256,7 @@ wl_connection_data(struct wl_connection *connection, uint32_t mask)
|
||||||
{
|
{
|
||||||
struct iovec iov[2];
|
struct iovec iov[2];
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
char cmsg[128];
|
char cmsg[CLEN];
|
||||||
int len, count, clen;
|
int len, count, clen;
|
||||||
|
|
||||||
if (mask & WL_CONNECTION_WRITABLE) {
|
if (mask & WL_CONNECTION_WRITABLE) {
|
||||||
|
|
@ -389,6 +393,21 @@ wl_message_size_extra(const struct wl_message *message)
|
||||||
return extra;
|
return extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
|
||||||
|
{
|
||||||
|
if (connection->n_fds_out + 1 > MAX_FDS_OUT) {
|
||||||
|
if (wl_connection_data(connection, WL_CONNECTION_WRITABLE))
|
||||||
|
return -1;
|
||||||
|
connection->n_fds_out = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_buffer_put(&connection->fds_out, &fd, sizeof fd);
|
||||||
|
connection->n_fds_out++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct wl_closure *
|
struct wl_closure *
|
||||||
wl_connection_vmarshal(struct wl_connection *connection,
|
wl_connection_vmarshal(struct wl_connection *connection,
|
||||||
struct wl_object *sender,
|
struct wl_object *sender,
|
||||||
|
|
@ -510,8 +529,11 @@ wl_connection_vmarshal(struct wl_connection *connection,
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
*fd_ptr = dup_fd;
|
*fd_ptr = dup_fd;
|
||||||
wl_buffer_put(&connection->fds_out,
|
if (wl_connection_put_fd(connection, dup_fd)) {
|
||||||
&dup_fd, sizeof dup_fd);
|
printf("request could not be mashaled: "
|
||||||
|
"can't send file descriptor");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "unhandled format code: '%c'\n",
|
fprintf(stderr, "unhandled format code: '%c'\n",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue