diff options
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r-- | security/keys/keyctl.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 31a0fd8189f1..0d7b1946ff94 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -1013,12 +1013,42 @@ error: | |||
1013 | */ | 1013 | */ |
1014 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | 1014 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) |
1015 | { | 1015 | { |
1016 | return keyctl_reject_key(id, timeout, ENOKEY, ringid); | ||
1017 | } | ||
1018 | |||
1019 | /* | ||
1020 | * Negatively instantiate the key with the given timeout (in seconds) and error | ||
1021 | * code and link the key into the destination keyring if one is given. | ||
1022 | * | ||
1023 | * The caller must have the appropriate instantiation permit set for this to | ||
1024 | * work (see keyctl_assume_authority). No other permissions are required. | ||
1025 | * | ||
1026 | * The key and any links to the key will be automatically garbage collected | ||
1027 | * after the timeout expires. | ||
1028 | * | ||
1029 | * Negative keys are used to rate limit repeated request_key() calls by causing | ||
1030 | * them to return the specified error code until the negative key expires. | ||
1031 | * | ||
1032 | * If successful, 0 will be returned. | ||
1033 | */ | ||
1034 | long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error, | ||
1035 | key_serial_t ringid) | ||
1036 | { | ||
1016 | const struct cred *cred = current_cred(); | 1037 | const struct cred *cred = current_cred(); |
1017 | struct request_key_auth *rka; | 1038 | struct request_key_auth *rka; |
1018 | struct key *instkey, *dest_keyring; | 1039 | struct key *instkey, *dest_keyring; |
1019 | long ret; | 1040 | long ret; |
1020 | 1041 | ||
1021 | kenter("%d,%u,%d", id, timeout, ringid); | 1042 | kenter("%d,%u,%u,%d", id, timeout, error, ringid); |
1043 | |||
1044 | /* must be a valid error code and mustn't be a kernel special */ | ||
1045 | if (error <= 0 || | ||
1046 | error >= MAX_ERRNO || | ||
1047 | error == ERESTARTSYS || | ||
1048 | error == ERESTARTNOINTR || | ||
1049 | error == ERESTARTNOHAND || | ||
1050 | error == ERESTART_RESTARTBLOCK) | ||
1051 | return -EINVAL; | ||
1022 | 1052 | ||
1023 | /* the appropriate instantiation authorisation key must have been | 1053 | /* the appropriate instantiation authorisation key must have been |
1024 | * assumed before calling this */ | 1054 | * assumed before calling this */ |
@@ -1038,7 +1068,7 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
1038 | goto error; | 1068 | goto error; |
1039 | 1069 | ||
1040 | /* instantiate the key and link it into a keyring */ | 1070 | /* instantiate the key and link it into a keyring */ |
1041 | ret = key_negate_and_link(rka->target_key, timeout, | 1071 | ret = key_reject_and_link(rka->target_key, timeout, error, |
1042 | dest_keyring, instkey); | 1072 | dest_keyring, instkey); |
1043 | 1073 | ||
1044 | key_put(dest_keyring); | 1074 | key_put(dest_keyring); |
@@ -1492,6 +1522,12 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
1492 | case KEYCTL_SESSION_TO_PARENT: | 1522 | case KEYCTL_SESSION_TO_PARENT: |
1493 | return keyctl_session_to_parent(); | 1523 | return keyctl_session_to_parent(); |
1494 | 1524 | ||
1525 | case KEYCTL_REJECT: | ||
1526 | return keyctl_reject_key((key_serial_t) arg2, | ||
1527 | (unsigned) arg3, | ||
1528 | (unsigned) arg4, | ||
1529 | (key_serial_t) arg5); | ||
1530 | |||
1495 | default: | 1531 | default: |
1496 | return -EOPNOTSUPP; | 1532 | return -EOPNOTSUPP; |
1497 | } | 1533 | } |