aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2010-06-11 12:31:10 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:34:27 -0400
commit927942aabbbe506bf9bc70a16dc5460ecc64c148 (patch)
tree2c53ccb405bd4afb03ff9f7acab892fafc7e9b0f
parent9156235b3427d6f01c5c95022f72f381f07583f5 (diff)
KEYS: Make /proc/keys check to see if a key is possessed before security check
Make /proc/keys check to see if the calling process possesses each key before performing the security check. The possession check can be skipped if the key doesn't have the possessor-view permission bit set. This causes the keys a process possesses to show up in /proc/keys, even if they don't have matching user/group/other view permissions. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--security/keys/internal.h5
-rw-r--r--security/keys/proc.c20
-rw-r--r--security/keys/process_keys.c64
3 files changed, 66 insertions, 23 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 38783dcf6c61..addb67b169f4 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -114,6 +114,10 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
114 const void *description, 114 const void *description,
115 key_match_func_t match); 115 key_match_func_t match);
116 116
117extern key_ref_t search_my_process_keyrings(struct key_type *type,
118 const void *description,
119 key_match_func_t match,
120 const struct cred *cred);
117extern key_ref_t search_process_keyrings(struct key_type *type, 121extern key_ref_t search_process_keyrings(struct key_type *type,
118 const void *description, 122 const void *description,
119 key_match_func_t match, 123 key_match_func_t match,
@@ -134,6 +138,7 @@ extern struct key *request_key_and_link(struct key_type *type,
134 struct key *dest_keyring, 138 struct key *dest_keyring,
135 unsigned long flags); 139 unsigned long flags);
136 140
141extern int lookup_user_key_possessed(const struct key *key, const void *target);
137extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, 142extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
138 key_perm_t perm); 143 key_perm_t perm);
139#define KEY_LOOKUP_CREATE 0x01 144#define KEY_LOOKUP_CREATE 0x01
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 068b66ea2f1b..70373966816e 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -184,20 +184,36 @@ static void proc_keys_stop(struct seq_file *p, void *v)
184 184
185static int proc_keys_show(struct seq_file *m, void *v) 185static int proc_keys_show(struct seq_file *m, void *v)
186{ 186{
187 const struct cred *cred = current_cred();
187 struct rb_node *_p = v; 188 struct rb_node *_p = v;
188 struct key *key = rb_entry(_p, struct key, serial_node); 189 struct key *key = rb_entry(_p, struct key, serial_node);
189 struct timespec now; 190 struct timespec now;
190 unsigned long timo; 191 unsigned long timo;
192 key_ref_t key_ref, skey_ref;
191 char xbuf[12]; 193 char xbuf[12];
192 int rc; 194 int rc;
193 195
196 key_ref = make_key_ref(key, 0);
197
198 /* determine if the key is possessed by this process (a test we can
199 * skip if the key does not indicate the possessor can view it
200 */
201 if (key->perm & KEY_POS_VIEW) {
202 skey_ref = search_my_process_keyrings(key->type, key,
203 lookup_user_key_possessed,
204 cred);
205 if (!IS_ERR(skey_ref)) {
206 key_ref_put(skey_ref);
207 key_ref = make_key_ref(key, 1);
208 }
209 }
210
194 /* check whether the current task is allowed to view the key (assuming 211 /* check whether the current task is allowed to view the key (assuming
195 * non-possession) 212 * non-possession)
196 * - the caller holds a spinlock, and thus the RCU read lock, making our 213 * - the caller holds a spinlock, and thus the RCU read lock, making our
197 * access to __current_cred() safe 214 * access to __current_cred() safe
198 */ 215 */
199 rc = key_task_permission(make_key_ref(key, 0), current_cred(), 216 rc = key_task_permission(key_ref, cred, KEY_VIEW);
200 KEY_VIEW);
201 if (rc < 0) 217 if (rc < 0)
202 return 0; 218 return 0;
203 219
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 6b8e4ff4cc68..f8e7251ae2c8 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -309,22 +309,19 @@ void key_fsgid_changed(struct task_struct *tsk)
309 309
310/*****************************************************************************/ 310/*****************************************************************************/
311/* 311/*
312 * search the process keyrings for the first matching key 312 * search only my process keyrings for the first matching key
313 * - we use the supplied match function to see if the description (or other 313 * - we use the supplied match function to see if the description (or other
314 * feature of interest) matches 314 * feature of interest) matches
315 * - we return -EAGAIN if we didn't find any matching key 315 * - we return -EAGAIN if we didn't find any matching key
316 * - we return -ENOKEY if we found only negative matching keys 316 * - we return -ENOKEY if we found only negative matching keys
317 */ 317 */
318key_ref_t search_process_keyrings(struct key_type *type, 318key_ref_t search_my_process_keyrings(struct key_type *type,
319 const void *description, 319 const void *description,
320 key_match_func_t match, 320 key_match_func_t match,
321 const struct cred *cred) 321 const struct cred *cred)
322{ 322{
323 struct request_key_auth *rka;
324 key_ref_t key_ref, ret, err; 323 key_ref_t key_ref, ret, err;
325 324
326 might_sleep();
327
328 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 325 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
329 * searchable, but we failed to find a key or we found a negative key; 326 * searchable, but we failed to find a key or we found a negative key;
330 * otherwise we want to return a sample error (probably -EACCES) if 327 * otherwise we want to return a sample error (probably -EACCES) if
@@ -424,6 +421,36 @@ key_ref_t search_process_keyrings(struct key_type *type,
424 } 421 }
425 } 422 }
426 423
424 /* no key - decide on the error we're going to go for */
425 key_ref = ret ? ret : err;
426
427found:
428 return key_ref;
429}
430
431/*****************************************************************************/
432/*
433 * search the process keyrings for the first matching key
434 * - we use the supplied match function to see if the description (or other
435 * feature of interest) matches
436 * - we return -EAGAIN if we didn't find any matching key
437 * - we return -ENOKEY if we found only negative matching keys
438 */
439key_ref_t search_process_keyrings(struct key_type *type,
440 const void *description,
441 key_match_func_t match,
442 const struct cred *cred)
443{
444 struct request_key_auth *rka;
445 key_ref_t key_ref, ret = ERR_PTR(-EACCES), err;
446
447 might_sleep();
448
449 key_ref = search_my_process_keyrings(type, description, match, cred);
450 if (!IS_ERR(key_ref))
451 goto found;
452 err = key_ref;
453
427 /* if this process has an instantiation authorisation key, then we also 454 /* if this process has an instantiation authorisation key, then we also
428 * search the keyrings of the process mentioned there 455 * search the keyrings of the process mentioned there
429 * - we don't permit access to request_key auth keys via this method 456 * - we don't permit access to request_key auth keys via this method
@@ -446,24 +473,19 @@ key_ref_t search_process_keyrings(struct key_type *type,
446 if (!IS_ERR(key_ref)) 473 if (!IS_ERR(key_ref))
447 goto found; 474 goto found;
448 475
449 switch (PTR_ERR(key_ref)) { 476 ret = key_ref;
450 case -EAGAIN: /* no key */
451 if (ret)
452 break;
453 case -ENOKEY: /* negative key */
454 ret = key_ref;
455 break;
456 default:
457 err = key_ref;
458 break;
459 }
460 } else { 477 } else {
461 up_read(&cred->request_key_auth->sem); 478 up_read(&cred->request_key_auth->sem);
462 } 479 }
463 } 480 }
464 481
465 /* no key - decide on the error we're going to go for */ 482 /* no key - decide on the error we're going to go for */
466 key_ref = ret ? ret : err; 483 if (err == ERR_PTR(-ENOKEY) || ret == ERR_PTR(-ENOKEY))
484 key_ref = ERR_PTR(-ENOKEY);
485 else if (err == ERR_PTR(-EACCES))
486 key_ref = ret;
487 else
488 key_ref = err;
467 489
468found: 490found:
469 return key_ref; 491 return key_ref;
@@ -474,7 +496,7 @@ found:
474/* 496/*
475 * see if the key we're looking at is the target key 497 * see if the key we're looking at is the target key
476 */ 498 */
477static int lookup_user_key_possessed(const struct key *key, const void *target) 499int lookup_user_key_possessed(const struct key *key, const void *target)
478{ 500{
479 return key == target; 501 return key == target;
480 502