summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchi ding <chi.ding@mobica.com>2013-12-05 13:28:53 (GMT)
committerKristian Høgsberg <krh@bitplanet.net>2014-01-09 22:27:52 (GMT)
commitc102c20f01c84abde71b7f208aae9b232226da1e (patch)
tree479368d714eb983d96d25fcb053a41725928be88
parentcd0dccd01e16fa404e03974d30ded3aebdb1c4bc (diff)
downloadwayland-c102c20f01c84abde71b7f208aae9b232226da1e.tar.gz
wayland-c102c20f01c84abde71b7f208aae9b232226da1e.tar.xz
Fix buffer overflow when serializing a closure object
Here is the JIRA page of this issue https://bugs.tizen.org/jira/browse/TIVI-1889 Change-Id: I773a6d2d8f6fd02ff10c92450db1fa8a69544219 Signed-off-by: Chi Ding <chi.ding@mobica.com> Closes: https://bugs.freedesktop.org/show_bug.cgi?id=65186
-rw-r--r--src/connection.c91
1 files changed, 83 insertions, 8 deletions
diff --git a/src/connection.c b/src/connection.c
index 1d8b61b..d05341a 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -962,6 +962,57 @@ copy_fds_to_connection(struct wl_closure *closure,
return 0;
}
+
+static uint32_t
+buffer_size_for_closure(struct wl_closure *closure)
+{
+ const struct wl_message *message = closure->message;
+ int i, count;
+ struct argument_details arg;
+ const char *signature;
+ uint32_t size, buffer_size = 0;
+
+ signature = message->signature;
+ count = arg_count_for_signature(signature);
+ for (i = 0; i < count; i++) {
+ signature = get_next_argument(signature, &arg);
+
+ switch (arg.type) {
+ case 'h':
+ break;
+ case 'u':
+ case 'i':
+ case 'f':
+ case 'o':
+ case 'n':
+ buffer_size++;
+ break;
+ case 's':
+ if (closure->args[i].s == NULL) {
+ buffer_size++;
+ break;
+ }
+
+ size = strlen(closure->args[i].s) + 1;
+ buffer_size += 1 + DIV_ROUNDUP(size, sizeof(uint32_t));
+ break;
+ case 'a':
+ if (closure->args[i].a == NULL) {
+ buffer_size++;
+ break;
+ }
+
+ size = closure->args[i].a->size;
+ buffer_size += (1 + DIV_ROUNDUP(size, sizeof(uint32_t)));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return buffer_size + 2;
+}
+
static int
serialize_closure(struct wl_closure *closure, uint32_t *buffer,
size_t buffer_count)
@@ -1055,33 +1106,57 @@ overflow:
int
wl_closure_send(struct wl_closure *closure, struct wl_connection *connection)
{
- uint32_t buffer[256];
int size;
+ uint32_t buffer_size;
+ uint32_t *buffer;
+ int result;
if (copy_fds_to_connection(closure, connection))
return -1;
- size = serialize_closure(closure, buffer, 256);
- if (size < 0)
+ buffer_size = buffer_size_for_closure(closure);
+ buffer = malloc(buffer_size * sizeof buffer[0]);
+ if (buffer == NULL)
+ return -1;
+
+ size = serialize_closure(closure, buffer, buffer_size);
+ if (size < 0) {
+ free(buffer);
return -1;
+ }
+
+ result = wl_connection_write(connection, buffer, size);
+ free(buffer);
- return wl_connection_write(connection, buffer, size);
+ return result;
}
int
wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
{
- uint32_t buffer[256];
int size;
+ uint32_t buffer_size;
+ uint32_t *buffer;
+ int result;
if (copy_fds_to_connection(closure, connection))
return -1;
- size = serialize_closure(closure, buffer, 256);
- if (size < 0)
+ buffer_size = buffer_size_for_closure(closure);
+ buffer = malloc(buffer_size * sizeof buffer[0]);
+ if (buffer == NULL)
+ return -1;
+
+ size = serialize_closure(closure, buffer, buffer_size);
+ if (size < 0) {
+ free(buffer);
return -1;
+ }
+
+ result = wl_connection_queue(connection, buffer, size);
+ free(buffer);
- return wl_connection_queue(connection, buffer, size);
+ return result;
}
void