Loading security/keys/compat.c +10 −19 Original line number Original line Diff line number Diff line Loading @@ -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); } } /* /* Loading security/keys/internal.h +3 −2 Original line number Original line Diff line number Diff line Loading @@ -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; Loading security/keys/keyctl.c +27 −51 Original line number Original line Diff line number Diff line Loading @@ -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. Loading @@ -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; Loading @@ -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; } } Loading @@ -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; } } Loading @@ -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; }; 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); } } /* /* Loading @@ -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; 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; ret = keyctl_instantiate_key_common(id, &from, ringid); no_payload_free: if (iov != iovstack) kfree(iov); kfree(iov); no_payload: return ret; return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); } } /* /* Loading Loading
security/keys/compat.c +10 −19 Original line number Original line Diff line number Diff line Loading @@ -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); } } /* /* Loading
security/keys/internal.h +3 −2 Original line number Original line Diff line number Diff line Loading @@ -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; Loading
security/keys/keyctl.c +27 −51 Original line number Original line Diff line number Diff line Loading @@ -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. Loading @@ -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; Loading @@ -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; } } Loading @@ -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; } } Loading @@ -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; }; 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); } } /* /* Loading @@ -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; 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; ret = keyctl_instantiate_key_common(id, &from, ringid); no_payload_free: if (iov != iovstack) kfree(iov); kfree(iov); no_payload: return ret; return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); } } /* /* Loading