Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b353a1f7 authored by Al Viro's avatar Al Viro
Browse files

switch keyctl_instantiate_key_common() to iov_iter



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 0504c074
Loading
Loading
Loading
Loading
+10 −19
Original line number Diff line number Diff line
@@ -31,30 +31,21 @@ static long compat_keyctl_instantiate_key_iov(
	key_serial_t ringid)
{
	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
	struct iov_iter from;
	long ret;

	if (!_payload_iov || !ioc)
		goto no_payload;
	if (!_payload_iov)
		ioc = 0;

	ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc,
					   ARRAY_SIZE(iovstack),
					   iovstack, &iov);
	ret = compat_import_iovec(WRITE, _payload_iov, ioc,
				  ARRAY_SIZE(iovstack), &iov,
				  &from);
	if (ret < 0)
		goto err;
	if (ret == 0)
		goto no_payload_free;

	ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
err:
	if (iov != iovstack)
		kfree(iov);
		return ret;

no_payload_free:
	if (iov != iovstack)
	ret = keyctl_instantiate_key_common(id, &from, ringid);
	kfree(iov);
no_payload:
	return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
	return ret;
}

/*
+3 −2
Original line number Diff line number Diff line
@@ -243,9 +243,10 @@ extern long keyctl_instantiate_key_iov(key_serial_t,
				       unsigned, key_serial_t);
extern long keyctl_invalidate_key(key_serial_t);

struct iov_iter;
extern long keyctl_instantiate_key_common(key_serial_t,
					  const struct iovec *,
					  unsigned, size_t, key_serial_t);
					  struct iov_iter *,
					  key_serial_t);
#ifdef CONFIG_PERSISTENT_KEYRINGS
extern long keyctl_get_persistent(uid_t, key_serial_t);
extern unsigned persistent_keyring_expiry;
+27 −51
Original line number Diff line number Diff line
@@ -997,21 +997,6 @@ static int keyctl_change_reqkey_auth(struct key *key)
	return commit_creds(new);
}

/*
 * Copy the iovec data from userspace
 */
static long copy_from_user_iovec(void *buffer, const struct iovec *iov,
				 unsigned ioc)
{
	for (; ioc > 0; ioc--) {
		if (copy_from_user(buffer, iov->iov_base, iov->iov_len) != 0)
			return -EFAULT;
		buffer += iov->iov_len;
		iov++;
	}
	return 0;
}

/*
 * Instantiate a key with the specified payload and link the key into the
 * destination keyring if one is given.
@@ -1022,20 +1007,21 @@ static long copy_from_user_iovec(void *buffer, const struct iovec *iov,
 * If successful, 0 will be returned.
 */
long keyctl_instantiate_key_common(key_serial_t id,
				   const struct iovec *payload_iov,
				   unsigned ioc,
				   size_t plen,
				   struct iov_iter *from,
				   key_serial_t ringid)
{
	const struct cred *cred = current_cred();
	struct request_key_auth *rka;
	struct key *instkey, *dest_keyring;
	size_t plen = from ? iov_iter_count(from) : 0;
	void *payload;
	long ret;
	bool vm = false;

	kenter("%d,,%zu,%d", id, plen, ringid);

	if (!plen)
		from = NULL;

	ret = -EINVAL;
	if (plen > 1024 * 1024 - 1)
		goto error;
@@ -1054,20 +1040,19 @@ long keyctl_instantiate_key_common(key_serial_t id,
	/* pull the payload in if one was supplied */
	payload = NULL;

	if (payload_iov) {
	if (from) {
		ret = -ENOMEM;
		payload = kmalloc(plen, GFP_KERNEL);
		if (!payload) {
			if (plen <= PAGE_SIZE)
				goto error;
			vm = true;
			payload = vmalloc(plen);
			if (!payload)
				goto error;
		}

		ret = copy_from_user_iovec(payload, payload_iov, ioc);
		if (ret < 0)
		ret = -EFAULT;
		if (copy_from_iter(payload, plen, from) != plen)
			goto error2;
	}

@@ -1089,10 +1074,7 @@ long keyctl_instantiate_key_common(key_serial_t id,
		keyctl_change_reqkey_auth(NULL);

error2:
	if (!vm)
		kfree(payload);
	else
		vfree(payload);
	kvfree(payload);
error:
	return ret;
}
@@ -1112,15 +1094,19 @@ long keyctl_instantiate_key(key_serial_t id,
			    key_serial_t ringid)
{
	if (_payload && plen) {
		struct iovec iov[1] = {
			[0].iov_base = (void __user *)_payload,
			[0].iov_len  = plen
		};
		struct iovec iov;
		struct iov_iter from;
		int ret;

		ret = import_single_range(WRITE, (void __user *)_payload, plen,
					  &iov, &from);
		if (unlikely(ret))
			return ret;

		return keyctl_instantiate_key_common(id, iov, 1, plen, ringid);
		return keyctl_instantiate_key_common(id, &from, ringid);
	}

	return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
	return keyctl_instantiate_key_common(id, NULL, ringid);
}

/*
@@ -1138,29 +1124,19 @@ long keyctl_instantiate_key_iov(key_serial_t id,
				key_serial_t ringid)
{
	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
	struct iov_iter from;
	long ret;

	if (!_payload_iov || !ioc)
		goto no_payload;
	if (!_payload_iov)
		ioc = 0;

	ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
				    ARRAY_SIZE(iovstack), iovstack, &iov);
	ret = import_iovec(WRITE, _payload_iov, ioc,
				    ARRAY_SIZE(iovstack), &iov, &from);
	if (ret < 0)
		goto err;
	if (ret == 0)
		goto no_payload_free;

	ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
err:
	if (iov != iovstack)
		kfree(iov);
		return ret;

no_payload_free:
	if (iov != iovstack)
	ret = keyctl_instantiate_key_common(id, &from, ringid);
	kfree(iov);
no_payload:
	return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
	return ret;
}

/*