コード例 #1
0
static void
do_os_wrappers_dupfd_cloexec(int n)
{
	int base_fd;
	int fd;
	int nr_fds;

	nr_fds = count_open_fds();

	base_fd = socket(PF_LOCAL, SOCK_STREAM, 0);
	assert(base_fd >= 0);

	fd = wl_os_dupfd_cloexec(base_fd, 13);
	assert(fd >= 13);

	close(base_fd);

	/*
	 * Must have 4 calls if falling back, but must also allow
	 * falling back without a forced fallback.
	 */
	assert(wrapped_calls_fcntl > n);

	exec_fd_leak_check(nr_fds);
}
コード例 #2
0
ファイル: connection.c プロジェクト: giucam/wayland
struct wl_closure *
wl_closure_marshal(struct wl_object *sender, uint32_t opcode,
		   union wl_argument *args,
		   const struct wl_message *message)
{
	struct wl_closure *closure;
	struct wl_object *object;
	int i, count, fd, dup_fd;
	const char *signature;
	struct argument_details arg;

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

	closure = malloc(sizeof *closure);
	if (closure == NULL) {
		errno = ENOMEM;
		return NULL;
	}

	memcpy(closure->args, args, count * sizeof *args);

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

		switch (arg.type) {
		case 'f':
		case 'u':
		case 'i':
			break;
		case 's':
			if (!arg.nullable && args[i].s == NULL)
				goto err_null;
			break;
		case 'o':
			if (!arg.nullable && args[i].o == NULL)
				goto err_null;
			break;
		case 'n':
			object = args[i].o;
			if (!arg.nullable && object == NULL)
				goto err_null;

			closure->args[i].n = object ? object->id : 0;
			break;
		case 'a':
			if (!arg.nullable && args[i].a == NULL)
				goto err_null;
			break;
		case 'h':
			fd = args[i].h;
			dup_fd = wl_os_dupfd_cloexec(fd, 0);
			if (dup_fd < 0)
				wl_abort("dup failed: %s\n", strerror(errno));
			closure->args[i].h = dup_fd;
			break;
		default:
			wl_abort("unhandled format code: '%c'\n", arg.type);
			break;
		}
	}

	closure->sender_id = sender->id;
	closure->opcode = opcode;
	closure->message = message;
	closure->count = count;

	return closure;

err_null:
	wl_closure_destroy(closure);
	wl_log("error marshalling arguments for %s (signature %s): "
	       "null value passed for arg %i\n", message->name,
	       message->signature, i);
	errno = EINVAL;
	return NULL;
}
コード例 #3
0
ファイル: connection.c プロジェクト: Godmen/wayland-rpi
struct wl_closure *
wl_closure_vmarshal(struct wl_object *sender,
		    uint32_t opcode, va_list ap,
		    const struct wl_message *message)
{
	struct wl_closure *closure;
	struct wl_object **objectp, *object;
	uint32_t length, aligned, *p, *start, size, *end;
	int dup_fd;
	struct wl_array **arrayp, *array;
	const char **sp, *s;
	const char *signature = message->signature;
	struct argument_details arg;
	char *extra;
	int i, count, fd, extra_size, *fd_ptr;

	/* FIXME: Match old fixed allocation for now */
	closure = malloc(sizeof *closure + 1024);
	if (closure == NULL)
		return NULL;

	extra_size = wl_message_size_extra(message);
	count = arg_count_for_signature(signature) + 2;
	extra = (char *) closure->buffer;
	start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)];
	end = &closure->buffer[256];
	p = &start[2];

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

	for (i = 2; i < count; i++) {
		signature = get_next_argument(signature, &arg);

		switch (arg.type) {
		case 'f':
			closure->types[i] = &ffi_type_sint32;
			closure->args[i] = p;
			if (end - p < 1)
				goto err;
			*p++ = va_arg(ap, wl_fixed_t);
			break;
		case 'u':
			closure->types[i] = &ffi_type_uint32;
			closure->args[i] = p;
			if (end - p < 1)
				goto err;
			*p++ = va_arg(ap, uint32_t);
			break;
		case 'i':
			closure->types[i] = &ffi_type_sint32;
			closure->args[i] = p;
			if (end - p < 1)
				goto err;
			*p++ = va_arg(ap, int32_t);
			break;
		case 's':
			closure->types[i] = &ffi_type_pointer;
			closure->args[i] = extra;
			sp = (const char **) extra;
			extra += sizeof *sp;

			s = va_arg(ap, const char *);

			if (!arg.nullable && s == NULL)
				goto err_null;

			length = s ? strlen(s) + 1: 0;
			aligned = (length + 3) & ~3;
			if (p + aligned / sizeof *p + 1 > end)
				goto err;
			*p++ = length;

			if (length > 0)
				*sp = (const char *) p;
			else
				*sp = NULL;

			memcpy(p, s, length);
			memset((char *) p + length, 0, aligned - length);
			p += aligned / sizeof *p;
			break;
		case 'o':
			closure->types[i] = &ffi_type_pointer;
			closure->args[i] = extra;
			objectp = (struct wl_object **) extra;
			extra += sizeof *objectp;

			object = va_arg(ap, struct wl_object *);

			if (!arg.nullable && object == NULL)
				goto err_null;

			*objectp = object;
			if (end - p < 1)
				goto err;
			*p++ = object ? object->id : 0;
			break;

		case 'n':
			closure->types[i] = &ffi_type_uint32;
			closure->args[i] = p;
			object = va_arg(ap, struct wl_object *);
			if (end - p < 1)
				goto err;

			if (!arg.nullable && object == NULL)
				goto err_null;

			*p++ = object ? object->id : 0;
			break;

		case 'a':
			closure->types[i] = &ffi_type_pointer;
			closure->args[i] = extra;
			arrayp = (struct wl_array **) extra;
			extra += sizeof *arrayp;

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

			array = va_arg(ap, struct wl_array *);

			if (!arg.nullable && array == NULL)
				goto err_null;

			if (array == NULL || array->size == 0) {
				if (end - p < 1)
					goto err;
				*p++ = 0;
				break;
			}
			if (p + DIV_ROUNDUP(array->size, sizeof *p) + 1 > end)
				goto err;
			*p++ = array->size;
			memcpy(p, array->data, array->size);

			(*arrayp)->size = array->size;
			(*arrayp)->alloc = array->alloc;
			(*arrayp)->data = p;

			p += DIV_ROUNDUP(array->size, sizeof *p);
			break;

		case 'h':
			closure->types[i] = &ffi_type_sint;
			closure->args[i] = extra;
			fd_ptr = (int *) extra;
			extra += sizeof *fd_ptr;

			fd = va_arg(ap, int);
			dup_fd = wl_os_dupfd_cloexec(fd, 0);
			if (dup_fd < 0) {
				fprintf(stderr, "dup failed: %m");
				abort();
			}
			*fd_ptr = dup_fd;
			break;
		default:
			fprintf(stderr, "unhandled format code: '%c'\n",
				arg.type);
			assert(0);
			break;
		}
	}

	size = (p - start) * sizeof *p;
	start[0] = sender->id;
	start[1] = opcode | (size << 16);

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

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

	return closure;

err:
	printf("request too big to marshal, maximum size is %zu\n",
	       sizeof closure->buffer);
	errno = ENOMEM;

	return NULL;

err_null:
	free(closure);
	wl_log("error marshalling arguments for %s:%i.%s (signature %s): "
	       "null value passed for arg %i\n",
	       sender->interface->name, sender->id, message->name,
	       message->signature, i);
	errno = EINVAL;
	return NULL;
}