diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-03-17 09:59:38 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 22:27:12 -0400 |
commit | b353a1f7bbd6c015e8563e902f7c78710348e28f (patch) | |
tree | 0a67a8267925c96ff192364fbe4e01c7079cd363 /security | |
parent | 0504c074b546651f19f23a214b76d145d3a0f5af (diff) |
switch keyctl_instantiate_key_common() to iov_iter
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'security')
-rw-r--r-- | security/keys/compat.c | 29 | ||||
-rw-r--r-- | security/keys/internal.h | 5 | ||||
-rw-r--r-- | security/keys/keyctl.c | 78 |
3 files changed, 40 insertions, 72 deletions
diff --git a/security/keys/compat.c b/security/keys/compat.c index 347896548ad3..25430a3aa7f7 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c | |||
@@ -31,30 +31,21 @@ static long compat_keyctl_instantiate_key_iov( | |||
31 | key_serial_t ringid) | 31 | key_serial_t ringid) |
32 | { | 32 | { |
33 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; | 33 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; |
34 | struct iov_iter from; | ||
34 | long ret; | 35 | long ret; |
35 | 36 | ||
36 | if (!_payload_iov || !ioc) | 37 | if (!_payload_iov) |
37 | goto no_payload; | 38 | ioc = 0; |
38 | 39 | ||
39 | ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc, | 40 | ret = compat_import_iovec(WRITE, _payload_iov, ioc, |
40 | ARRAY_SIZE(iovstack), | 41 | ARRAY_SIZE(iovstack), &iov, |
41 | iovstack, &iov); | 42 | &from); |
42 | if (ret < 0) | 43 | if (ret < 0) |
43 | goto err; | 44 | return ret; |
44 | if (ret == 0) | ||
45 | goto no_payload_free; | ||
46 | |||
47 | ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); | ||
48 | err: | ||
49 | if (iov != iovstack) | ||
50 | kfree(iov); | ||
51 | return ret; | ||
52 | 45 | ||
53 | no_payload_free: | 46 | ret = keyctl_instantiate_key_common(id, &from, ringid); |
54 | if (iov != iovstack) | 47 | kfree(iov); |
55 | kfree(iov); | 48 | return ret; |
56 | no_payload: | ||
57 | return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); | ||
58 | } | 49 | } |
59 | 50 | ||
60 | /* | 51 | /* |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 200e37867336..5105c2c2da75 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -243,9 +243,10 @@ extern long keyctl_instantiate_key_iov(key_serial_t, | |||
243 | unsigned, key_serial_t); | 243 | unsigned, key_serial_t); |
244 | extern long keyctl_invalidate_key(key_serial_t); | 244 | extern long keyctl_invalidate_key(key_serial_t); |
245 | 245 | ||
246 | struct iov_iter; | ||
246 | extern long keyctl_instantiate_key_common(key_serial_t, | 247 | extern long keyctl_instantiate_key_common(key_serial_t, |
247 | const struct iovec *, | 248 | struct iov_iter *, |
248 | unsigned, size_t, key_serial_t); | 249 | key_serial_t); |
249 | #ifdef CONFIG_PERSISTENT_KEYRINGS | 250 | #ifdef CONFIG_PERSISTENT_KEYRINGS |
250 | extern long keyctl_get_persistent(uid_t, key_serial_t); | 251 | extern long keyctl_get_persistent(uid_t, key_serial_t); |
251 | extern unsigned persistent_keyring_expiry; | 252 | extern unsigned persistent_keyring_expiry; |
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 | */ | ||
1003 | static 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 | */ |
1024 | long keyctl_instantiate_key_common(key_serial_t id, | 1009 | long 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 | ||
1091 | error2: | 1076 | error2: |
1092 | if (!vm) | 1077 | kvfree(payload); |
1093 | kfree(payload); | ||
1094 | else | ||
1095 | vfree(payload); | ||
1096 | error: | 1078 | error: |
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); | ||
1154 | err: | ||
1155 | if (iov != iovstack) | ||
1156 | kfree(iov); | ||
1157 | return ret; | 1139 | return ret; |
1158 | |||
1159 | no_payload_free: | ||
1160 | if (iov != iovstack) | ||
1161 | kfree(iov); | ||
1162 | no_payload: | ||
1163 | return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); | ||
1164 | } | 1140 | } |
1165 | 1141 | ||
1166 | /* | 1142 | /* |