summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>2012-03-09 12:51:42 +0200
committerKristian Høgsberg <krh@bitplanet.net>2012-03-10 16:01:46 -0500
commit73d4a53672c66fb2ad9576545a5aae3bad2483ed (patch)
tree9bbe3d01dc32f1b3f59c567a832f750a8ab1243e
parent46df9232faa5f2e154ad14b6b10ca2475dbbf83b (diff)
Flush the connection if we have to many marshaled fdsHEADmaster
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.
-rw-r--r--src/connection.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/src/connection.c b/src/connection.c
index 1ea2418..fa01545 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -56,9 +56,13 @@ struct wl_closure {
uint32_t *start;
};
+#define MAX_FDS_OUT 28
+#define CLEN (CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t)))
+
struct wl_connection {
struct wl_buffer in, out;
struct wl_buffer fds_in, fds_out;
+ int n_fds_out;
int fd;
void *data;
wl_connection_update_func_t update;
@@ -217,7 +221,7 @@ build_cmsg(struct wl_buffer *buffer, char *data, int *clen)
static void
close_fds(struct wl_buffer *buffer)
{
- int fds[32], i, count;
+ int fds[MAX_FDS_OUT], i, count;
size_t size;
size = buffer->head - buffer->tail;
@@ -252,7 +256,7 @@ wl_connection_data(struct wl_connection *connection, uint32_t mask)
{
struct iovec iov[2];
struct msghdr msg;
- char cmsg[128];
+ char cmsg[CLEN];
int len, count, clen;
if (mask & WL_CONNECTION_WRITABLE) {
@@ -389,6 +393,21 @@ wl_message_size_extra(const struct wl_message *message)
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 *
wl_connection_vmarshal(struct wl_connection *connection,
struct wl_object *sender,
@@ -510,8 +529,11 @@ wl_connection_vmarshal(struct wl_connection *connection,
abort();
}
*fd_ptr = dup_fd;
- wl_buffer_put(&connection->fds_out,
- &dup_fd, sizeof dup_fd);
+ if (wl_connection_put_fd(connection, dup_fd)) {
+ printf("request could not be mashaled: "
+ "can't send file descriptor");
+ return NULL;
+ }
break;
default:
fprintf(stderr, "unhandled format code: '%c'\n",