aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/keyctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r--security/keys/keyctl.c78
1 files changed, 27 insertions, 51 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 4743d71e4aa6..0b9ec78a7a7a 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -998,21 +998,6 @@ static int keyctl_change_reqkey_auth(struct key *key)
998} 998}
999 999
1000/* 1000/*
1001 * Copy the iovec data from userspace
1002 */
1003static long copy_from_user_iovec(void *buffer, const struct iovec *iov,
1004 unsigned ioc)
1005{
1006 for (; ioc > 0; ioc--) {
1007 if (copy_from_user(buffer, iov->iov_base, iov->iov_len) != 0)
1008 return -EFAULT;
1009 buffer += iov->iov_len;
1010 iov++;
1011 }
1012 return 0;
1013}
1014
1015/*
1016 * Instantiate a key with the specified payload and link the key into the 1001 * Instantiate a key with the specified payload and link the key into the
1017 * destination keyring if one is given. 1002 * destination keyring if one is given.
1018 * 1003 *
@@ -1022,20 +1007,21 @@ static long copy_from_user_iovec(void *buffer, const struct iovec *iov,
1022 * If successful, 0 will be returned. 1007 * If successful, 0 will be returned.
1023 */ 1008 */
1024long keyctl_instantiate_key_common(key_serial_t id, 1009long keyctl_instantiate_key_common(key_serial_t id,
1025 const struct iovec *payload_iov, 1010 struct iov_iter *from,
1026 unsigned ioc,
1027 size_t plen,
1028 key_serial_t ringid) 1011 key_serial_t ringid)
1029{ 1012{
1030 const struct cred *cred = current_cred(); 1013 const struct cred *cred = current_cred();
1031 struct request_key_auth *rka; 1014 struct request_key_auth *rka;
1032 struct key *instkey, *dest_keyring; 1015 struct key *instkey, *dest_keyring;
1016 size_t plen = from ? iov_iter_count(from) : 0;
1033 void *payload; 1017 void *payload;
1034 long ret; 1018 long ret;
1035 bool vm = false;
1036 1019
1037 kenter("%d,,%zu,%d", id, plen, ringid); 1020 kenter("%d,,%zu,%d", id, plen, ringid);
1038 1021
1022 if (!plen)
1023 from = NULL;
1024
1039 ret = -EINVAL; 1025 ret = -EINVAL;
1040 if (plen > 1024 * 1024 - 1) 1026 if (plen > 1024 * 1024 - 1)
1041 goto error; 1027 goto error;
@@ -1054,20 +1040,19 @@ long keyctl_instantiate_key_common(key_serial_t id,
1054 /* pull the payload in if one was supplied */ 1040 /* pull the payload in if one was supplied */
1055 payload = NULL; 1041 payload = NULL;
1056 1042
1057 if (payload_iov) { 1043 if (from) {
1058 ret = -ENOMEM; 1044 ret = -ENOMEM;
1059 payload = kmalloc(plen, GFP_KERNEL); 1045 payload = kmalloc(plen, GFP_KERNEL);
1060 if (!payload) { 1046 if (!payload) {
1061 if (plen <= PAGE_SIZE) 1047 if (plen <= PAGE_SIZE)
1062 goto error; 1048 goto error;
1063 vm = true;
1064 payload = vmalloc(plen); 1049 payload = vmalloc(plen);
1065 if (!payload) 1050 if (!payload)
1066 goto error; 1051 goto error;
1067 } 1052 }
1068 1053
1069 ret = copy_from_user_iovec(payload, payload_iov, ioc); 1054 ret = -EFAULT;
1070 if (ret < 0) 1055 if (copy_from_iter(payload, plen, from) != plen)
1071 goto error2; 1056 goto error2;
1072 } 1057 }
1073 1058
@@ -1089,10 +1074,7 @@ long keyctl_instantiate_key_common(key_serial_t id,
1089 keyctl_change_reqkey_auth(NULL); 1074 keyctl_change_reqkey_auth(NULL);
1090 1075
1091error2: 1076error2:
1092 if (!vm) 1077 kvfree(payload);
1093 kfree(payload);
1094 else
1095 vfree(payload);
1096error: 1078error:
1097 return ret; 1079 return ret;
1098} 1080}
@@ -1112,15 +1094,19 @@ long keyctl_instantiate_key(key_serial_t id,
1112 key_serial_t ringid) 1094 key_serial_t ringid)
1113{ 1095{
1114 if (_payload && plen) { 1096 if (_payload && plen) {
1115 struct iovec iov[1] = { 1097 struct iovec iov;
1116 [0].iov_base = (void __user *)_payload, 1098 struct iov_iter from;
1117 [0].iov_len = plen 1099 int ret;
1118 };
1119 1100
1120 return keyctl_instantiate_key_common(id, iov, 1, plen, ringid); 1101 ret = import_single_range(WRITE, (void __user *)_payload, plen,
1102 &iov, &from);
1103 if (unlikely(ret))
1104 return ret;
1105
1106 return keyctl_instantiate_key_common(id, &from, ringid);
1121 } 1107 }
1122 1108
1123 return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); 1109 return keyctl_instantiate_key_common(id, NULL, ringid);
1124} 1110}
1125 1111
1126/* 1112/*
@@ -1138,29 +1124,19 @@ long keyctl_instantiate_key_iov(key_serial_t id,
1138 key_serial_t ringid) 1124 key_serial_t ringid)
1139{ 1125{
1140 struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 1126 struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1127 struct iov_iter from;
1141 long ret; 1128 long ret;
1142 1129
1143 if (!_payload_iov || !ioc) 1130 if (!_payload_iov)
1144 goto no_payload; 1131 ioc = 0;
1145 1132
1146 ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, 1133 ret = import_iovec(WRITE, _payload_iov, ioc,
1147 ARRAY_SIZE(iovstack), iovstack, &iov); 1134 ARRAY_SIZE(iovstack), &iov, &from);
1148 if (ret < 0) 1135 if (ret < 0)
1149 goto err; 1136 return ret;
1150 if (ret == 0) 1137 ret = keyctl_instantiate_key_common(id, &from, ringid);
1151 goto no_payload_free; 1138 kfree(iov);
1152
1153 ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
1154err:
1155 if (iov != iovstack)
1156 kfree(iov);
1157 return ret; 1139 return ret;
1158
1159no_payload_free:
1160 if (iov != iovstack)
1161 kfree(iov);
1162no_payload:
1163 return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
1164} 1140}
1165 1141
1166/* 1142/*