diff options
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r-- | security/keys/keyctl.c | 143 |
1 files changed, 134 insertions, 9 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 31a0fd8189f1..427fddcaeb19 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -913,6 +913,21 @@ static int keyctl_change_reqkey_auth(struct key *key) | |||
913 | } | 913 | } |
914 | 914 | ||
915 | /* | 915 | /* |
916 | * Copy the iovec data from userspace | ||
917 | */ | ||
918 | static long copy_from_user_iovec(void *buffer, const struct iovec *iov, | ||
919 | unsigned ioc) | ||
920 | { | ||
921 | for (; ioc > 0; ioc--) { | ||
922 | if (copy_from_user(buffer, iov->iov_base, iov->iov_len) != 0) | ||
923 | return -EFAULT; | ||
924 | buffer += iov->iov_len; | ||
925 | iov++; | ||
926 | } | ||
927 | return 0; | ||
928 | } | ||
929 | |||
930 | /* | ||
916 | * Instantiate a key with the specified payload and link the key into the | 931 | * Instantiate a key with the specified payload and link the key into the |
917 | * destination keyring if one is given. | 932 | * destination keyring if one is given. |
918 | * | 933 | * |
@@ -921,10 +936,11 @@ static int keyctl_change_reqkey_auth(struct key *key) | |||
921 | * | 936 | * |
922 | * If successful, 0 will be returned. | 937 | * If successful, 0 will be returned. |
923 | */ | 938 | */ |
924 | long keyctl_instantiate_key(key_serial_t id, | 939 | long keyctl_instantiate_key_common(key_serial_t id, |
925 | const void __user *_payload, | 940 | const struct iovec *payload_iov, |
926 | size_t plen, | 941 | unsigned ioc, |
927 | key_serial_t ringid) | 942 | size_t plen, |
943 | key_serial_t ringid) | ||
928 | { | 944 | { |
929 | const struct cred *cred = current_cred(); | 945 | const struct cred *cred = current_cred(); |
930 | struct request_key_auth *rka; | 946 | struct request_key_auth *rka; |
@@ -953,7 +969,7 @@ long keyctl_instantiate_key(key_serial_t id, | |||
953 | /* pull the payload in if one was supplied */ | 969 | /* pull the payload in if one was supplied */ |
954 | payload = NULL; | 970 | payload = NULL; |
955 | 971 | ||
956 | if (_payload) { | 972 | if (payload_iov) { |
957 | ret = -ENOMEM; | 973 | ret = -ENOMEM; |
958 | payload = kmalloc(plen, GFP_KERNEL); | 974 | payload = kmalloc(plen, GFP_KERNEL); |
959 | if (!payload) { | 975 | if (!payload) { |
@@ -965,8 +981,8 @@ long keyctl_instantiate_key(key_serial_t id, | |||
965 | goto error; | 981 | goto error; |
966 | } | 982 | } |
967 | 983 | ||
968 | ret = -EFAULT; | 984 | ret = copy_from_user_iovec(payload, payload_iov, ioc); |
969 | if (copy_from_user(payload, _payload, plen) != 0) | 985 | if (ret < 0) |
970 | goto error2; | 986 | goto error2; |
971 | } | 987 | } |
972 | 988 | ||
@@ -997,6 +1013,72 @@ error: | |||
997 | } | 1013 | } |
998 | 1014 | ||
999 | /* | 1015 | /* |
1016 | * Instantiate a key with the specified payload and link the key into the | ||
1017 | * destination keyring if one is given. | ||
1018 | * | ||
1019 | * The caller must have the appropriate instantiation permit set for this to | ||
1020 | * work (see keyctl_assume_authority). No other permissions are required. | ||
1021 | * | ||
1022 | * If successful, 0 will be returned. | ||
1023 | */ | ||
1024 | long keyctl_instantiate_key(key_serial_t id, | ||
1025 | const void __user *_payload, | ||
1026 | size_t plen, | ||
1027 | key_serial_t ringid) | ||
1028 | { | ||
1029 | if (_payload && plen) { | ||
1030 | struct iovec iov[1] = { | ||
1031 | [0].iov_base = (void __user *)_payload, | ||
1032 | [0].iov_len = plen | ||
1033 | }; | ||
1034 | |||
1035 | return keyctl_instantiate_key_common(id, iov, 1, plen, ringid); | ||
1036 | } | ||
1037 | |||
1038 | return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); | ||
1039 | } | ||
1040 | |||
1041 | /* | ||
1042 | * Instantiate a key with the specified multipart payload and link the key into | ||
1043 | * the destination keyring if one is given. | ||
1044 | * | ||
1045 | * The caller must have the appropriate instantiation permit set for this to | ||
1046 | * work (see keyctl_assume_authority). No other permissions are required. | ||
1047 | * | ||
1048 | * If successful, 0 will be returned. | ||
1049 | */ | ||
1050 | long keyctl_instantiate_key_iov(key_serial_t id, | ||
1051 | const struct iovec __user *_payload_iov, | ||
1052 | unsigned ioc, | ||
1053 | key_serial_t ringid) | ||
1054 | { | ||
1055 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; | ||
1056 | long ret; | ||
1057 | |||
1058 | if (_payload_iov == 0 || ioc == 0) | ||
1059 | goto no_payload; | ||
1060 | |||
1061 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, | ||
1062 | ARRAY_SIZE(iovstack), iovstack, &iov); | ||
1063 | if (ret < 0) | ||
1064 | return ret; | ||
1065 | if (ret == 0) | ||
1066 | goto no_payload_free; | ||
1067 | |||
1068 | ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); | ||
1069 | |||
1070 | if (iov != iovstack) | ||
1071 | kfree(iov); | ||
1072 | return ret; | ||
1073 | |||
1074 | no_payload_free: | ||
1075 | if (iov != iovstack) | ||
1076 | kfree(iov); | ||
1077 | no_payload: | ||
1078 | return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); | ||
1079 | } | ||
1080 | |||
1081 | /* | ||
1000 | * Negatively instantiate the key with the given timeout (in seconds) and link | 1082 | * Negatively instantiate the key with the given timeout (in seconds) and link |
1001 | * the key into the destination keyring if one is given. | 1083 | * the key into the destination keyring if one is given. |
1002 | * | 1084 | * |
@@ -1013,12 +1095,42 @@ error: | |||
1013 | */ | 1095 | */ |
1014 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | 1096 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) |
1015 | { | 1097 | { |
1098 | return keyctl_reject_key(id, timeout, ENOKEY, ringid); | ||
1099 | } | ||
1100 | |||
1101 | /* | ||
1102 | * Negatively instantiate the key with the given timeout (in seconds) and error | ||
1103 | * code and link the key into the destination keyring if one is given. | ||
1104 | * | ||
1105 | * The caller must have the appropriate instantiation permit set for this to | ||
1106 | * work (see keyctl_assume_authority). No other permissions are required. | ||
1107 | * | ||
1108 | * The key and any links to the key will be automatically garbage collected | ||
1109 | * after the timeout expires. | ||
1110 | * | ||
1111 | * Negative keys are used to rate limit repeated request_key() calls by causing | ||
1112 | * them to return the specified error code until the negative key expires. | ||
1113 | * | ||
1114 | * If successful, 0 will be returned. | ||
1115 | */ | ||
1116 | long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error, | ||
1117 | key_serial_t ringid) | ||
1118 | { | ||
1016 | const struct cred *cred = current_cred(); | 1119 | const struct cred *cred = current_cred(); |
1017 | struct request_key_auth *rka; | 1120 | struct request_key_auth *rka; |
1018 | struct key *instkey, *dest_keyring; | 1121 | struct key *instkey, *dest_keyring; |
1019 | long ret; | 1122 | long ret; |
1020 | 1123 | ||
1021 | kenter("%d,%u,%d", id, timeout, ringid); | 1124 | kenter("%d,%u,%u,%d", id, timeout, error, ringid); |
1125 | |||
1126 | /* must be a valid error code and mustn't be a kernel special */ | ||
1127 | if (error <= 0 || | ||
1128 | error >= MAX_ERRNO || | ||
1129 | error == ERESTARTSYS || | ||
1130 | error == ERESTARTNOINTR || | ||
1131 | error == ERESTARTNOHAND || | ||
1132 | error == ERESTART_RESTARTBLOCK) | ||
1133 | return -EINVAL; | ||
1022 | 1134 | ||
1023 | /* the appropriate instantiation authorisation key must have been | 1135 | /* the appropriate instantiation authorisation key must have been |
1024 | * assumed before calling this */ | 1136 | * assumed before calling this */ |
@@ -1038,7 +1150,7 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
1038 | goto error; | 1150 | goto error; |
1039 | 1151 | ||
1040 | /* instantiate the key and link it into a keyring */ | 1152 | /* instantiate the key and link it into a keyring */ |
1041 | ret = key_negate_and_link(rka->target_key, timeout, | 1153 | ret = key_reject_and_link(rka->target_key, timeout, error, |
1042 | dest_keyring, instkey); | 1154 | dest_keyring, instkey); |
1043 | 1155 | ||
1044 | key_put(dest_keyring); | 1156 | key_put(dest_keyring); |
@@ -1492,6 +1604,19 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
1492 | case KEYCTL_SESSION_TO_PARENT: | 1604 | case KEYCTL_SESSION_TO_PARENT: |
1493 | return keyctl_session_to_parent(); | 1605 | return keyctl_session_to_parent(); |
1494 | 1606 | ||
1607 | case KEYCTL_REJECT: | ||
1608 | return keyctl_reject_key((key_serial_t) arg2, | ||
1609 | (unsigned) arg3, | ||
1610 | (unsigned) arg4, | ||
1611 | (key_serial_t) arg5); | ||
1612 | |||
1613 | case KEYCTL_INSTANTIATE_IOV: | ||
1614 | return keyctl_instantiate_key_iov( | ||
1615 | (key_serial_t) arg2, | ||
1616 | (const struct iovec __user *) arg3, | ||
1617 | (unsigned) arg4, | ||
1618 | (key_serial_t) arg5); | ||
1619 | |||
1495 | default: | 1620 | default: |
1496 | return -EOPNOTSUPP; | 1621 | return -EOPNOTSUPP; |
1497 | } | 1622 | } |