Commit fdd1b94581782a2ddf9124414e5b7a5f48ce2f9c

Authored by David Howells
Committed by James Morris
1 parent b9fffa3877

KEYS: Add a new keyctl op to reject a key with a specified error code

Add a new keyctl op to reject a key with a specified error code.  This works
much the same as negating a key, and so keyctl_negate_key() is made a special
case of keyctl_reject_key().  The difference is that keyctl_negate_key()
selects ENOKEY as the error to be reported.

Typically the key would be rejected with EKEYEXPIRED, EKEYREVOKED or
EKEYREJECTED, but this is not mandatory.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>

Showing 11 changed files with 81 additions and 20 deletions Side-by-side Diff

Documentation/keys-request-key.txt
... ... @@ -127,14 +127,15 @@
127 127 of them, and (b) it requires the same UID/GID/Groups all the way through.
128 128  
129 129  
130   -======================
131   -NEGATIVE INSTANTIATION
132   -======================
  130 +====================================
  131 +NEGATIVE INSTANTIATION AND REJECTION
  132 +====================================
133 133  
134 134 Rather than instantiating a key, it is possible for the possessor of an
135 135 authorisation key to negatively instantiate a key that's under construction.
136 136 This is a short duration placeholder that causes any attempt at re-requesting
137   -the key whilst it exists to fail with error ENOKEY.
  137 +the key whilst it exists to fail with error ENOKEY if negated or the specified
  138 +error if rejected.
138 139  
139 140 This is provided to prevent excessive repeated spawning of /sbin/request-key
140 141 processes for a key that will never be obtainable.
Documentation/keys.txt
... ... @@ -657,6 +657,8 @@
657 657  
658 658 long keyctl(KEYCTL_NEGATE, key_serial_t key,
659 659 unsigned timeout, key_serial_t keyring);
  660 + long keyctl(KEYCTL_REJECT, key_serial_t key,
  661 + unsigned timeout, unsigned error, key_serial_t keyring);
660 662  
661 663 If the kernel calls back to userspace to complete the instantiation of a
662 664 key, userspace should use this call mark the key as negative before the
663 665  
... ... @@ -669,7 +671,11 @@
669 671 that keyring, however all the constraints applying in KEYCTL_LINK apply in
670 672 this case too.
671 673  
  674 + If the key is rejected, future searches for it will return the specified
  675 + error code until the rejected key expires. Negating the key is the same
  676 + as rejecting the key with ENOKEY as the error code.
672 677  
  678 +
673 679 (*) Set the default request-key destination keyring.
674 680  
675 681 long keyctl(KEYCTL_SET_REQKEY_KEYRING, int reqkey_defl);
... ... @@ -1240,8 +1246,8 @@
1240 1246 The program (or whatever it calls) should finish construction of the key by
1241 1247 calling KEYCTL_INSTANTIATE, which also permits it to cache the key in one of
1242 1248 the keyrings (probably the session ring) before returning. Alternatively, the
1243   -key can be marked as negative with KEYCTL_NEGATE; this also permits the key to
1244   -be cached in one of the keyrings.
  1249 +key can be marked as negative with KEYCTL_NEGATE or KEYCTL_REJECT; this also
  1250 +permits the key to be cached in one of the keyrings.
1245 1251  
1246 1252 If it returns with the key remaining in the unconstructed state, the key will
1247 1253 be marked as being negative, it will be added to the session keyring, and an
include/linux/key-type.h
... ... @@ -105,11 +105,20 @@
105 105 size_t datalen,
106 106 struct key *keyring,
107 107 struct key *instkey);
108   -extern int key_negate_and_link(struct key *key,
  108 +extern int key_reject_and_link(struct key *key,
109 109 unsigned timeout,
  110 + unsigned error,
110 111 struct key *keyring,
111 112 struct key *instkey);
112 113 extern void complete_request_key(struct key_construction *cons, int error);
  114 +
  115 +static inline int key_negate_and_link(struct key *key,
  116 + unsigned timeout,
  117 + struct key *keyring,
  118 + struct key *instkey)
  119 +{
  120 + return key_reject_and_link(key, timeout, ENOKEY, keyring, instkey);
  121 +}
113 122  
114 123 #endif /* CONFIG_KEYS */
115 124 #endif /* _LINUX_KEY_TYPE_H */
... ... @@ -170,6 +170,7 @@
170 170 struct list_head link;
171 171 unsigned long x[2];
172 172 void *p[2];
  173 + int reject_error;
173 174 } type_data;
174 175  
175 176 /* key data
include/linux/keyctl.h
... ... @@ -53,6 +53,7 @@
53 53 #define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */
54 54 #define KEYCTL_GET_SECURITY 17 /* get key security label */
55 55 #define KEYCTL_SESSION_TO_PARENT 18 /* apply session keyring to parent process */
  56 +#define KEYCTL_REJECT 19 /* reject a partially constructed key */
56 57  
57 58 #endif /* _LINUX_KEYCTL_H */
security/keys/compat.c
... ... @@ -85,6 +85,9 @@
85 85 case KEYCTL_SESSION_TO_PARENT:
86 86 return keyctl_session_to_parent();
87 87  
  88 + case KEYCTL_REJECT:
  89 + return keyctl_reject_key(arg2, arg3, arg4, arg5);
  90 +
