aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2011-03-07 10:06:09 -0500
committerJames Morris <jmorris@namei.org>2011-03-07 19:17:18 -0500
commitfdd1b94581782a2ddf9124414e5b7a5f48ce2f9c (patch)
treece83bfd1f0b1a7d4b9521bdb3d6afef1bff1d4f2
parentb9fffa3877a3ebbe0a5ad5a247358e2f7df15b24 (diff)
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>
-rw-r--r--Documentation/keys-request-key.txt9
-rw-r--r--Documentation/keys.txt10
-rw-r--r--include/linux/key-type.h11
-rw-r--r--include/linux/key.h1
-rw-r--r--include/linux/keyctl.h1
-rw-r--r--security/keys/compat.c3
-rw-r--r--security/keys/internal.h1
-rw-r--r--security/keys/key.c19
-rw-r--r--security/keys/keyctl.c40
-rw-r--r--security/keys/keyring.c4
-rw-r--r--security/keys/request_key.c2
11 files changed, 81 insertions, 20 deletions
diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt
index 09b55e461740..69686ad12c66 100644
--- a/Documentation/keys-request-key.txt
+++ b/Documentation/keys-request-key.txt
@@ -127,14 +127,15 @@ This is because process A's keyrings can't simply be attached to
127of them, and (b) it requires the same UID/GID/Groups all the way through. 127of them, and (b) it requires the same UID/GID/Groups all the way through.
128 128
129 129
130====================== 130====================================
131NEGATIVE INSTANTIATION 131NEGATIVE INSTANTIATION AND REJECTION
132====================== 132====================================
133 133
134Rather than instantiating a key, it is possible for the possessor of an 134Rather than instantiating a key, it is possible for the possessor of an
135authorisation key to negatively instantiate a key that's under construction. 135authorisation key to negatively instantiate a key that's under construction.
136This is a short duration placeholder that causes any attempt at re-requesting 136This is a short duration placeholder that causes any attempt at re-requesting
137the key whilst it exists to fail with error ENOKEY. 137the key whilst it exists to fail with error ENOKEY if negated or the specified
138error if rejected.
138 139
139This is provided to prevent excessive repeated spawning of /sbin/request-key 140This is provided to prevent excessive repeated spawning of /sbin/request-key
140processes for a key that will never be obtainable. 141processes for a key that will never be obtainable.
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index cf68d1fed95d..a6a97fdfaddd 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -657,6 +657,8 @@ The keyctl syscall functions are:
657 657
658 long keyctl(KEYCTL_NEGATE, key_serial_t key, 658 long keyctl(KEYCTL_NEGATE, key_serial_t key,
659 unsigned timeout, key_serial_t keyring); 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 If the kernel calls back to userspace to complete the instantiation of a 663 If the kernel calls back to userspace to complete the instantiation of a
662 key, userspace should use this call mark the key as negative before the 664 key, userspace should use this call mark the key as negative before the
@@ -669,6 +671,10 @@ The keyctl syscall functions are:
669 that keyring, however all the constraints applying in KEYCTL_LINK apply in 671 that keyring, however all the constraints applying in KEYCTL_LINK apply in
670 this case too. 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.
677
672 678
673 (*) Set the default request-key destination keyring. 679 (*) Set the default request-key destination keyring.
674 680
@@ -1240,8 +1246,8 @@ example, the KDE desktop manager).
1240The program (or whatever it calls) should finish construction of the key by 1246The program (or whatever it calls) should finish construction of the key by
1241calling KEYCTL_INSTANTIATE, which also permits it to cache the key in one of 1247calling KEYCTL_INSTANTIATE, which also permits it to cache the key in one of
1242the keyrings (probably the session ring) before returning. Alternatively, the 1248the keyrings (probably the session ring) before returning. Alternatively, the
1243key can be marked as negative with KEYCTL_NEGATE; this also permits the key to 1249key can be marked as negative with KEYCTL_NEGATE or KEYCTL_REJECT; this also
1244be cached in one of the keyrings. 1250permits the key to be cached in one of the keyrings.
1245 1251
1246If it returns with the key remaining in the unconstructed state, the key will 1252If it returns with the key remaining in the unconstructed state, the key will
1247be marked as being negative, it will be added to the session keyring, and an 1253be marked as being negative, it will be added to the session keyring, and an
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index fc8525e838b7..9efd081bb31e 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -105,11 +105,20 @@ extern int key_instantiate_and_link(struct key *key,
105 size_t datalen, 105 size_t datalen,
106 struct key *keyring, 106 struct key *keyring,
107 struct key *instkey); 107 struct key *instkey);
108extern int key_negate_and_link(struct key *key, 108extern int key_reject_and_link(struct key *key,
109 unsigned timeout, 109 unsigned timeout,
110 unsigned error,
110 struct key *keyring, 111 struct key *keyring,
111 struct key *instkey); 112 struct key *instkey);
112extern void complete_request_key(struct key_construction *cons, int error); 113extern void complete_request_key(struct key_construction *cons, int error);
113 114
115static 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}
122
114#endif /* CONFIG_KEYS */ 123#endif /* CONFIG_KEYS */
115#endif /* _LINUX_KEY_TYPE_H */ 124#endif /* _LINUX_KEY_TYPE_H */
diff --git a/include/linux/key.h b/include/linux/key.h
index a6b1edcffc34..b2bb01719561 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -170,6 +170,7 @@ struct key {
170 struct list_head link; 170 struct list_head link;
171 unsigned long x[2]; 171 unsigned long x[2];
172 void *p[2]; 172 void *p[2];
173 int reject_error;
173 } type_data; 174 } type_data;
174 175
175 /* key data 176 /* key data
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index bd383f1944fb..7022974def0c 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -53,5 +53,6 @@
53#define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */ 53#define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */
54#define KEYCTL_GET_SECURITY 17 /* get key security label */ 54#define KEYCTL_GET_SECURITY 17 /* get key security label */
55#define KEYCTL_SESSION_TO_PARENT 18 /* apply session keyring to parent process */ 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#endif /* _LINUX_KEYCTL_H */ 58#endif /* _LINUX_KEYCTL_H */
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 07a5f35e3970..17c99d0149ec 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -85,6 +85,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
85 case KEYCTL_SESSION_TO_PARENT: 85 case KEYCTL_SESSION_TO_PARENT:
86 return keyctl_session_to_parent(); 86 return keyctl_session_to_parent();
87 87
88 case KEYCTL_REJECT:
89 return keyctl_reject_key(arg2, arg3, arg4, arg5);
90
88 default: 91 default:
89 return -EOPNOTSUPP; 92 return -EOPNOTSUPP;
90 } 93 }
diff --git a/security/keys/internal.h b/security/keys/internal.h
index a52aa7c88b41..286c0959ee51 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -214,6 +214,7 @@ extern long keyctl_assume_authority(key_serial_t);
214extern long keyctl_get_security(key_serial_t keyid, char __user *buffer, 214extern long keyctl_get_security(key_serial_t keyid, char __user *buffer,
215 size_t buflen); 215 size_t buflen);
216extern long keyctl_session_to_parent(void); 216extern long keyctl_session_to_parent(void);
217extern long keyctl_reject_key(key_serial_t, unsigned, unsigned, key_serial_t);
217 218
218/* 219/*
219 * Debugging key validation 220 * Debugging key validation
diff --git a/security/keys/key.c b/security/keys/key.c
index 8e315ef2e88e..f7f9d93f08d9 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -511,26 +511,29 @@ int key_instantiate_and_link(struct key *key,
511EXPORT_SYMBOL(key_instantiate_and_link); 511EXPORT_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 * @key: The key to instantiate. 515 * @key: The key to instantiate.
516 * @timeout: The timeout on the negative key. 516 * @timeout: The timeout on the negative key.
517 * @error: The error to return when the key is hit.
517 * @keyring: Keyring to create a link in on success (or NULL). 518 * @keyring: Keyring to create a link in on success (or NULL).
518 * @authkey: The authorisation token permitting instantiation. 519 * @authkey: The authorisation token permitting instantiation.
519 * 520 *
520 * Negatively instantiate a key that's in the uninstantiated state and, if 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 * successful, set its timeout and stored error and link it in to the
522 * is supplied. The key and any links to the key will be automatically garbage 523 * destination keyring if one is supplied. The key and any links to the key
523 * collected after the timeout expires. 524 * will be automatically garbage collected after the timeout expires.
524 * 525 *
525 * Negative keys are used to rate limit repeated request_key() calls by causing 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 * If successful, 0 is returned, the authorisation token is revoked and anyone 530 * If successful, 0 is returned, the authorisation token is revoked and anyone
529 * waiting for the key is woken up. If the key was already instantiated, 531 * waiting for the key is woken up. If the key was already instantiated,
530 * -EBUSY will be returned. 532 * -EBUSY will be returned.
531 */ 533 */
532int key_negate_and_link(struct key *key, 534int key_reject_and_link(struct key *key,
533 unsigned timeout, 535 unsigned timeout,
536 unsigned error,
534 struct key *keyring, 537 struct key *keyring,
535 struct key *authkey) 538 struct key *authkey)
536{ 539{
@@ -556,6 +559,7 @@ int key_negate_and_link(struct key *key,
556 atomic_inc(&key->user->nikeys); 559 atomic_inc(&key->user->nikeys);
557 set_bit(KEY_FLAG_NEGATIVE, &key->flags); 560 set_bit(KEY_FLAG_NEGATIVE, &key->flags);
558 set_bit(KEY_FLAG_INSTANTIATED, &key->flags); 561 set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
562 key->type_data.reject_error = -error;
559 now = current_kernel_time(); 563 now = current_kernel_time();
560 key->expiry = now.tv_sec + timeout; 564 key->expiry = now.tv_sec + timeout;
561 key_schedule_gc(key->expiry + key_gc_delay); 565 key_schedule_gc(key->expiry + key_gc_delay);
@@ -585,8 +589,7 @@ int key_negate_and_link(struct key *key,
585 589
586 return ret == 0 ? link_ret : ret; 590 return ret == 0 ? link_ret : ret;
587} 591}
588 592EXPORT_SYMBOL(key_reject_and_link);
589EXPORT_SYMBOL(key_negate_and_link);
590 593
591/* 594/*
592 * Garbage collect keys in process context so that we don't have to disable 595 * Garbage collect keys in process context so that we don't have to disable
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 */
1014long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) 1014long 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 */
1034long 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 }
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 5620f084dede..cdd2f3f88c88 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -352,7 +352,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
352 goto error_2; 352 goto error_2;
353 if (key->expiry && now.tv_sec >= key->expiry) 353 if (key->expiry && now.tv_sec >= key->expiry)
354 goto error_2; 354 goto error_2;
355 key_ref = ERR_PTR(-ENOKEY); 355 key_ref = ERR_PTR(key->type_data.reject_error);
356 if (kflags & (1 << KEY_FLAG_NEGATIVE)) 356 if (kflags & (1 << KEY_FLAG_NEGATIVE))
357 goto error_2; 357 goto error_2;
358 goto found; 358 goto found;
@@ -401,7 +401,7 @@ descend:
401 401
402 /* we set a different error code if we pass a negative key */ 402 /* we set a different error code if we pass a negative key */
403 if (kflags & (1 << KEY_FLAG_NEGATIVE)) { 403 if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
404 err = -ENOKEY; 404 err = key->type_data.reject_error;
405 continue; 405 continue;
406 } 406 }
407 407
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index a3dc0d460def..df3c0417ee40 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -585,7 +585,7 @@ int wait_for_key_construction(struct key *key, bool intr)
585 if (ret < 0) 585 if (ret < 0)
586 return ret; 586 return ret;
587 if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) 587 if (test_bit(KEY_FLAG_NEGATIVE, &key->flags))
588 return -ENOKEY; 588 return key->type_data.reject_error;
589 return key_validate(key); 589 return key_validate(key);
590} 590}
591EXPORT_SYMBOL(wait_for_key_construction); 591EXPORT_SYMBOL(wait_for_key_construction);