aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/keys.txt10
-rw-r--r--include/linux/key.h5
-rw-r--r--security/keys/key.c4
-rw-r--r--security/keys/process_keys.c42
-rw-r--r--security/keys/request_key_auth.c45
5 files changed, 89 insertions, 17 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 703020012708..3bbe157b45e4 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -964,6 +964,16 @@ The structure has a number of fields, some of which are mandatory:
964 It is not safe to sleep in this method; the caller may hold spinlocks. 964 It is not safe to sleep in this method; the caller may hold spinlocks.
965 965
966 966
967 (*) void (*revoke)(struct key *key);
968
969 This method is optional. It is called to discard part of the payload
970 data upon a key being revoked. The caller will have the key semaphore
971 write-locked.
972
973 It is safe to sleep in this method, though care should be taken to avoid
974 a deadlock against the key semaphore.
975
976
967 (*) void (*destroy)(struct key *key); 977 (*) void (*destroy)(struct key *key);
968 978
969 This method is optional. It is called to discard the payload data on a key 979 This method is optional. It is called to discard the payload data on a key
diff --git a/include/linux/key.h b/include/linux/key.h
index 8c275d12ef63..e81ebf910d0b 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -205,6 +205,11 @@ struct key_type {
205 /* match a key against a description */ 205 /* match a key against a description */
206 int (*match)(const struct key *key, const void *desc); 206 int (*match)(const struct key *key, const void *desc);
207 207
208 /* clear some of the data from a key on revokation (optional)
209 * - the key's semaphore will be write-locked by the caller
210 */
211 void (*revoke)(struct key *key);
212
208 /* clear the data from a key (optional) */ 213 /* clear the data from a key (optional) */
209 void (*destroy)(struct key *key); 214 void (*destroy)(struct key *key);
210 215
diff --git a/security/keys/key.c b/security/keys/key.c
index 14a15abb7735..51f851557389 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -907,6 +907,10 @@ void key_revoke(struct key *key)
907 * it */ 907 * it */
908 down_write(&key->sem); 908 down_write(&key->sem);
909 set_bit(KEY_FLAG_REVOKED, &key->flags); 909 set_bit(KEY_FLAG_REVOKED, &key->flags);
910
911 if (key->type->revoke)
912 key->type->revoke(key);
913
910 up_write(&key->sem); 914 up_write(&key->sem);
911 915
912} /* end key_revoke() */ 916} /* end key_revoke() */
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index a50a91332fe1..4d9825f9962c 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -391,6 +391,8 @@ key_ref_t search_process_keyrings(struct key_type *type,
391 struct request_key_auth *rka; 391 struct request_key_auth *rka;
392 key_ref_t key_ref, ret, err; 392 key_ref_t key_ref, ret, err;
393 393
394 might_sleep();
395
394 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 396 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
395 * searchable, but we failed to find a key or we found a negative key; 397 * searchable, but we failed to find a key or we found a negative key;
396 * otherwise we want to return a sample error (probably -EACCES) if 398 * otherwise we want to return a sample error (probably -EACCES) if
@@ -496,27 +498,35 @@ key_ref_t search_process_keyrings(struct key_type *type,
496 */ 498 */
497 if (context->request_key_auth && 499 if (context->request_key_auth &&
498 context == current && 500 context == current &&
499 type != &key_type_request_key_auth && 501 type != &key_type_request_key_auth
500 key_validate(context->request_key_auth) == 0
501 ) { 502 ) {
502 rka = context->request_key_auth->payload.data; 503 /* defend against the auth key being revoked */
504 down_read(&context->request_key_auth->sem);
503 505
504 key_ref = search_process_keyrings(type, description, match, 506 if (key_validate(context->request_key_auth) == 0) {
505 rka->context); 507 rka = context->request_key_auth->payload.data;
506 508
507 if (!IS_ERR(key_ref)) 509 key_ref = search_process_keyrings(type, description,
508 goto found; 510 match, rka->context);
509 511
510 switch (PTR_ERR(key_ref)) { 512 up_read(&context->request_key_auth->sem);
511 case -EAGAIN: /* no key */ 513
512 if (ret) 514 if (!IS_ERR(key_ref))
515 goto found;
516
517 switch (PTR_ERR(key_ref)) {
518 case -EAGAIN: /* no key */
519 if (ret)
520 break;
521 case -ENOKEY: /* negative key */
522 ret = key_ref;
513 break; 523 break;
514 case -ENOKEY: /* negative key */ 524 default:
515 ret = key_ref; 525 err = key_ref;
516 break; 526 break;
517 default: 527 }
518 err = key_ref; 528 } else {
519 break; 529 up_read(&context->request_key_auth->sem);
520 } 530 }
521 } 531 }
522 532
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 0ecc2e8d2bd0..cb9817ced3fd 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -20,6 +20,7 @@
20 20
21static int request_key_auth_instantiate(struct key *, const void *, size_t); 21static int request_key_auth_instantiate(struct key *, const void *, size_t);
22static void request_key_auth_describe(const struct key *, struct seq_file *); 22static void request_key_auth_describe(const struct key *, struct seq_file *);
23static void request_key_auth_revoke(struct key *);
23static void request_key_auth_destroy(struct key *); 24static void request_key_auth_destroy(struct key *);
24static long request_key_auth_read(const struct key *, char __user *, size_t); 25static long request_key_auth_read(const struct key *, char __user *, size_t);
25 26
@@ -31,6 +32,7 @@ struct key_type key_type_request_key_auth = {
31 .def_datalen = sizeof(struct request_key_auth), 32 .def_datalen = sizeof(struct request_key_auth),
32 .instantiate = request_key_auth_instantiate, 33 .instantiate = request_key_auth_instantiate,
33 .describe = request_key_auth_describe, 34 .describe = request_key_auth_describe,
35 .revoke = request_key_auth_revoke,
34 .destroy = request_key_auth_destroy, 36 .destroy = request_key_auth_destroy,
35 .read = request_key_auth_read, 37 .read = request_key_auth_read,
36}; 38};
@@ -93,6 +95,24 @@ static long request_key_auth_read(const struct key *key,
93 95
94/*****************************************************************************/ 96/*****************************************************************************/
95/* 97/*
98 * handle revocation of an authorisation token key
99 * - called with the key sem write-locked
100 */
101static void request_key_auth_revoke(struct key *key)
102{
103 struct request_key_auth *rka = key->payload.data;
104
105 kenter("{%d}", key->serial);
106
107 if (rka->context) {
108 put_task_struct(rka->context);
109 rka->context = NULL;
110 }
111
112} /* end request_key_auth_revoke() */
113
114/*****************************************************************************/
115/*
96 * destroy an instantiation authorisation token key 116 * destroy an instantiation authorisation token key
97 */ 117 */
98static void request_key_auth_destroy(struct key *key) 118static void request_key_auth_destroy(struct key *key)
@@ -101,6 +121,11 @@ static void request_key_auth_destroy(struct key *key)
101 121
102 kenter("{%d}", key->serial); 122 kenter("{%d}", key->serial);
103 123
124 if (rka->context) {
125 put_task_struct(rka->context);
126 rka->context = NULL;
127 }
128
104 key_put(rka->target_key); 129 key_put(rka->target_key);
105 kfree(rka); 130 kfree(rka);
106 131
@@ -131,14 +156,26 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
131 * another process */ 156 * another process */
132 if (current->request_key_auth) { 157 if (current->request_key_auth) {
133 /* it is - use that instantiation context here too */ 158 /* it is - use that instantiation context here too */
159 down_read(&current->request_key_auth->sem);
160
161 /* if the auth key has been revoked, then the key we're
162 * servicing is already instantiated */
163 if (test_bit(KEY_FLAG_REVOKED,
164 &current->request_key_auth->flags))
165 goto auth_key_revoked;
166
134 irka = current->request_key_auth->payload.data; 167 irka = current->request_key_auth->payload.data;
135 rka->context = irka->context; 168 rka->context = irka->context;
136 rka->pid = irka->pid; 169 rka->pid = irka->pid;
170 get_task_struct(rka->context);
171
172 up_read(&current->request_key_auth->sem);
137 } 173 }
138 else { 174 else {
139 /* it isn't - use this process as the context */ 175 /* it isn't - use this process as the context */
140 rka->context = current; 176 rka->context = current;
141 rka->pid = current->pid; 177 rka->pid = current->pid;
178 get_task_struct(rka->context);
142 } 179 }
143 180
144 rka->target_key = key_get(target); 181 rka->target_key = key_get(target);
@@ -161,9 +198,15 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
161 if (ret < 0) 198 if (ret < 0)
162 goto error_inst; 199 goto error_inst;
163 200
164 kleave(" = {%d})", authkey->serial); 201 kleave(" = {%d}", authkey->serial);
165 return authkey; 202 return authkey;
166 203
204auth_key_revoked:
205 up_read(&current->request_key_auth->sem);
206 kfree(rka);
207 kleave("= -EKEYREVOKED");
208 return ERR_PTR(-EKEYREVOKED);
209
167error_inst: 210error_inst:
168 key_revoke(authkey); 211 key_revoke(authkey);
169 key_put(authkey); 212 key_put(authkey);