switch keyctl_instantiate_key_common() to iov_iter
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Родитель
0504c074b5
Коммит
b353a1f7bb
|
@ -31,30 +31,21 @@ static long compat_keyctl_instantiate_key_iov(
|
||||||
key_serial_t ringid)
|
key_serial_t ringid)
|
||||||
{
|
{
|
||||||
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
|
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
|
||||||
|
struct iov_iter from;
|
||||||
long ret;
|
long ret;
|
||||||
|
|
||||||
if (!_payload_iov || !ioc)
|
if (!_payload_iov)
|
||||||
goto no_payload;
|
ioc = 0;
|
||||||
|
|
||||||
ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc,
|
ret = compat_import_iovec(WRITE, _payload_iov, ioc,
|
||||||
ARRAY_SIZE(iovstack),
|
ARRAY_SIZE(iovstack), &iov,
|
||||||
iovstack, &iov);
|
&from);
|
||||||
if (ret < 0)
|
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;
|
return ret;
|
||||||
|
|
||||||
no_payload_free:
|
ret = keyctl_instantiate_key_common(id, &from, ringid);
|
||||||
if (iov != iovstack)
|
|
||||||
kfree(iov);
|
kfree(iov);
|
||||||
no_payload:
|
return ret;
|
||||||
return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -243,9 +243,10 @@ extern long keyctl_instantiate_key_iov(key_serial_t,
|
||||||
unsigned, key_serial_t);
|
unsigned, key_serial_t);
|
||||||
extern long keyctl_invalidate_key(key_serial_t);
|
extern long keyctl_invalidate_key(key_serial_t);
|
||||||
|
|
||||||
|
struct iov_iter;
|
||||||
extern long keyctl_instantiate_key_common(key_serial_t,
|
extern long keyctl_instantiate_key_common(key_serial_t,
|
||||||
const struct iovec *,
|
struct iov_iter *,
|
||||||
unsigned, size_t, key_serial_t);
|
key_serial_t);
|
||||||
#ifdef CONFIG_PERSISTENT_KEYRINGS
|
#ifdef CONFIG_PERSISTENT_KEYRINGS
|
||||||
extern long keyctl_get_persistent(uid_t, key_serial_t);
|
extern long keyctl_get_persistent(uid_t, key_serial_t);
|
||||||
extern unsigned persistent_keyring_expiry;
|
extern unsigned persistent_keyring_expiry;
|
||||||
|
|
|
@ -997,21 +997,6 @@ static int keyctl_change_reqkey_auth(struct key *key)
|
||||||
return commit_creds(new);
|
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
|
* Instantiate a key with the specified payload and link the key into the
|
||||||
* destination keyring if one is given.
|
* 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.
|
* If successful, 0 will be returned.
|
||||||
*/
|
*/
|
||||||
long keyctl_instantiate_key_common(key_serial_t id,
|
long keyctl_instantiate_key_common(key_serial_t id,
|
||||||
const struct iovec *payload_iov,
|
struct iov_iter *from,
|
||||||
unsigned ioc,
|
|
||||||
size_t plen,
|
|
||||||
key_serial_t ringid)
|
key_serial_t ringid)
|
||||||
{
|
{
|
||||||
const struct cred *cred = current_cred();
|
const struct cred *cred = current_cred();
|
||||||
struct request_key_auth *rka;
|
struct request_key_auth *rka;
|
||||||
struct key *instkey, *dest_keyring;
|
struct key *instkey, *dest_keyring;
|
||||||
|
size_t plen = from ? iov_iter_count(from) : 0;
|
||||||
void *payload;
|
void *payload;
|
||||||
long ret;
|
long ret;
|
||||||
bool vm = false;
|
|
||||||
|
|
||||||
kenter("%d,,%zu,%d", id, plen, ringid);
|
kenter("%d,,%zu,%d", id, plen, ringid);
|
||||||
|
|
||||||
|
if (!plen)
|
||||||
|
from = NULL;
|
||||||
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (plen > 1024 * 1024 - 1)
|
if (plen > 1024 * 1024 - 1)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1054,20 +1040,19 @@ long keyctl_instantiate_key_common(key_serial_t id,
|
||||||
/* pull the payload in if one was supplied */
|
/* pull the payload in if one was supplied */
|
||||||
payload = NULL;
|
payload = NULL;
|
||||||
|
|
||||||
if (payload_iov) {
|
if (from) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
payload = kmalloc(plen, GFP_KERNEL);
|
payload = kmalloc(plen, GFP_KERNEL);
|
||||||
if (!payload) {
|
if (!payload) {
|
||||||
if (plen <= PAGE_SIZE)
|
if (plen <= PAGE_SIZE)
|
||||||
goto error;
|
goto error;
|
||||||
vm = true;
|
|
||||||
payload = vmalloc(plen);
|
payload = vmalloc(plen);
|
||||||
if (!payload)
|
if (!payload)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = copy_from_user_iovec(payload, payload_iov, ioc);
|
ret = -EFAULT;
|
||||||
if (ret < 0)
|
if (copy_from_iter(payload, plen, from) != plen)
|
||||||
goto error2;
|
goto error2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1089,10 +1074,7 @@ long keyctl_instantiate_key_common(key_serial_t id,
|
||||||
keyctl_change_reqkey_auth(NULL);
|
keyctl_change_reqkey_auth(NULL);
|
||||||
|
|
||||||
error2:
|
error2:
|
||||||
if (!vm)
|
kvfree(payload);
|
||||||
kfree(payload);
|
|
||||||
else
|
|
||||||
vfree(payload);
|
|
||||||
error:
|
error:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1112,15 +1094,19 @@ long keyctl_instantiate_key(key_serial_t id,
|
||||||
key_serial_t ringid)
|
key_serial_t ringid)
|
||||||
{
|
{
|
||||||
if (_payload && plen) {
|
if (_payload && plen) {
|
||||||
struct iovec iov[1] = {
|
struct iovec iov;
|
||||||
[0].iov_base = (void __user *)_payload,
|
struct iov_iter from;
|
||||||
[0].iov_len = plen
|
int ret;
|
||||||
};
|
|
||||||
|
|
||||||
return keyctl_instantiate_key_common(id, iov, 1, plen, ringid);
|
ret = import_single_range(WRITE, (void __user *)_payload, plen,
|
||||||
|
&iov, &from);
|
||||||
|
if (unlikely(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
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)
|
key_serial_t ringid)
|
||||||
{
|
{
|
||||||
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
|
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
|
||||||
|
struct iov_iter from;
|
||||||
long ret;
|
long ret;
|
||||||
|
|
||||||
if (!_payload_iov || !ioc)
|
if (!_payload_iov)
|
||||||
goto no_payload;
|
ioc = 0;
|
||||||
|
|
||||||
ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
|
ret = import_iovec(WRITE, _payload_iov, ioc,
|
||||||
ARRAY_SIZE(iovstack), iovstack, &iov);
|
ARRAY_SIZE(iovstack), &iov, &from);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err;
|
return ret;
|
||||||
if (ret == 0)
|
ret = keyctl_instantiate_key_common(id, &from, ringid);
|
||||||
goto no_payload_free;
|
|
||||||
|
|
||||||
ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
|
|
||||||
err:
|
|
||||||
if (iov != iovstack)
|
|
||||||
kfree(iov);
|
kfree(iov);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
no_payload_free:
|
|
||||||
if (iov != iovstack)
|
|
||||||
kfree(iov);
|
|
||||||
no_payload:
|
|
||||||
return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче