[PATCH] Flush the connection if we have to many marshaled fds

Ander Conselvan de Oliveira ander.conselvan.de.oliveira at intel.com
Fri Mar 9 01:18:49 PST 2012


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 forcing that to be written if we would generate a buffer
longer than the maximum.
---
 src/connection.c |   23 +++++++++++++++++++----
 1 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/src/connection.c b/src/connection.c
index 1ea2418..30a99c0 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,18 @@ wl_message_size_extra(const struct wl_message *message)
 	return extra;
 }
 
+static void
+wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
+{
+	if (connection->n_fds_out + 1 > MAX_FDS_OUT) {
+		wl_connection_data(connection, WL_CONNECTION_WRITABLE);
+		connection->n_fds_out = 0;
+	}
+
+	wl_buffer_put(&connection->fds_out, &fd, sizeof fd);
+	connection->n_fds_out++;
+}
+
 struct wl_closure *
 wl_connection_vmarshal(struct wl_connection *connection,
 		       struct wl_object *sender,
@@ -510,8 +526,7 @@ wl_connection_vmarshal(struct wl_connection *connection,
 				abort();
 			}
 			*fd_ptr = dup_fd;
-			wl_buffer_put(&connection->fds_out,
-				      &dup_fd, sizeof dup_fd);
+			wl_connection_put_fd(connection, dup_fd);
 			break;
 		default:
 			fprintf(stderr, "unhandled format code: '%c'\n",
-- 
1.7.4.1



More information about the wayland-devel mailing list