88 91 default:
89 92 return -EOPNOTSUPP;
90 93 }
security/keys/internal.h
... ... @@ -214,6 +214,7 @@
214 214 extern long keyctl_get_security(key_serial_t keyid, char __user *buffer,
215 215 size_t buflen);
216 216 extern long keyctl_session_to_parent(void);
  217 +extern long keyctl_reject_key(key_serial_t, unsigned, unsigned, key_serial_t);
217 218  
218 219 /*
219 220 * Debugging key validation
... ... @@ -511,26 +511,29 @@
511 511 EXPORT_SYMBOL(key_instantiate_and_link);
512 512  
513 513 /**
514   - * key_negate_and_link - Negatively instantiate a key and link it into the keyring.
  514 + * key_reject_and_link - Negatively instantiate a key and link it into the keyring.
515 515 * @key: The key to instantiate.
516 516 * @timeout: The timeout on the negative key.
  517 + * @error: The error to return when the key is hit.
517 518 * @keyring: Keyring to create a link in on success (or NULL).
518 519 * @authkey: The authorisation token permitting instantiation.
519 520 *
520 521 * Negatively instantiate a key that's in the uninstantiated state and, if
521   - * successful, set its timeout and link it in to the destination keyring if one
522   - * is supplied. The key and any links to the key will be automatically garbage
523   - * collected after the timeout expires.
  522 + * successful, set its timeout and stored error and link it in to the
  523 + * destination keyring if one is supplied. The key and any links to the key
  524 + * will be automatically garbage collected after the timeout expires.
524 525 *
525 526 * Negative keys are used to rate limit repeated request_key() calls by causing
526   - * them to return -ENOKEY until the negative key expires.
  527 + * them to return the stored error code (typically ENOKEY) until the negative
  528 + * key expires.
527 529 *
528 530 * If successful, 0 is returned, the authorisation token is revoked and anyone
529 531 * waiting for the key is woken up. If the key was already instantiated,
530 532 * -EBUSY will be returned.
531 533 */
532   -int key_negate_and_link(struct key *key,
  534 +int key_reject_and_link(struct key *key,
533 535 unsigned timeout,
  536 + unsigned error,
534 537 struct key *keyring,
535 538 struct key *authkey)
536 539 {
... ... @@ -556,6 +559,7 @@
556 559 atomic_inc(&key->user->nikeys);
557 560 set_bit(KEY_FLAG_NEGATIVE, &key->flags);
558 561 set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
  562 + key->type_data.reject_error = -error;
559 563 now = current_kernel_time();
560 564 key->expiry = now.tv_sec + timeout;
561 565 key_schedule_gc(key->expiry + key_gc_delay);
... ... @@ -585,8 +589,7 @@
585 589  
586 590 return ret == 0 ? link_ret : ret;
587 591 }
588   -
589   -EXPORT_SYMBOL(key_negate_and_link);
  592 +EXPORT_SYMBOL(key_reject_and_link);
590 593  
591 594 /*
592 595 * Garbage collect keys in process context so that we don't have to disable
security/keys/keyctl.c
... ... @@ -1013,13 +1013,43 @@
1013 1013 */
1014 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 1037 const struct cred *cred = current_cred();
1017 1038 struct request_key_auth *rka;
1018 1039 struct key *instkey, *dest_keyring;
1019 1040 long ret;
1020 1041  
1021   - kenter("%d,%u,%d", id, timeout, ringid);
  1042 + kenter("%d,%u,%u,%d", id, timeout, error, ringid);
1022 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;
  1052 +
1023 1053 /* the appropriate instantiation authorisation key must have been
1024 1054 * assumed before calling this */
1025 1055 ret = -EPERM;
... ... @@ -1038,7 +1068,7 @@
1038 1068 goto error;
1039 1069  
1040 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 1072 dest_keyring, instkey);
1043 1073  
1044 1074 key_put(dest_keyring);
... ... @@ -1491,6 +1521,12 @@
1491 1521  
1492 1522 case KEYCTL_SESSION_TO_PARENT:
1493 1523 return keyctl_session_to_parent();
  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);
1494 1530  
1495 1531 default:
1496 1532 return -EOPNOTSUPP;
security/keys/keyring.c
... ... @@ -352,7 +352,7 @@
352 352 goto error_2;
353 353 if (key->expiry && now.tv_sec >= key->expiry)
354 354 goto error_2;
355   - key_ref = ERR_PTR(-ENOKEY);
  355 + key_ref = ERR_PTR(key->type_data.reject_error);
356 356 if (kflags & (1 << KEY_FLAG_NEGATIVE))
357 357 goto error_2;
358 358 goto found;
... ... @@ -401,7 +401,7 @@
401 401  
402 402 /* we set a different error code if we pass a negative key */
403 403 if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
404   - err = -ENOKEY;
  404 + err = key->type_data.reject_error;
405 405 continue;
406 406 }
407 407  
security/keys/request_key.c
... ... @@ -585,7 +585,7 @@
585 585 if (ret < 0)
586 586 return ret;
587 587 if (test_bit(KEY_FLAG_NEGATIVE, &key->flags))
588   - return -ENOKEY;
  588 + return key->type_data.reject_error;
589 589 return key_validate(key);
590 590 }
591 591 EXPORT_SYMBOL(wait_for_key_construction);