On Fri,  9 Mar 2012 11:18:49 +0200
Ander Conselvan de Oliveira <[email protected]>
wrote:

> 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);

You are not testing the return value of wl_connection_data(). What are
the implications if it fails? Shouldn't the failure be returned back up
in the call chain, and be dealt with, like in
http://cgit.freedesktop.org/wayland/wayland/commit/?id=b26774da5b907a71aa7c72ee1feb6dcde92b9fcb

> +             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",


Thanks,
pq
_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to