diff --git a/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0101-Revert-client-Do-not-warn-about-attached-proxies-on-.patch b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0101-Revert-client-Do-not-warn-about-attached-proxies-on-.patch new file mode 100644 index 000000000..904813e92 --- /dev/null +++ b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0101-Revert-client-Do-not-warn-about-attached-proxies-on-.patch @@ -0,0 +1,134 @@ +From 7a890bbf1d6eef0f1b52a701640afe2e495aaa8c Mon Sep 17 00:00:00 2001 +From: Wujian Sun +Date: Wed, 29 Nov 2023 17:04:51 +0800 +Subject: [PATCH 1/4] Revert "client: Do not warn about attached proxies on + default queue destruction." + +This reverts commit b01a85dfd5e8cda7170b7ba6fe66fc3800f93990. +Upstream-Status: Inappropriate [i.MX specific] +--- + src/wayland-client.c | 14 ++++------ + tests/queue-test.c | 63 +------------------------------------------- + 2 files changed, 6 insertions(+), 71 deletions(-) + +diff --git a/src/wayland-client.c b/src/wayland-client.c +index 105f9be..baebfa9 100644 +--- a/src/wayland-client.c ++++ b/src/wayland-client.c +@@ -304,18 +304,14 @@ wl_event_queue_release(struct wl_event_queue *queue) + if (!wl_list_empty(&queue->proxy_list)) { + struct wl_proxy *proxy, *tmp; + +- if (queue != &queue->display->default_queue) { +- wl_log("warning: queue %p destroyed while proxies " +- "still attached:\n", queue); +- } ++ wl_log("warning: queue %p destroyed while proxies still " ++ "attached:\n", queue); + + wl_list_for_each_safe(proxy, tmp, &queue->proxy_list, + queue_link) { +- if (queue != &queue->display->default_queue) { +- wl_log(" %s@%u still attached\n", +- proxy->object.interface->name, +- proxy->object.id); +- } ++ wl_log(" %s@%u still attached\n", ++ proxy->object.interface->name, ++ proxy->object.id); + proxy->queue = NULL; + wl_list_remove(&proxy->queue_link); + wl_list_init(&proxy->queue_link); +diff --git a/tests/queue-test.c b/tests/queue-test.c +index 4129310..63abc19 100644 +--- a/tests/queue-test.c ++++ b/tests/queue-test.c +@@ -308,22 +308,12 @@ client_test_queue_set_queue_race(void) + } + + static char * +-maybe_map_file(int fd, size_t *len) ++map_file(int fd, size_t *len) + { + char *data; + + *len = lseek(fd, 0, SEEK_END); + data = mmap(0, *len, PROT_READ, MAP_PRIVATE, fd, 0); +- +- return data; +-} +- +-static char * +-map_file(int fd, size_t *len) +-{ +- char *data; +- +- data = maybe_map_file(fd, len); + assert(data != MAP_FAILED && "Failed to mmap file"); + + return data; +@@ -432,45 +422,6 @@ client_test_queue_proxy_event_to_destroyed_queue(void) + wl_display_disconnect(display); + } + +-static void +-client_test_queue_destroy_default_with_attached_proxies(void) +-{ +- struct wl_display *display; +- struct wl_callback *callback; +- char *log; +- size_t log_len; +- char callback_name[24]; +- int ret; +- +- display = wl_display_connect(NULL); +- assert(display); +- +- /* Create a sync dispatching events on the default queue. */ +- callback = wl_display_sync(display); +- assert(callback != NULL); +- +- /* Destroy the default queue (by disconnecting) before the attached +- * object. */ +- wl_display_disconnect(display); +- +- /* Check that the log does not contain any warning about the attached +- * wl_callback proxy. */ +- log = maybe_map_file(client_log_fd, &log_len); +- ret = snprintf(callback_name, sizeof(callback_name), "wl_callback@%u", +- wl_proxy_get_id((struct wl_proxy *) callback)); +- assert(ret > 0 && ret < (int)sizeof(callback_name) && +- "callback name creation failed (possibly truncated)"); +- assert(log == MAP_FAILED || strstr(log, callback_name) == NULL); +- if (log != MAP_FAILED) +- munmap(log, log_len); +- +- /* HACK: Directly free the memory of the wl_callback proxy to appease +- * ASan. We would normally use wl_callback_destroy(), but since we have +- * destroyed the associated wl_display, using this function would lead +- * to memory errors. */ +- free(callback); +-} +- + static void + dummy_bind(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +@@ -585,15 +536,3 @@ TEST(queue_proxy_event_to_destroyed_queue) + /* Check that the client aborted. */ + display_destroy_expect_signal(d, SIGABRT); + } +- +-TEST(queue_destroy_default_with_attached_proxies) +-{ +- struct display *d = display_create(); +- +- test_set_timeout(2); +- +- client_create_noarg(d, client_test_queue_destroy_default_with_attached_proxies); +- display_run(d); +- +- display_destroy(d); +-} +-- +2.17.1 + diff --git a/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0102-Revert-client-Abort-when-trying-to-add-an-event-to-a.patch b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0102-Revert-client-Abort-when-trying-to-add-an-event-to-a.patch new file mode 100644 index 000000000..a1ce6af61 --- /dev/null +++ b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0102-Revert-client-Abort-when-trying-to-add-an-event-to-a.patch @@ -0,0 +1,129 @@ +From ebc08059a18a66f0296e530351be830e8f3e7e53 Mon Sep 17 00:00:00 2001 +From: Wujian Sun +Date: Wed, 29 Nov 2023 17:05:39 +0800 +Subject: [PATCH 2/4] Revert "client: Abort when trying to add an event to a + destroyed queue" + +This reverts commit d72f9007c36f2f8ad2dc26178545e8a7f5b993a0. +Upstream-Status: Inappropriate [i.MX specific] +--- + src/wayland-client.c | 5 ---- + tests/queue-test.c | 61 -------------------------------------------- + 2 files changed, 66 deletions(-) + +diff --git a/src/wayland-client.c b/src/wayland-client.c +index baebfa9..564e227 100644 +--- a/src/wayland-client.c ++++ b/src/wayland-client.c +@@ -312,7 +312,6 @@ wl_event_queue_release(struct wl_event_queue *queue) + wl_log(" %s@%u still attached\n", + proxy->object.interface->name, + proxy->object.id); +- proxy->queue = NULL; + wl_list_remove(&proxy->queue_link); + wl_list_init(&proxy->queue_link); + } +@@ -542,7 +541,6 @@ proxy_destroy(struct wl_proxy *proxy) + + proxy->flags |= WL_PROXY_FLAG_DESTROYED; + +- proxy->queue = NULL; + wl_list_remove(&proxy->queue_link); + wl_list_init(&proxy->queue_link); + +@@ -1567,9 +1565,6 @@ queue_event(struct wl_display *display, int len) + else + queue = proxy->queue; + +- if (!queue) +- wl_abort("Tried to add event to destroyed queue\n"); +- + wl_list_insert(queue->event_list.prev, &closure->link); + + return size; +diff --git a/tests/queue-test.c b/tests/queue-test.c +index 63abc19..f9254f7 100644 +--- a/tests/queue-test.c ++++ b/tests/queue-test.c +@@ -34,7 +34,6 @@ + #include + #include + #include +-#include + + #include "wayland-client.h" + #include "wayland-server.h" +@@ -385,43 +384,6 @@ client_test_queue_destroy_with_attached_proxies(void) + wl_display_disconnect(display); + } + +-static void +-client_test_queue_proxy_event_to_destroyed_queue(void) +-{ +- struct wl_event_queue *queue; +- struct wl_display *display; +- struct wl_display *display_wrapper; +- struct wl_callback *callback; +- +- display = wl_display_connect(NULL); +- assert(display); +- +- /* Pretend we are in a separate thread where a thread-local queue is +- * used. */ +- queue = wl_display_create_queue(display); +- assert(queue); +- +- /* Create a sync dispatching events on the thread-local queue. */ +- display_wrapper = wl_proxy_create_wrapper(display); +- assert(display_wrapper); +- wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue); +- callback = wl_display_sync(display_wrapper); +- wl_proxy_wrapper_destroy(display_wrapper); +- assert(callback != NULL); +- wl_display_flush(display); +- +- /* Destroy the queue before the attached object. */ +- wl_event_queue_destroy(queue); +- +- /* During this roundtrip we should receive the done event on 'callback', +- * try to queue it to the destroyed queue, and abort. */ +- wl_display_roundtrip(display); +- +- wl_callback_destroy(callback); +- +- wl_display_disconnect(display); +-} +- + static void + dummy_bind(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +@@ -513,26 +475,3 @@ TEST(queue_destroy_with_attached_proxies) + + display_destroy(d); + } +- +-TEST(queue_proxy_event_to_destroyed_queue) +-{ +- struct display *d = display_create(); +- struct client_info *ci; +- char *client_log; +- size_t client_log_len; +- +- test_set_timeout(2); +- +- ci = client_create_noarg(d, client_test_queue_proxy_event_to_destroyed_queue); +- display_run(d); +- +- /* Check that the final line in the log mentions the expected reason +- * for the abort. */ +- client_log = map_file(ci->log_fd, &client_log_len); +- assert(!strcmp(last_line_of(client_log), +- "Tried to add event to destroyed queue\n")); +- munmap(client_log, client_log_len); +- +- /* Check that the client aborted. */ +- display_destroy_expect_signal(d, SIGABRT); +-} +-- +2.17.1 + diff --git a/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0103-Revert-client-Warn-when-a-queue-is-destroyed-with-at.patch b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0103-Revert-client-Warn-when-a-queue-is-destroyed-with-at.patch new file mode 100644 index 000000000..1c6f0b428 --- /dev/null +++ b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0103-Revert-client-Warn-when-a-queue-is-destroyed-with-at.patch @@ -0,0 +1,163 @@ +From 629b02dfa53ed6dc19378853b6f2ca3a308e30fe Mon Sep 17 00:00:00 2001 +From: Wujian Sun +Date: Wed, 29 Nov 2023 17:05:59 +0800 +Subject: [PATCH 3/4] Revert "client: Warn when a queue is destroyed with + attached proxies" + +This reverts commit 0ba650202e742b23150054cf0740168cd529b010. +Upstream-Status: Inappropriate [i.MX specific] +--- + src/wayland-client.c | 16 -------- + tests/queue-test.c | 93 -------------------------------------------- + 2 files changed, 109 deletions(-) + +diff --git a/src/wayland-client.c b/src/wayland-client.c +index 564e227..8c897d4 100644 +--- a/src/wayland-client.c ++++ b/src/wayland-client.c +@@ -301,22 +301,6 @@ wl_event_queue_release(struct wl_event_queue *queue) + { + struct wl_closure *closure; + +- if (!wl_list_empty(&queue->proxy_list)) { +- struct wl_proxy *proxy, *tmp; +- +- wl_log("warning: queue %p destroyed while proxies still " +- "attached:\n", queue); +- +- wl_list_for_each_safe(proxy, tmp, &queue->proxy_list, +- queue_link) { +- wl_log(" %s@%u still attached\n", +- proxy->object.interface->name, +- proxy->object.id); +- wl_list_remove(&proxy->queue_link); +- wl_list_init(&proxy->queue_link); +- } +- } +- + while (!wl_list_empty(&queue->event_list)) { + closure = wl_container_of(queue->event_list.next, + closure, link); +diff --git a/tests/queue-test.c b/tests/queue-test.c +index f9254f7..86a3602 100644 +--- a/tests/queue-test.c ++++ b/tests/queue-test.c +@@ -23,14 +23,11 @@ + * SOFTWARE. + */ + +-#define _GNU_SOURCE /* For memrchr */ + #include + #include + #include + #include +-#include + #include +-#include + #include + #include + #include +@@ -306,84 +303,6 @@ client_test_queue_set_queue_race(void) + wl_display_disconnect(display); + } + +-static char * +-map_file(int fd, size_t *len) +-{ +- char *data; +- +- *len = lseek(fd, 0, SEEK_END); +- data = mmap(0, *len, PROT_READ, MAP_PRIVATE, fd, 0); +- assert(data != MAP_FAILED && "Failed to mmap file"); +- +- return data; +-} +- +-static char * +-last_line_of(char *s) +-{ +- size_t len = strlen(s); +- char *last; +- +- last = memrchr(s, '\n', len); +- /* If we found a newline at end of string, find the previous one. */ +- if (last && last[1] == 0) +- last = memrchr(s, '\n', len - 1); +- /* If we have a newline, the last line starts after the newline. +- * Otherwise, the whole string is the last line. */ +- if (last) +- last += 1; +- else +- last = s; +- +- return last; +-} +- +-static void +-client_test_queue_destroy_with_attached_proxies(void) +-{ +- struct wl_event_queue *queue; +- struct wl_display *display; +- struct wl_display *display_wrapper; +- struct wl_callback *callback; +- char *log; +- size_t log_len; +- char callback_name[24]; +- int ret; +- +- display = wl_display_connect(NULL); +- assert(display); +- +- /* Pretend we are in a separate thread where a thread-local queue is +- * used. */ +- queue = wl_display_create_queue(display); +- assert(queue); +- +- /* Create a sync dispatching events on the thread-local queue. */ +- display_wrapper = wl_proxy_create_wrapper(display); +- assert(display_wrapper); +- wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue); +- callback = wl_display_sync(display_wrapper); +- wl_proxy_wrapper_destroy(display_wrapper); +- assert(callback != NULL); +- +- /* Destroy the queue before the attached object. */ +- wl_event_queue_destroy(queue); +- +- /* Check that the log contains some information about the attached +- * wl_callback proxy. */ +- log = map_file(client_log_fd, &log_len); +- ret = snprintf(callback_name, sizeof(callback_name), "wl_callback@%u", +- wl_proxy_get_id((struct wl_proxy *) callback)); +- assert(ret > 0 && ret < (int)sizeof(callback_name) && +- "callback name creation failed (possibly truncated)"); +- assert(strstr(last_line_of(log), callback_name)); +- munmap(log, log_len); +- +- wl_callback_destroy(callback); +- +- wl_display_disconnect(display); +-} +- + static void + dummy_bind(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +@@ -463,15 +382,3 @@ TEST(queue_set_queue_race) + + display_destroy(d); + } +- +-TEST(queue_destroy_with_attached_proxies) +-{ +- struct display *d = display_create(); +- +- test_set_timeout(2); +- +- client_create_noarg(d, client_test_queue_destroy_with_attached_proxies); +- display_run(d); +- +- display_destroy(d); +-} +-- +2.17.1 + diff --git a/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0104-Revert-client-Track-the-proxies-attached-to-a-queue.patch b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0104-Revert-client-Track-the-proxies-attached-to-a-queue.patch new file mode 100644 index 000000000..fa03c3fc6 --- /dev/null +++ b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0104-Revert-client-Track-the-proxies-attached-to-a-queue.patch @@ -0,0 +1,107 @@ +From 5780ff48cd5e40c2669f3cd94653ab7f850d7a98 Mon Sep 17 00:00:00 2001 +From: Wujian Sun +Date: Wed, 29 Nov 2023 17:06:22 +0800 +Subject: [PATCH 4/4] Revert "client: Track the proxies attached to a queue" + +This reverts commit 674145dc3f621e5a3673714c7527d0e1c5336ab1. +Upstream-Status: Inappropriate [i.MX specific] +--- + src/wayland-client.c | 22 ---------------------- + 1 file changed, 22 deletions(-) + +diff --git a/src/wayland-client.c b/src/wayland-client.c +index 8c897d4..b57bfe9 100644 +--- a/src/wayland-client.c ++++ b/src/wayland-client.c +@@ -70,12 +70,10 @@ struct wl_proxy { + wl_dispatcher_func_t dispatcher; + uint32_t version; + const char * const *tag; +- struct wl_list queue_link; /**< in struct wl_event_queue::proxy_list */ + }; + + struct wl_event_queue { + struct wl_list event_list; +- struct wl_list proxy_list; /**< struct wl_proxy::queue_link */ + struct wl_display *display; + }; + +@@ -223,7 +221,6 @@ static void + wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display) + { + wl_list_init(&queue->event_list); +- wl_list_init(&queue->proxy_list); + queue->display = display; + } + +@@ -438,8 +435,6 @@ proxy_create(struct wl_proxy *factory, const struct wl_interface *interface, + return NULL; + } + +- wl_list_insert(&proxy->queue->proxy_list, &proxy->queue_link); +- + return proxy; + } + +@@ -499,8 +494,6 @@ wl_proxy_create_for_id(struct wl_proxy *factory, + return NULL; + } + +- wl_list_insert(&proxy->queue->proxy_list, &proxy->queue_link); +- + return proxy; + } + +@@ -525,9 +518,6 @@ proxy_destroy(struct wl_proxy *proxy) + + proxy->flags |= WL_PROXY_FLAG_DESTROYED; + +- wl_list_remove(&proxy->queue_link); +- wl_list_init(&proxy->queue_link); +- + wl_proxy_unref(proxy); + } + +@@ -2346,8 +2336,6 @@ wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue) + { + pthread_mutex_lock(&proxy->display->mutex); + +- wl_list_remove(&proxy->queue_link); +- + if (queue) { + assert(proxy->display == queue->display); + proxy->queue = queue; +@@ -2355,8 +2343,6 @@ wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue) + proxy->queue = &proxy->display->default_queue; + } + +- wl_list_insert(&proxy->queue->proxy_list, &proxy->queue_link); +- + pthread_mutex_unlock(&proxy->display->mutex); + } + +@@ -2428,8 +2414,6 @@ wl_proxy_create_wrapper(void *proxy) + wrapper->flags = WL_PROXY_FLAG_WRAPPER; + wrapper->refcount = 1; + +- wl_list_insert(&wrapper->queue->proxy_list, &wrapper->queue_link); +- + pthread_mutex_unlock(&wrapped_proxy->display->mutex); + + return wrapper; +@@ -2451,12 +2435,6 @@ wl_proxy_wrapper_destroy(void *proxy_wrapper) + + assert(wrapper->refcount == 1); + +- pthread_mutex_lock(&wrapper->display->mutex); +- +- wl_list_remove(&wrapper->queue_link); +- +- pthread_mutex_unlock(&wrapper->display->mutex); +- + free(wrapper); + } + +-- +2.17.1 + diff --git a/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0201-Apply-WIP-CL-from-upstream-wayland.patch b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0201-Apply-WIP-CL-from-upstream-wayland.patch new file mode 100644 index 000000000..38d6365b2 --- /dev/null +++ b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0201-Apply-WIP-CL-from-upstream-wayland.patch @@ -0,0 +1,795 @@ +From 223d1f32861e21bf9827b813659fbe46c97d8e66 Mon Sep 17 00:00:00 2001 +From: Erik Chen +Date: Thu, 20 Oct 2022 00:06:01 +0000 +Subject: [PATCH 1/5] Apply WIP CL from upstream wayland + +This CL provides the capability of dynamically modifying the buffer size. +https://gitlab.freedesktop.org/wayland/wayland/-/commit/0bfcd4c4bef0ddb555c0e9f07cd3ceff81a33313 + +Note that I am not the author. This CL has been reviewed upstream. + +Bug: 1342356 +Change-Id: I24f90fb31248a52aa97f1813a5ff9b30157aa350 +Upstream-Status: Pending +--- + src/connection.c | 303 ++++++++++++++++++++++++++++---------- + src/wayland-client.c | 2 +- + src/wayland-private.h | 8 +- + src/wayland-server-core.h | 7 + + src/wayland-server.c | 63 +++++++- + tests/connection-test.c | 46 +++++- + tests/display-test.c | 5 +- + tests/os-wrappers-test.c | 6 +- + 8 files changed, 350 insertions(+), 90 deletions(-) + +diff --git a/src/connection.c b/src/connection.c +index ceaeac1..bc6d730 100644 +--- a/src/connection.c ++++ b/src/connection.c +@@ -55,12 +55,12 @@ div_roundup(uint32_t n, size_t a) + } + + struct wl_ring_buffer { +- char data[4096]; +- uint32_t head, tail; ++ char *data; ++ size_t head, tail; ++ uint32_t size_bits; ++ uint32_t max_size_bits; /* 0 for unlimited */ + }; + +-#define MASK(i) ((i) & 4095) +- + #define MAX_FDS_OUT 28 + #define CLEN (CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t))) + +@@ -71,23 +71,27 @@ struct wl_connection { + int want_flush; + }; + ++static size_t ++ring_buffer_space(const struct wl_ring_buffer *b) { ++ return ((size_t)1) << b->size_bits; ++} ++ ++static size_t ++ring_buffer_mask(const struct wl_ring_buffer *b, size_t i) { ++ size_t m = (((size_t)1) << b->size_bits) - 1; ++ return i & m; ++} ++ + static int + ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count) + { +- uint32_t head, size; ++ size_t head, size; + +- if (count > sizeof(b->data)) { +- wl_log("Data too big for buffer (%d > %d).\n", +- count, sizeof(b->data)); +- errno = E2BIG; +- return -1; +- } +- +- head = MASK(b->head); +- if (head + count <= sizeof b->data) { ++ head = ring_buffer_mask(b, b->head); ++ if (head + count <= ring_buffer_space(b)) { + memcpy(b->data + head, data, count); + } else { +- size = sizeof b->data - head; ++ size = ring_buffer_space(b) - head; + memcpy(b->data + head, data, size); + memcpy(b->data, (const char *) data + size, count - size); + } +@@ -100,21 +104,21 @@ ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count) + static void + ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count) + { +- uint32_t head, tail; ++ size_t head, tail; + +- head = MASK(b->head); +- tail = MASK(b->tail); ++ head = ring_buffer_mask(b, b->head); ++ tail = ring_buffer_mask(b, b->tail); + if (head < tail) { + iov[0].iov_base = b->data + head; + iov[0].iov_len = tail - head; + *count = 1; + } else if (tail == 0) { + iov[0].iov_base = b->data + head; +- iov[0].iov_len = sizeof b->data - head; ++ iov[0].iov_len = ring_buffer_space(b) - head; + *count = 1; + } else { + iov[0].iov_base = b->data + head; +- iov[0].iov_len = sizeof b->data - head; ++ iov[0].iov_len = ring_buffer_space(b) - head; + iov[1].iov_base = b->data; + iov[1].iov_len = tail; + *count = 2; +@@ -124,21 +128,21 @@ ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count) + static void + ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count) + { +- uint32_t head, tail; ++ size_t head, tail; + +- head = MASK(b->head); +- tail = MASK(b->tail); ++ head = ring_buffer_mask(b, b->head); ++ tail = ring_buffer_mask(b, b->tail); + if (tail < head) { + iov[0].iov_base = b->data + tail; + iov[0].iov_len = head - tail; + *count = 1; + } else if (head == 0) { + iov[0].iov_base = b->data + tail; +- iov[0].iov_len = sizeof b->data - tail; ++ iov[0].iov_len = ring_buffer_space(b) - tail; + *count = 1; + } else { + iov[0].iov_base = b->data + tail; +- iov[0].iov_len = sizeof b->data - tail; ++ iov[0].iov_len = ring_buffer_space(b) - tail; + iov[1].iov_base = b->data; + iov[1].iov_len = head; + *count = 2; +@@ -148,26 +152,136 @@ ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count) + static void + ring_buffer_copy(struct wl_ring_buffer *b, void *data, size_t count) + { +- uint32_t tail, size; ++ size_t tail, size; + +- tail = MASK(b->tail); +- if (tail + count <= sizeof b->data) { ++ tail = ring_buffer_mask(b, b->tail); ++ if (tail + count <= ring_buffer_space(b)) { + memcpy(data, b->data + tail, count); + } else { +- size = sizeof b->data - tail; ++ size = ring_buffer_space(b) - tail; + memcpy(data, b->data + tail, size); + memcpy((char *) data + size, b->data, count - size); + } + } + +-static uint32_t ++static size_t + ring_buffer_size(struct wl_ring_buffer *b) + { + return b->head - b->tail; + } + ++static uint32_t ++get_max_size_bits_for_size(size_t buffer_size) ++{ ++ uint32_t max_size_bits = WL_BUFFER_DEFAULT_SIZE_POT; ++ ++ /* buffer_size == 0 means unbound buffer size */ ++ if (buffer_size == 0) ++ return 0; ++ ++ do { ++ if (buffer_size <= (((size_t)1) << max_size_bits)) ++ break; ++ } while (max_size_bits++ < (8 * sizeof(size_t) - 1)); ++ ++ return max_size_bits; ++} ++ ++static int ++ring_buffer_allocate(struct wl_ring_buffer *b, size_t size_bits) ++{ ++ char *new_data; ++ ++ new_data = calloc(((size_t)1) << size_bits, 1); ++ if (!new_data) { ++ errno = ENOMEM; ++ return -1; ++ } ++ ++ ring_buffer_copy(b, new_data, ring_buffer_size(b)); ++ free(b->data); ++ b->data = new_data; ++ b->size_bits = size_bits; ++ b->head = ring_buffer_size(b); ++ b->tail = 0; ++ ++ return 0; ++} ++ ++static size_t ++ring_buffer_get_bits_for_size(struct wl_ring_buffer *b, size_t count) ++{ ++ size_t net_size = ring_buffer_size(b) + count; ++ size_t max_size_bits = get_max_size_bits_for_size(net_size); ++ ++ if (max_size_bits < WL_BUFFER_DEFAULT_SIZE_POT) ++ max_size_bits = WL_BUFFER_DEFAULT_SIZE_POT; ++ ++ if (b->max_size_bits > 0 && max_size_bits > b->max_size_bits) ++ max_size_bits = b->max_size_bits; ++ ++ return max_size_bits; ++} ++ ++static int ++ring_buffer_check_space(struct wl_ring_buffer *b, size_t count) ++{ ++ if (ring_buffer_size(b) + count > ring_buffer_space(b)) { ++ wl_log("Data too big for buffer (%d + %zd > %zd).\n", ++ ring_buffer_size(b), count, ring_buffer_space(b)); ++ errno = E2BIG; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++ring_buffer_ensure_space(struct wl_ring_buffer *b, size_t count) ++{ ++ size_t size_bits = ring_buffer_get_bits_for_size(b, count); ++ size_t net_size = ring_buffer_size(b) + count; ++ ++ if (b->data == NULL) ++ return ring_buffer_allocate(b, size_bits); ++ ++ /* Do not shrink (reallocate) if net size won't fit */ ++ if (net_size >= (((size_t)1) << size_bits) || b->size_bits == size_bits) ++ return ring_buffer_check_space(b, count); ++ ++ if (ring_buffer_allocate(b, size_bits) < 0) ++ return -1; ++ ++ return ring_buffer_check_space(b, count); ++} ++ ++void ++wl_connection_set_max_buffer_size(struct wl_connection *connection, ++ size_t max_buffer_size) ++{ ++ uint32_t max_size_bits; ++ ++ max_size_bits = get_max_size_bits_for_size(max_buffer_size); ++ ++ connection->fds_in.size_bits = WL_BUFFER_DEFAULT_SIZE_POT; ++ connection->fds_in.max_size_bits = max_size_bits; ++ ring_buffer_ensure_space(&connection->fds_in, 0); ++ ++ connection->fds_out.size_bits = WL_BUFFER_DEFAULT_SIZE_POT; ++ connection->fds_out.max_size_bits = max_size_bits; ++ ring_buffer_ensure_space(&connection->fds_out, 0); ++ ++ connection->in.size_bits = WL_BUFFER_DEFAULT_SIZE_POT; ++ connection->in.max_size_bits = max_size_bits; ++ ring_buffer_ensure_space(&connection->in, 0); ++ ++ connection->out.size_bits = WL_BUFFER_DEFAULT_SIZE_POT; ++ connection->out.max_size_bits = max_size_bits; ++ ring_buffer_ensure_space(&connection->out, 0); ++} ++ + struct wl_connection * +-wl_connection_create(int fd) ++wl_connection_create(int fd, size_t max_buffer_size) + { + struct wl_connection *connection; + +@@ -175,6 +289,8 @@ wl_connection_create(int fd) + if (connection == NULL) + return NULL; + ++ wl_connection_set_max_buffer_size(connection, max_buffer_size); ++ + connection->fd = fd; + + return connection; +@@ -183,20 +299,28 @@ wl_connection_create(int fd) + static void + close_fds(struct wl_ring_buffer *buffer, int max) + { +- int32_t fds[sizeof(buffer->data) / sizeof(int32_t)], i, count; +- size_t size; ++ size_t size, tail, space; ++ int32_t i, count, *p; + + size = ring_buffer_size(buffer); + if (size == 0) + return; + +- ring_buffer_copy(buffer, fds, size); +- count = size / sizeof fds[0]; ++ count = size / sizeof(int32_t); + if (max > 0 && max < count) + count = max; +- size = count * sizeof fds[0]; +- for (i = 0; i < count; i++) +- close(fds[i]); ++ ++ tail = ring_buffer_mask(buffer, buffer->tail); ++ space = ring_buffer_space(buffer); ++ ++ p = (int32_t *) (buffer->data + tail); ++ for (i = 0; i < count; i++) { ++ if (p >= (int32_t *) (buffer->data + space)) ++ p = (int32_t *) buffer->data; ++ close(*p++); ++ } ++ ++ size = count * sizeof(int32_t); + buffer->tail += size; + } + +@@ -213,6 +337,10 @@ wl_connection_destroy(struct wl_connection *connection) + + close_fds(&connection->fds_out, -1); + close_fds(&connection->fds_in, -1); ++ free(connection->fds_in.data); ++ free(connection->fds_out.data); ++ free(connection->in.data); ++ free(connection->out.data); + free(connection); + + return fd; +@@ -256,7 +384,7 @@ static int + decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg) + { + struct cmsghdr *cmsg; +- size_t size, max, i; ++ size_t size, i; + int overflow = 0; + + for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; +@@ -266,8 +394,8 @@ decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg) + continue; + + size = cmsg->cmsg_len - CMSG_LEN(0); +- max = sizeof(buffer->data) - ring_buffer_size(buffer); +- if (size > max || overflow) { ++ ++ if (ring_buffer_ensure_space(buffer, size) < 0 || overflow) { + overflow = 1; + size /= sizeof(int32_t); + for (i = 0; i < size; i++) +@@ -293,17 +421,30 @@ wl_connection_flush(struct wl_connection *connection) + char cmsg[CLEN]; + int len = 0, count; + size_t clen; +- uint32_t tail; ++ size_t tail; + + if (!connection->want_flush) + return 0; + + tail = connection->out.tail; + while (connection->out.head - connection->out.tail > 0) { +- ring_buffer_get_iov(&connection->out, iov, &count); +- + build_cmsg(&connection->fds_out, cmsg, &clen); + ++ if (clen >= CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t))) { ++ /* Send only a single byte, to ensure all FDs are sent ++ * before the bytes are cleared out. This can fail to ++ * clear the FDs first if individual messages are allowed to ++ * have 8*28 = 224 fds. */ ++ iov[0].iov_base = connection->out.data + ++ ring_buffer_mask(&connection->out, connection->out.tail); ++ iov[0].iov_len = 1; ++ count = 1; ++ } else { ++ ring_buffer_get_iov(&connection->out, iov, &count); ++ } ++ ++ msg.msg_name = NULL; ++ msg.msg_namelen = 0; + msg.msg_iov = iov; + msg.msg_iovlen = count; + msg.msg_control = (clen > 0) ? cmsg : NULL; +@@ -341,49 +482,49 @@ wl_connection_read(struct wl_connection *connection) + char cmsg[CLEN]; + int len, count, ret; + +- if (ring_buffer_size(&connection->in) >= sizeof(connection->in.data)) { +- errno = EOVERFLOW; +- return -1; +- } ++ while (1) { ++ int data_size = ring_buffer_size(&connection->in); ++ size_t size_bits = ring_buffer_get_bits_for_size(&connection->in, 1); + +- ring_buffer_put_iov(&connection->in, iov, &count); ++ // stop once we've read the max buffer size ++ if (data_size >= (1 << size_bits)) ++ return data_size; ++ if (ring_buffer_ensure_space(&connection->in, 1) < 0) ++ return -1; + +- msg.msg_name = NULL; +- msg.msg_namelen = 0; +- msg.msg_iov = iov; +- msg.msg_iovlen = count; +- msg.msg_control = cmsg; +- msg.msg_controllen = sizeof cmsg; +- msg.msg_flags = 0; ++ ring_buffer_put_iov(&connection->in, iov, &count); + +- do { +- len = wl_os_recvmsg_cloexec(connection->fd, &msg, MSG_DONTWAIT); +- } while (len < 0 && errno == EINTR); ++ msg.msg_name = NULL; ++ msg.msg_namelen = 0; ++ msg.msg_iov = iov; ++ msg.msg_iovlen = count; ++ msg.msg_control = cmsg; ++ msg.msg_controllen = sizeof cmsg; ++ msg.msg_flags = 0; + +- if (len <= 0) +- return len; ++ do { ++ len = wl_os_recvmsg_cloexec(connection->fd, &msg, MSG_DONTWAIT); ++ } while (len < 0 && errno == EINTR); + +- ret = decode_cmsg(&connection->fds_in, &msg); +- if (ret) +- return -1; ++ if (len < 0 && errno != EAGAIN) { ++ return -1; ++ } else if (len <= 0) { ++ return (data_size > 0) ? data_size : len; ++ } + +- connection->in.head += len; ++ ret = decode_cmsg(&connection->fds_in, &msg); ++ if (ret) ++ return -1; + +- return wl_connection_pending_input(connection); ++ connection->in.head += len; ++ } + } + + int + wl_connection_write(struct wl_connection *connection, + const void *data, size_t count) + { +- if (connection->out.head - connection->out.tail + +- count > ARRAY_LENGTH(connection->out.data)) { +- connection->want_flush = 1; +- if (wl_connection_flush(connection) < 0) +- return -1; +- } +- +- if (ring_buffer_put(&connection->out, data, count) < 0) ++ if (wl_connection_queue(connection, data, count) < 0) + return -1; + + connection->want_flush = 1; +@@ -396,12 +537,15 @@ wl_connection_queue(struct wl_connection *connection, + const void *data, size_t count) + { + if (connection->out.head - connection->out.tail + +- count > ARRAY_LENGTH(connection->out.data)) { ++ count > WL_BUFFER_DEFAULT_MAX_SIZE) { + connection->want_flush = 1; +- if (wl_connection_flush(connection) < 0) ++ if (wl_connection_flush(connection) < 0 && errno != EAGAIN) + return -1; + } + ++ if (ring_buffer_ensure_space(&connection->out, count) < 0) ++ return -1; ++ + return ring_buffer_put(&connection->out, data, count); + } + +@@ -427,12 +571,15 @@ wl_connection_get_fd(struct wl_connection *connection) + static int + wl_connection_put_fd(struct wl_connection *connection, int32_t fd) + { +- if (ring_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) { ++ if (ring_buffer_size(&connection->fds_out) >= MAX_FDS_OUT * sizeof fd) { + connection->want_flush = 1; +- if (wl_connection_flush(connection) < 0) ++ if (wl_connection_flush(connection) < 0 && errno != EAGAIN) + return -1; + } + ++ if (ring_buffer_ensure_space(&connection->fds_out, sizeof fd) < 0) ++ return -1; ++ + return ring_buffer_put(&connection->fds_out, &fd, sizeof fd); + } + +diff --git a/src/wayland-client.c b/src/wayland-client.c +index b57bfe9..895d7b8 100644 +--- a/src/wayland-client.c ++++ b/src/wayland-client.c +@@ -1198,7 +1198,7 @@ wl_display_connect_to_fd(int fd) + */ + display->proxy.version = 0; + +- display->connection = wl_connection_create(display->fd); ++ display->connection = wl_connection_create(display->fd, 0); + if (display->connection == NULL) + goto err_connection; + +diff --git a/src/wayland-private.h b/src/wayland-private.h +index 9274f1b..a3a5032 100644 +--- a/src/wayland-private.h ++++ b/src/wayland-private.h +@@ -47,6 +47,8 @@ + #define WL_SERVER_ID_START 0xff000000 + #define WL_MAP_MAX_OBJECTS 0x00f00000 + #define WL_CLOSURE_MAX_ARGS 20 ++#define WL_BUFFER_DEFAULT_SIZE_POT 12 ++#define WL_BUFFER_DEFAULT_MAX_SIZE (1 << WL_BUFFER_DEFAULT_SIZE_POT) + + struct wl_object { + const struct wl_interface *interface; +@@ -106,7 +108,7 @@ void + wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data); + + struct wl_connection * +-wl_connection_create(int fd); ++wl_connection_create(int fd, size_t max_buffer_size); + + int + wl_connection_destroy(struct wl_connection *connection); +@@ -237,4 +239,8 @@ zalloc(size_t s) + void + wl_connection_close_fds_in(struct wl_connection *connection, int max); + ++void ++wl_connection_set_max_buffer_size(struct wl_connection *connection, ++ size_t max_buffer_size); ++ + #endif +diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h +index df95821..15ee498 100644 +--- a/src/wayland-server-core.h ++++ b/src/wayland-server-core.h +@@ -217,6 +217,10 @@ wl_display_flush_clients(struct wl_display *display); + void + wl_display_destroy_clients(struct wl_display *display); + ++void ++wl_display_set_default_max_buffer_size(struct wl_display *display, ++ size_t max_buffer_size); ++ + struct wl_client; + + typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data, +@@ -365,6 +369,9 @@ wl_client_for_each_resource(struct wl_client *client, + wl_client_for_each_resource_iterator_func_t iterator, + void *user_data); + ++void ++wl_client_set_max_buffer_size(struct wl_client *client, size_t max_buffer_size); ++ + /** \class wl_listener + * + * \brief A single listener for Wayland signals +diff --git a/src/wayland-server.c b/src/wayland-server.c +index d51acc6..166a065 100644 +--- a/src/wayland-server.c ++++ b/src/wayland-server.c +@@ -110,6 +110,8 @@ struct wl_display { + + int terminate_efd; + struct wl_event_source *term_source; ++ ++ size_t max_buffer_size; + }; + + struct wl_global { +@@ -538,7 +540,8 @@ wl_client_create(struct wl_display *display, int fd) + &client->pid) != 0) + goto err_source; + +- client->connection = wl_connection_create(fd); ++ client->connection = wl_connection_create(fd, display->max_buffer_size); ++ + if (client->connection == NULL) + goto err_source; + +@@ -1144,6 +1147,7 @@ wl_display_create(void) + + display->global_filter = NULL; + display->global_filter_data = NULL; ++ display->max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE; + + wl_array_init(&display->additional_shm_formats); + +@@ -1550,6 +1554,36 @@ wl_display_destroy_clients(struct wl_display *display) + } + } + ++/** Sets the default maximum size for connection buffers of new clients ++ * ++ * \param display The display object ++ * \param max_buffer_size The default maximum size of the connection buffers ++ * ++ * This function sets the default size of the internal connection buffers for ++ * new clients, it doesn't change the buffer size for existing wl_client. ++ * ++ * The connection buffer size of each existing wl_client can be adjusted using ++ * wl_client_set_max_buffer_size(). ++ * ++ * The actual size of the connection buffers is a power of two, the requested ++ * \a max_buffer_size is therefore rounded up to the nearest power of two value. ++ * ++ * The minimum buffer size is 4096. ++ * ++ * \sa wl_client_set_max_buffer_size ++ * ++ * \memberof wl_display ++ */ ++WL_EXPORT void ++wl_display_set_default_max_buffer_size(struct wl_display *display, ++ size_t max_buffer_size) ++{ ++ if (max_buffer_size < WL_BUFFER_DEFAULT_MAX_SIZE) ++ max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE; ++ ++ display->max_buffer_size = max_buffer_size; ++} ++ + static int + socket_data(int fd, uint32_t mask, void *data) + { +@@ -2245,6 +2279,33 @@ wl_signal_emit_mutable(struct wl_signal *signal, void *data) + wl_list_remove(&end.link); + } + ++/** Adjust the maximum size of the client connection buffers ++ * ++ * \param client The client object ++ * \param max_buffer_size The maximum size of the connection buffers ++ * ++ * The actual size of the connection buffers is a power of two, the requested ++ * \a max_buffer_size is therefore rounded up to the nearest power of two value. ++ * ++ * Lowering the maximum size may not take effect immediately if the current content ++ * of the buffer does not fit within the new size limit. ++ * ++ * The minimum buffer size is 4096. The default buffers size can be set using ++ * wl_display_set_default_max_buffer_size() ++ * ++ * \sa wl_display_set_default_max_buffer_size() ++ * ++ * \memberof wl_client ++ */ ++WL_EXPORT void ++wl_client_set_max_buffer_size(struct wl_client *client, size_t max_buffer_size) ++{ ++ if (max_buffer_size < WL_BUFFER_DEFAULT_MAX_SIZE) ++ max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE; ++ ++ wl_connection_set_max_buffer_size(client->connection, max_buffer_size); ++} ++ + /** \cond INTERNAL */ + + /** Initialize a wl_priv_signal object +diff --git a/tests/connection-test.c b/tests/connection-test.c +index 9762e0d..0c76045 100644 +--- a/tests/connection-test.c ++++ b/tests/connection-test.c +@@ -50,7 +50,7 @@ setup(int *s) + + assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0); + +- connection = wl_connection_create(s[0]); ++ connection = wl_connection_create(s[0], WL_BUFFER_DEFAULT_MAX_SIZE); + assert(connection); + + return connection; +@@ -183,9 +183,11 @@ setup_marshal_data(struct marshal_data *data) + { + assert(socketpair(AF_UNIX, + SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); +- data->read_connection = wl_connection_create(data->s[0]); ++ data->read_connection = wl_connection_create(data->s[0], ++ WL_BUFFER_DEFAULT_MAX_SIZE); + assert(data->read_connection); +- data->write_connection = wl_connection_create(data->s[1]); ++ data->write_connection = wl_connection_create(data->s[1], ++ WL_BUFFER_DEFAULT_MAX_SIZE); + assert(data->write_connection); + } + +@@ -277,6 +279,25 @@ expected_fail_marshal(int expected_error, const char *format, ...) + assert(errno == expected_error); + } + ++static void ++marshal_send(struct marshal_data *data, const char *format, ...) ++{ ++ struct wl_closure *closure; ++ static const uint32_t opcode = 4444; ++ static struct wl_object sender = { NULL, NULL, 1234 }; ++ struct wl_message message = { "test", format, NULL }; ++ va_list ap; ++ ++ va_start(ap, format); ++ closure = wl_closure_vmarshal(&sender, opcode, ap, &message); ++ va_end(ap); ++ ++ assert(closure); ++ assert(wl_closure_send(closure, data->write_connection) == 0); ++ ++ wl_closure_destroy(closure); ++} ++ + static void + expected_fail_marshal_send(struct marshal_data *data, int expected_error, + const char *format, ...) +@@ -644,6 +665,25 @@ TEST(connection_marshal_too_big) + free(big_string); + } + ++TEST(connection_marshal_big_enough) ++{ ++ struct marshal_data data; ++ char *big_string = malloc(5000); ++ ++ assert(big_string); ++ ++ memset(big_string, ' ', 4999); ++ big_string[4999] = '\0'; ++ ++ setup_marshal_data(&data); ++ wl_connection_set_max_buffer_size(data.write_connection, 5120); ++ ++ marshal_send(&data, "s", big_string); ++ ++ release_marshal_data(&data); ++ free(big_string); ++} ++ + static void + marshal_helper(const char *format, void *handler, ...) + { +diff --git a/tests/display-test.c b/tests/display-test.c +index bcb3267..6fc136d 100644 +--- a/tests/display-test.c ++++ b/tests/display-test.c +@@ -1513,10 +1513,7 @@ send_overflow_client(void *data) + /* Do not close the pipe file descriptors afterwards, because the leak + * check verifies that the initial/final FD counts are the same */ + assert(write(pipes[1], &tmp, sizeof(tmp)) == (ssize_t)sizeof(tmp)); +- +- /* Expect an error */ +- fprintf(stderr, "Send loop failed on try %d, err = %d, %s\n", i, err, strerror(err)); +- assert(err == EAGAIN); ++ assert(err == 0); + + client_disconnect_nocheck(c); + } +diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c +index 8d8c3ab..e65a5d6 100644 +--- a/tests/os-wrappers-test.c ++++ b/tests/os-wrappers-test.c +@@ -256,10 +256,12 @@ setup_marshal_data(struct marshal_data *data) + assert(socketpair(AF_UNIX, + SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); + +- data->read_connection = wl_connection_create(data->s[0]); ++ data->read_connection = wl_connection_create(data->s[0], ++ WL_BUFFER_DEFAULT_MAX_SIZE); + assert(data->read_connection); + +- data->write_connection = wl_connection_create(data->s[1]); ++ data->write_connection = wl_connection_create(data->s[1], ++ WL_BUFFER_DEFAULT_MAX_SIZE); + assert(data->write_connection); + } + +-- +2.17.1 + diff --git a/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0202-Set-the-default-max-buffer-size-to-unbounded.patch b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0202-Set-the-default-max-buffer-size-to-unbounded.patch new file mode 100644 index 000000000..2c8ad487d --- /dev/null +++ b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0202-Set-the-default-max-buffer-size-to-unbounded.patch @@ -0,0 +1,45 @@ +From 191eeb6f2ed6429b16db053b45f0fa81df55329d Mon Sep 17 00:00:00 2001 +From: Erik Chen +Date: Sun, 30 Oct 2022 23:31:57 +0000 +Subject: [PATCH 2/5] Set the default max buffer size to unbounded. + +Bug: 1342356 +Change-Id: I6e6c353504d6817b9bf76bc7e8b24001d7957ad6 +Upstream-Status: Pending +--- + src/connection.c | 2 +- + src/wayland-private.h | 5 ++++- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/connection.c b/src/connection.c +index bc6d730..2b3c7e4 100644 +--- a/src/connection.c ++++ b/src/connection.c +@@ -537,7 +537,7 @@ wl_connection_queue(struct wl_connection *connection, + const void *data, size_t count) + { + if (connection->out.head - connection->out.tail + +- count > WL_BUFFER_DEFAULT_MAX_SIZE) { ++ count > WL_BUFFER_FLUSH_SIZE) { + connection->want_flush = 1; + if (wl_connection_flush(connection) < 0 && errno != EAGAIN) + return -1; +diff --git a/src/wayland-private.h b/src/wayland-private.h +index a3a5032..1aafa2e 100644 +--- a/src/wayland-private.h ++++ b/src/wayland-private.h +@@ -48,7 +48,10 @@ + #define WL_MAP_MAX_OBJECTS 0x00f00000 + #define WL_CLOSURE_MAX_ARGS 20 + #define WL_BUFFER_DEFAULT_SIZE_POT 12 +-#define WL_BUFFER_DEFAULT_MAX_SIZE (1 << WL_BUFFER_DEFAULT_SIZE_POT) ++// 0 means unbounded. ++#define WL_BUFFER_DEFAULT_MAX_SIZE 0 ++// The size at which queueing a request will also trigger a flush. ++#define WL_BUFFER_FLUSH_SIZE (1 << WL_BUFFER_DEFAULT_SIZE_POT) + + struct wl_object { + const struct wl_interface *interface; +-- +2.17.1 + diff --git a/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0203-Log-the-object-and-methods-when-marshalling-or-sendi.patch b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0203-Log-the-object-and-methods-when-marshalling-or-sendi.patch new file mode 100644 index 000000000..afd9f4069 --- /dev/null +++ b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0203-Log-the-object-and-methods-when-marshalling-or-sendi.patch @@ -0,0 +1,43 @@ +From 47a912b7a20d689da5a9e1fb848a616822de8b60 Mon Sep 17 00:00:00 2001 +From: Kramer Ge +Date: Wed, 19 Jul 2023 14:46:56 -0400 +Subject: [PATCH 3/5] Log the object and methods when marshalling or sending + fails. + +The log that appears before a display_error will be captured as crash +signature. + +Bug: 1451333 +Change-Id: I06a0a1294c5431d0f8261e522aaa469e2c427725 +Upstream-Status: Pending +--- + src/wayland-client.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/wayland-client.c b/src/wayland-client.c +index 895d7b8..451c035 100644 +--- a/src/wayland-client.c ++++ b/src/wayland-client.c +@@ -848,7 +848,8 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode, + + closure = wl_closure_marshal(&proxy->object, opcode, args, message); + if (closure == NULL) { +- wl_log("Error marshalling request: %s\n", strerror(errno)); ++ wl_log("Error marshalling request for %s.%s: %s\n", ++ proxy->object.interface->name, message->name, strerror(errno)); + display_fatal_error(proxy->display, errno); + goto err_unlock; + } +@@ -857,7 +858,8 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode, + wl_closure_print(closure, &proxy->object, true, false, NULL); + + if (wl_closure_send(closure, proxy->display->connection)) { +- wl_log("Error sending request: %s\n", strerror(errno)); ++ wl_log("Error sending request for %s.%s: %s\n", ++ proxy->object.interface->name, message->name, strerror(errno)); + display_fatal_error(proxy->display, errno); + } + +-- +2.17.1 + diff --git a/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0204-Fix-buffer-resize-crash.patch b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0204-Fix-buffer-resize-crash.patch new file mode 100644 index 000000000..80104ff27 --- /dev/null +++ b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0204-Fix-buffer-resize-crash.patch @@ -0,0 +1,121 @@ +From 3806c948b5e3af1e13383ce3b24b0cebfde0a721 Mon Sep 17 00:00:00 2001 +From: Thomas Lukaszewicz +Date: Fri, 21 Jul 2023 23:28:12 +0000 +Subject: [PATCH 4/5] Fix buffer resize crash + +Currently chromium wayland clients can crash if a connection buffer +(which is initialized at a capacity of 2^12) is asked to resize +exactly at its resize threshold. This threshold is in steps of +powers of 2. + +Take net_size to be the size the connection buffer is required to +support for the current outbound request queue. + +This is crash due to certain parts of the code assuming that +net_size can exactly match the capacity of the connection buffer, +while other parts of the code assume the capacity of the buffer +must exceed the net_size. The latter assumption is the root cause +of the crash. + +Specifically: + 1. ring_buffer_ensure_space() attempts to find the new buffer + `size_bits` required to contain the new `net_size` of the + request buffer [1] + 2. This eventually calls into get_max_size_bits_for_size() + which finds the `size_bits` required for `net_size`[2] + - This code assumes that `net_size <= 2^size_bits` in order + to fit the data + 3. Back in ring_buffer_ensure_space() the `size_bits` returned + is checked to ensure it can contain `net_size` and if a + resize is needed. + - This code assumes that `net_size < 2^size_bits` in order + to fit the data [3] + - If a resize is not needed, the buffer is checked + whether it can hold `net_size` without resizing and a + crash occurs [4] + +The assumptions about buffer capacity differ in 2 and 3, and the +assertion in 3 causes the crash in the associated bug. This only +occurs when `net_size == 2^size_bits` which satisfies the condition +in 2 but fails the condition in 3. + +In Lacros code there were a set of users encountering this crash +when buffers were being asked to resize when clients made the +zwp_text_input_v1_set_surrounding_text() with large blocks of +text (typically from a ssh session). + +This CL enforces the requirement that the connection buffer must +be greater than the net_size. + +For more context see below. +https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/188#note_2010874 + +[1] https://chromium.googlesource.com/external/anongit.freedesktop.org/git/wayland/wayland/+/refs/heads/chromium_1_21_0/src/connection.c#242 + +[2] https://chromium.googlesource.com/external/anongit.freedesktop.org/git/wayland/wayland/+/refs/heads/chromium_1_21_0/src/connection.c#183 + +[3] https://chromium.googlesource.com/external/anongit.freedesktop.org/git/wayland/wayland/+/refs/heads/chromium_1_21_0/src/connection.c#249 + +[4] https://chromium.googlesource.com/external/anongit.freedesktop.org/git/wayland/wayland/+/refs/heads/chromium_1_21_0/src/connection.c#229 + +Bug: 1451333 +Change-Id: I87853e3ff26c1d693f199fd0045fef796c3730c9 +Upstream-Status: Pending +--- + src/connection.c | 2 +- + tests/connection-test.c | 26 ++++++++++++++++++++++++++ + 2 files changed, 27 insertions(+), 1 deletion(-) + +diff --git a/src/connection.c b/src/connection.c +index 2b3c7e4..bea4714 100644 +--- a/src/connection.c ++++ b/src/connection.c +@@ -180,7 +180,7 @@ get_max_size_bits_for_size(size_t buffer_size) + return 0; + + do { +- if (buffer_size <= (((size_t)1) << max_size_bits)) ++ if (buffer_size < (((size_t)1) << max_size_bits)) + break; + } while (max_size_bits++ < (8 * sizeof(size_t) - 1)); + +diff --git a/tests/connection-test.c b/tests/connection-test.c +index 0c76045..7f64443 100644 +--- a/tests/connection-test.c ++++ b/tests/connection-test.c +@@ -684,6 +684,32 @@ TEST(connection_marshal_big_enough) + free(big_string); + } + ++/* Ensures that buffers are resiable to accomodate requests for sizes at the ++ * resize threshold (power of 2). Regression test for crbug.com/1451333. */ ++TEST(connection_marshal_resize_at_buffer_growth_threshold) ++{ ++ /* A string of lenth 8178 requires a buffer size of exactly 2^13. ++ * TODO(tluk): Determine a way to require a resize at 2^13 in a more robust ++ * way */ ++ struct marshal_data data; ++ const int kStrSize = 8178; ++ char *big_string = malloc(kStrSize); ++ assert(big_string); ++ ++ memset(big_string, ' ', kStrSize-1); ++ big_string[kStrSize-1] = '\0'; ++ ++ setup_marshal_data(&data); ++ ++ /* Set the max size to 0 (unbounded). */ ++ wl_connection_set_max_buffer_size(data.write_connection, 0); ++ ++ marshal_send(&data, "s", big_string); ++ ++ release_marshal_data(&data); ++ free(big_string); ++} ++ + static void + marshal_helper(const char *format, void *handler, ...) + { +-- +2.17.1 + diff --git a/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0205-connection-avoid-calling-memcpy-on-NULL-0.patch b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0205-connection-avoid-calling-memcpy-on-NULL-0.patch new file mode 100644 index 000000000..6b4a89c1b --- /dev/null +++ b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0205-connection-avoid-calling-memcpy-on-NULL-0.patch @@ -0,0 +1,53 @@ +From 603a8330853615f84674c0db86f65c1f1c671163 Mon Sep 17 00:00:00 2001 +From: David Benjamin +Date: Wed, 8 Nov 2023 11:51:40 -0500 +Subject: [PATCH 5/5] connection: avoid calling memcpy on NULL, 0 + +This imports +https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/354 from +upstream. + +Bug: 1394755 +Change-Id: If8f495b6aa70871920de9f66a1f1600dce917a10 +Upstream-Status: Pending +--- + src/connection.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/connection.c b/src/connection.c +index bea4714..2233eb4 100644 +--- a/src/connection.c ++++ b/src/connection.c +@@ -87,6 +87,9 @@ ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count) + { + size_t head, size; + ++ if (count == 0) ++ return 0; ++ + head = ring_buffer_mask(b, b->head); + if (head + count <= ring_buffer_space(b)) { + memcpy(b->data + head, data, count); +@@ -154,6 +157,9 @@ ring_buffer_copy(struct wl_ring_buffer *b, void *data, size_t count) + { + size_t tail, size; + ++ if (count == 0) ++ return; ++ + tail = ring_buffer_mask(b, b->tail); + if (tail + count <= ring_buffer_space(b)) { + memcpy(data, b->data + tail, count); +@@ -1333,7 +1339,8 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer, + if (p + div_roundup(size, sizeof *p) > end) + goto overflow; + +- memcpy(p, closure->args[i].a->data, size); ++ if (size != 0) ++ memcpy(p, closure->args[i].a->data, size); + p += div_roundup(size, sizeof *p); + break; + default: +-- +2.17.1 + diff --git a/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland_%.bbappend b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland_%.bbappend new file mode 100644 index 000000000..e032e878e --- /dev/null +++ b/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland_%.bbappend @@ -0,0 +1,13 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + +SRC_URI:append:imxgpu:arm = " \ + file://0101-Revert-client-Do-not-warn-about-attached-proxies-on-.patch \ + file://0102-Revert-client-Abort-when-trying-to-add-an-event-to-a.patch \ + file://0103-Revert-client-Warn-when-a-queue-is-destroyed-with-at.patch \ + file://0104-Revert-client-Track-the-proxies-attached-to-a-queue.patch \ + file://0201-Apply-WIP-CL-from-upstream-wayland.patch \ + file://0202-Set-the-default-max-buffer-size-to-unbounded.patch \ + file://0203-Log-the-object-and-methods-when-marshalling-or-sendi.patch \ + file://0204-Fix-buffer-resize-crash.patch \ + file://0205-connection-avoid-calling-memcpy-on-NULL-0.patch \ +"