Exemplo n.º 1
0
static void
close_fds(struct wl_buffer *buffer)
{
	int fds[MAX_FDS_OUT], i, count;
	size_t size;

	size = buffer->head - buffer->tail;
	if (size == 0)
		return;

	wl_buffer_copy(buffer, fds, size);
	count = size / sizeof fds[0];
	for (i = 0; i < count; i++)
		close(fds[i]);
	buffer->tail += size;
}
Exemplo n.º 2
0
static void
close_fds(struct wl_buffer *buffer, int max)
{
	int32_t fds[sizeof(buffer->data) / sizeof(int32_t)], i, count;
	size_t size;

	size = buffer->head - buffer->tail;
	if (size == 0)
		return;

	wl_buffer_copy(buffer, fds, size);
	count = size / sizeof fds[0];
	if (max > 0 && max < count)
		count = max;
	for (i = 0; i < count; i++)
		close(fds[i]);
	buffer->tail += size;
}
Exemplo n.º 3
0
static void
build_cmsg(struct wl_buffer *buffer, char *data, int *clen)
{
	struct cmsghdr *cmsg;
	size_t size;

	size = buffer->head - buffer->tail;
	if (size > 0) {
		cmsg = (struct cmsghdr *) data;
		cmsg->cmsg_level = SOL_SOCKET;
		cmsg->cmsg_type = SCM_RIGHTS;
		cmsg->cmsg_len = CMSG_LEN(size);
		wl_buffer_copy(buffer, CMSG_DATA(cmsg), size);
		*clen = cmsg->cmsg_len;
	} else {
		*clen = 0;
	}
}
Exemplo n.º 4
0
struct wl_closure *
wl_connection_demarshal(struct wl_connection *connection,
			uint32_t size,
			struct wl_map *objects,
			const struct wl_message *message)
{
	uint32_t *p, *next, *end, length, id;
	int fd;
	char *s;
	unsigned int i, count, num_arrays;
	const char *signature;
	struct argument_details arg;
	struct wl_closure *closure;
	struct wl_array *array, *array_extra;

	count = arg_count_for_signature(message->signature);
	if (count > WL_CLOSURE_MAX_ARGS) {
		wl_log("too many args (%d)\n", count);
		errno = EINVAL;
		wl_connection_consume(connection, size);
		return NULL;
	}

	num_arrays = wl_message_count_arrays(message);
	closure = malloc(sizeof *closure + size + num_arrays * sizeof *array);
	if (closure == NULL) {
		errno = ENOMEM;
		wl_connection_consume(connection, size);
		return NULL;
	}

	array_extra = closure->extra;
	p = (uint32_t *)(closure->extra + num_arrays);
	end = p + size / sizeof *p;

	wl_connection_copy(connection, p, size);
	closure->sender_id = *p++;
	closure->opcode = *p++ & 0x0000ffff;

	signature = message->signature;
	for (i = 0; i < count; i++) {
		signature = get_next_argument(signature, &arg);

		if (arg.type != 'h' && p + 1 > end) {
			wl_log("message too short, "
			       "object (%d), message %s(%s)\n",
			       *p, message->name, message->signature);
			errno = EINVAL;
			goto err;
		}

		switch (arg.type) {
		case 'u':
			closure->args[i].u = *p++;
			break;
		case 'i':
			closure->args[i].i = *p++;
			break;
		case 'f':
			closure->args[i].f = *p++;
			break;
		case 's':
			length = *p++;

			if (length == 0) {
				closure->args[i].s = NULL;
				break;
			}

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				wl_log("message too short, "
				       "object (%d), message %s(%s)\n",
				       closure->sender_id, message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}

			s = (char *) p;

			if (length > 0 && s[length - 1] != '\0') {
				wl_log("string not nul-terminated, "
				       "message %s(%s)\n",
				       message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			closure->args[i].s = s;
			p = next;
			break;
		case 'o':
			id = *p++;
			closure->args[i].n = id;

			if (id == 0 && !arg.nullable) {
				wl_log("NULL object received on non-nullable "
				       "type, message %s(%s)\n", message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}
			break;
		case 'n':
			id = *p++;
			closure->args[i].n = id;

			if (id == 0 && !arg.nullable) {
				wl_log("NULL new ID received on non-nullable "
				       "type, message %s(%s)\n", message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}

			if (wl_map_reserve_new(objects, id) < 0) {
				wl_log("not a valid new object id (%u), "
				       "message %s(%s)\n",
				       id, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			break;
		case 'a':
			length = *p++;

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				wl_log("message too short, "
				       "object (%d), message %s(%s)\n",
				       closure->sender_id, message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}

			array_extra->size = length;
			array_extra->alloc = 0;
			array_extra->data = p;

			closure->args[i].a = array_extra++;
			p = next;
			break;
		case 'h':
			if (connection->fds_in.tail == connection->fds_in.head) {
				wl_log("file descriptor expected, "
				       "object (%d), message %s(%s)\n",
				       closure->sender_id, message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}

			wl_buffer_copy(&connection->fds_in, &fd, sizeof fd);
			connection->fds_in.tail += sizeof fd;
			closure->args[i].h = fd;
			break;
		default:
			wl_abort("unknown type\n");
			break;
		}
	}

	closure->count = count;
	closure->message = message;

	wl_connection_consume(connection, size);

	return closure;

 err:
	wl_closure_destroy(closure);
	wl_connection_consume(connection, size);

	return NULL;
}
Exemplo n.º 5
0
void
wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
{
	wl_buffer_copy(&connection->in, data, size);
}
Exemplo n.º 6
0
struct wl_closure *
wl_connection_demarshal(struct wl_connection *connection,
			uint32_t size,
			struct wl_map *objects,
			const struct wl_message *message)
{
	uint32_t *p, *next, *end, length, **id;
	int *fd;
	char *extra, **s;
	unsigned int i, count, extra_space;
	const char *signature = message->signature;
	struct argument_details arg;
	struct wl_object **object;
	struct wl_array **array;
	struct wl_closure *closure;

	count = arg_count_for_signature(signature) + 2;
	if (count > ARRAY_LENGTH(closure->types)) {
		printf("too many args (%d)\n", count);
		errno = EINVAL;
		wl_connection_consume(connection, size);
		return NULL;
	}

	extra_space = wl_message_size_extra(message);
	closure = malloc(sizeof *closure + 8 + size + extra_space);
	if (closure == NULL)
		return NULL;

	closure->message = message;
	closure->types[0] = &ffi_type_pointer;
	closure->types[1] = &ffi_type_pointer;
	closure->start = closure->buffer;

	wl_connection_copy(connection, closure->buffer, size);
	p = &closure->buffer[2];
	end = (uint32_t *) ((char *) p + size);
	extra = (char *) end;
	for (i = 2; i < count; i++) {
		signature = get_next_argument(signature, &arg);

		if (p + 1 > end) {
			printf("message too short, "
			       "object (%d), message %s(%s)\n",
			       *p, message->name, message->signature);
			errno = EINVAL;
			goto err;
		}

		switch (arg.type) {
		case 'u':
			closure->types[i] = &ffi_type_uint32;
			closure->args[i] = p++;
			break;
		case 'i':
			closure->types[i] = &ffi_type_sint32;
			closure->args[i] = p++;
			break;
		case 'f':
			closure->types[i] = &ffi_type_sint32;
			closure->args[i] = p++;
			break;
		case 's':
			closure->types[i] = &ffi_type_pointer;
			length = *p++;

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				printf("message too short, "
				       "object (%d), message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			s = (char **) extra;
			extra += sizeof *s;
			closure->args[i] = s;

			if (length == 0) {
				*s = NULL;
			} else {
				*s = (char *) p;
			}

			if (length > 0 && (*s)[length - 1] != '\0') {
				printf("string not nul-terminated, "
				       "message %s(%s)\n",
				       message->name, message->signature);
				errno = EINVAL;
				goto err;
			}
			p = next;
			break;
		case 'o':
			closure->types[i] = &ffi_type_pointer;
			object = (struct wl_object **) extra;
			extra += sizeof *object;
			closure->args[i] = object;

			if (*p == 0 && !arg.nullable) {
				printf("NULL new ID received on non-nullable "
				       "type, message %s(%s)\n", message->name,
				       message->signature);
				*object = NULL;
				errno = EINVAL;
				goto err;
			}

			*object = wl_map_lookup(objects, *p);
			if (*object == WL_ZOMBIE_OBJECT) {
				/* references object we've already
				 * destroyed client side */
				*object = NULL;
			} else if (*object == NULL && *p != 0) {
				printf("unknown object (%u), message %s(%s)\n",
				       *p, message->name, message->signature);
				*object = NULL;
				errno = EINVAL;
				goto err;
			}

			if (*object != NULL && message->types[i-2] != NULL &&
			    (*object)->interface != message->types[i-2]) {
				printf("invalid object (%u), type (%s), "
					"message %s(%s)\n",
				       *p, (*object)->interface->name,
				       message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			p++;
			break;
		case 'n':
			closure->types[i] = &ffi_type_pointer;
			id = (uint32_t **) extra;
			extra += sizeof *id;
			closure->args[i] = id;
			*id = p;

			if (*id == 0 && !arg.nullable) {
				printf("NULL new ID received on non-nullable "
				       "type, message %s(%s)\n", message->name,
				       message->signature);
				errno = EINVAL;
				goto err;
			}

			if (wl_map_reserve_new(objects, *p) < 0) {
				printf("not a valid new object id (%d), "
				       "message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			p++;
			break;
		case 'a':
			closure->types[i] = &ffi_type_pointer;
			length = *p++;

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				printf("message too short, "
				       "object (%d), message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			array = (struct wl_array **) extra;
			extra += sizeof *array;
			closure->args[i] = array;

			*array = (struct wl_array *) extra;
			extra += sizeof **array;

			(*array)->size = length;
			(*array)->alloc = 0;
			(*array)->data = p;
			p = next;
			break;
		case 'h':
			closure->types[i] = &ffi_type_sint;

			fd = (int *) extra;
			extra += sizeof *fd;
			closure->args[i] = fd;

			wl_buffer_copy(&connection->fds_in, fd, sizeof *fd);
			connection->fds_in.tail += sizeof *fd;
			break;
		default:
			printf("unknown type\n");
			assert(0);
			break;
		}
	}

	closure->count = i;

	ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
		     closure->count, &ffi_type_void, closure->types);

	wl_connection_consume(connection, size);

	return closure;

 err:
	closure->count = i;
	wl_closure_destroy(closure);
	wl_connection_consume(connection, size);

	return NULL;
}
Exemplo n.º 7
0
struct wl_closure *
wl_connection_demarshal(struct wl_connection *connection,
			uint32_t size,
			struct wl_hash_table *objects,
			const struct wl_message *message)
{
	uint32_t *p, *next, *end, length;
	int *fd;
	char *extra, **s;
	int i, count, extra_space;
	struct wl_object **object;
	struct wl_array **array;
	struct wl_closure *closure = &connection->receive_closure;

	count = strlen(message->signature) + 2;
	if (count > ARRAY_LENGTH(closure->types)) {
		printf("too many args (%d)\n", count);
		assert(0);
	}

	extra_space = wl_message_size_extra(message);
	if (sizeof closure->buffer < size + extra_space) {
		printf("request too big, should malloc tmp buffer here\n");
		assert(0);
	}

	closure->message = message;
	closure->types[0] = &ffi_type_pointer;
	closure->types[1] = &ffi_type_pointer;

	wl_connection_copy(connection, closure->buffer, size);
	p = &closure->buffer[2];
	end = (uint32_t *) ((char *) (p + size));
	extra = (char *) end;
	for (i = 2; i < count; i++) {
		if (p + 1 > end) {
			printf("message too short, "
			       "object (%d), message %s(%s)\n",
			       *p, message->name, message->signature);
			errno = EINVAL;
			goto err;
		}

		switch (message->signature[i - 2]) {
		case 'u':
			closure->types[i] = &ffi_type_uint32;
			closure->args[i] = p++;
			break;
		case 'i':
			closure->types[i] = &ffi_type_sint32;
			closure->args[i] = p++;
			break;
		case 's':
			closure->types[i] = &ffi_type_pointer;
			length = *p++;

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				printf("message too short, "
				       "object (%d), message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			s = (char **) extra;
			extra += sizeof *s;
			closure->args[i] = s;

			if (length == 0) {
				*s = NULL;
			} else {
				*s = (char *) p;
			}

			if (length > 0 && (*s)[length - 1] != '\0') {
				printf("string not nul-terminated, "
				       "message %s(%s)\n",
				       message->name, message->signature);
				errno = EINVAL;
				goto err;
			}
			p = next;
			break;
		case 'o':
			closure->types[i] = &ffi_type_pointer;
			object = (struct wl_object **) extra;
			extra += sizeof *object;
			closure->args[i] = object;

			*object = wl_hash_table_lookup(objects, *p);
			if (*object == NULL && *p != 0) {
				printf("unknown object (%d), message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			p++;
			break;
		case 'n':
			closure->types[i] = &ffi_type_uint32;
			closure->args[i] = p;
			object = wl_hash_table_lookup(objects, *p);
			if (object != NULL) {
				printf("not a new object (%d), "
				       "message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}
			p++;
			break;
		case 'a':
			closure->types[i] = &ffi_type_pointer;
			length = *p++;

			next = p + DIV_ROUNDUP(length, sizeof *p);
			if (next > end) {
				printf("message too short, "
				       "object (%d), message %s(%s)\n",
				       *p, message->name, message->signature);
				errno = EINVAL;
				goto err;
			}

			array = (struct wl_array **) extra;
			extra += sizeof *array;
			closure->args[i] = array;

			*array = (struct wl_array *) extra;
			extra += sizeof **array;

			(*array)->size = length;
			(*array)->alloc = 0;
			(*array)->data = p;
			p = next;
			break;
		case 'h':
			closure->types[i] = &ffi_type_sint;

			fd = (int *) extra;
			extra += sizeof *fd;
			closure->args[i] = fd;

			wl_buffer_copy(&connection->fds_in, fd, sizeof *fd);
			connection->fds_in.tail += sizeof *fd;
			break;
		default:
			printf("unknown type\n");
			assert(0);
			break;
		}
	}

	closure->count = i;
	ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
		     closure->count, &ffi_type_uint32, closure->types);

	wl_connection_consume(connection, size);

	return closure;

 err:
	closure->count = i;
	wl_closure_destroy(closure);

	return NULL;
}