diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /security/keys/process_keys.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r-- | security/keys/process_keys.c | 150 |
1 files changed, 89 insertions, 61 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index f8e7251ae2c8..a3063eb3dc23 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Management of a process's keyrings | 1 | /* Manage a process's keyrings |
2 | * | 2 | * |
3 | * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
@@ -21,13 +21,13 @@ | |||
21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
22 | #include "internal.h" | 22 | #include "internal.h" |
23 | 23 | ||
24 | /* session keyring create vs join semaphore */ | 24 | /* Session keyring create vs join semaphore */ |
25 | static DEFINE_MUTEX(key_session_mutex); | 25 | static DEFINE_MUTEX(key_session_mutex); |
26 | 26 | ||
27 | /* user keyring creation semaphore */ | 27 | /* User keyring creation semaphore */ |
28 | static DEFINE_MUTEX(key_user_keyring_mutex); | 28 | static DEFINE_MUTEX(key_user_keyring_mutex); |
29 | 29 | ||
30 | /* the root user's tracking struct */ | 30 | /* The root user's tracking struct */ |
31 | struct key_user root_key_user = { | 31 | struct key_user root_key_user = { |
32 | .usage = ATOMIC_INIT(3), | 32 | .usage = ATOMIC_INIT(3), |
33 | .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock), | 33 | .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock), |
@@ -38,9 +38,8 @@ struct key_user root_key_user = { | |||
38 | .user_ns = &init_user_ns, | 38 | .user_ns = &init_user_ns, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | /*****************************************************************************/ | ||
42 | /* | 41 | /* |
43 | * install user and user session keyrings for a particular UID | 42 | * Install the user and user session keyrings for the current process's UID. |
44 | */ | 43 | */ |
45 | int install_user_keyrings(void) | 44 | int install_user_keyrings(void) |
46 | { | 45 | { |
@@ -122,7 +121,8 @@ error: | |||
122 | } | 121 | } |
123 | 122 | ||
124 | /* | 123 | /* |
125 | * install a fresh thread keyring directly to new credentials | 124 | * Install a fresh thread keyring directly to new credentials. This keyring is |
125 | * allowed to overrun the quota. | ||
126 | */ | 126 | */ |
127 | int install_thread_keyring_to_cred(struct cred *new) | 127 | int install_thread_keyring_to_cred(struct cred *new) |
128 | { | 128 | { |
@@ -138,7 +138,7 @@ int install_thread_keyring_to_cred(struct cred *new) | |||
138 | } | 138 | } |
139 | 139 | ||
140 | /* | 140 | /* |
141 | * install a fresh thread keyring, discarding the old one | 141 | * Install a fresh thread keyring, discarding the old one. |
142 | */ | 142 | */ |
143 | static int install_thread_keyring(void) | 143 | static int install_thread_keyring(void) |
144 | { | 144 | { |
@@ -161,9 +161,10 @@ static int install_thread_keyring(void) | |||
161 | } | 161 | } |
162 | 162 | ||
163 | /* | 163 | /* |
164 | * install a process keyring directly to a credentials struct | 164 | * Install a process keyring directly to a credentials struct. |
165 | * - returns -EEXIST if there was already a process keyring, 0 if one installed, | 165 | * |
166 | * and other -ve on any other error | 166 | * Returns -EEXIST if there was already a process keyring, 0 if one installed, |
167 | * and other value on any other error | ||
167 | */ | 168 | */ |
168 | int install_process_keyring_to_cred(struct cred *new) | 169 | int install_process_keyring_to_cred(struct cred *new) |
169 | { | 170 | { |
@@ -192,8 +193,11 @@ int install_process_keyring_to_cred(struct cred *new) | |||
192 | } | 193 | } |
193 | 194 | ||
194 | /* | 195 | /* |
195 | * make sure a process keyring is installed | 196 | * Make sure a process keyring is installed for the current process. The |
196 | * - we | 197 | * existing process keyring is not replaced. |
198 | * | ||
199 | * Returns 0 if there is a process keyring by the end of this function, some | ||
200 | * error otherwise. | ||
197 | */ | 201 | */ |
198 | static int install_process_keyring(void) | 202 | static int install_process_keyring(void) |
199 | { | 203 | { |
@@ -207,14 +211,14 @@ static int install_process_keyring(void) | |||
207 | ret = install_process_keyring_to_cred(new); | 211 | ret = install_process_keyring_to_cred(new); |
208 | if (ret < 0) { | 212 | if (ret < 0) { |
209 | abort_creds(new); | 213 | abort_creds(new); |
210 | return ret != -EEXIST ?: 0; | 214 | return ret != -EEXIST ? ret : 0; |
211 | } | 215 | } |
212 | 216 | ||
213 | return commit_creds(new); | 217 | return commit_creds(new); |
214 | } | 218 | } |
215 | 219 | ||
216 | /* | 220 | /* |
217 | * install a session keyring directly to a credentials struct | 221 | * Install a session keyring directly to a credentials struct. |
218 | */ | 222 | */ |
219 | int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) | 223 | int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) |
220 | { | 224 | { |
@@ -254,8 +258,8 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) | |||
254 | } | 258 | } |
255 | 259 | ||
256 | /* | 260 | /* |
257 | * install a session keyring, discarding the old one | 261 | * Install a session keyring, discarding the old one. If a keyring is not |
258 | * - if a keyring is not supplied, an empty one is invented | 262 | * supplied, an empty one is invented. |
259 | */ | 263 | */ |
260 | static int install_session_keyring(struct key *keyring) | 264 | static int install_session_keyring(struct key *keyring) |
261 | { | 265 | { |
@@ -275,9 +279,8 @@ static int install_session_keyring(struct key *keyring) | |||
275 | return commit_creds(new); | 279 | return commit_creds(new); |
276 | } | 280 | } |
277 | 281 | ||
278 | /*****************************************************************************/ | ||
279 | /* | 282 | /* |
280 | * the filesystem user ID changed | 283 | * Handle the fsuid changing. |
281 | */ | 284 | */ |
282 | void key_fsuid_changed(struct task_struct *tsk) | 285 | void key_fsuid_changed(struct task_struct *tsk) |
283 | { | 286 | { |
@@ -288,12 +291,10 @@ void key_fsuid_changed(struct task_struct *tsk) | |||
288 | tsk->cred->thread_keyring->uid = tsk->cred->fsuid; | 291 | tsk->cred->thread_keyring->uid = tsk->cred->fsuid; |
289 | up_write(&tsk->cred->thread_keyring->sem); | 292 | up_write(&tsk->cred->thread_keyring->sem); |
290 | } | 293 | } |
294 | } | ||
291 | 295 | ||
292 | } /* end key_fsuid_changed() */ | ||
293 | |||
294 | /*****************************************************************************/ | ||
295 | /* | 296 | /* |
296 | * the filesystem group ID changed | 297 | * Handle the fsgid changing. |
297 | */ | 298 | */ |
298 | void key_fsgid_changed(struct task_struct *tsk) | 299 | void key_fsgid_changed(struct task_struct *tsk) |
299 | { | 300 | { |
@@ -304,20 +305,33 @@ void key_fsgid_changed(struct task_struct *tsk) | |||
304 | tsk->cred->thread_keyring->gid = tsk->cred->fsgid; | 305 | tsk->cred->thread_keyring->gid = tsk->cred->fsgid; |
305 | up_write(&tsk->cred->thread_keyring->sem); | 306 | up_write(&tsk->cred->thread_keyring->sem); |
306 | } | 307 | } |
308 | } | ||
307 | 309 | ||
308 | } /* end key_fsgid_changed() */ | ||
309 | |||
310 | /*****************************************************************************/ | ||
311 | /* | 310 | /* |
312 | * search only my process keyrings for the first matching key | 311 | * Search the process keyrings attached to the supplied cred for the first |
313 | * - we use the supplied match function to see if the description (or other | 312 | * matching key. |
314 | * feature of interest) matches | 313 | * |
315 | * - we return -EAGAIN if we didn't find any matching key | 314 | * The search criteria are the type and the match function. The description is |
316 | * - we return -ENOKEY if we found only negative matching keys | 315 | * given to the match function as a parameter, but doesn't otherwise influence |
316 | * the search. Typically the match function will compare the description | ||
317 | * parameter to the key's description. | ||
318 | * | ||
319 | * This can only search keyrings that grant Search permission to the supplied | ||
320 | * credentials. Keyrings linked to searched keyrings will also be searched if | ||
321 | * they grant Search permission too. Keys can only be found if they grant | ||
322 | * Search permission to the credentials. | ||
323 | * | ||
324 | * Returns a pointer to the key with the key usage count incremented if | ||
325 | * successful, -EAGAIN if we didn't find any matching key or -ENOKEY if we only | ||
326 | * matched negative keys. | ||
327 | * | ||
328 | * In the case of a successful return, the possession attribute is set on the | ||
329 | * returned key reference. | ||
317 | */ | 330 | */ |
318 | key_ref_t search_my_process_keyrings(struct key_type *type, | 331 | key_ref_t search_my_process_keyrings(struct key_type *type, |
319 | const void *description, | 332 | const void *description, |
320 | key_match_func_t match, | 333 | key_match_func_t match, |
334 | bool no_state_check, | ||
321 | const struct cred *cred) | 335 | const struct cred *cred) |
322 | { | 336 | { |
323 | key_ref_t key_ref, ret, err; | 337 | key_ref_t key_ref, ret, err; |
@@ -337,7 +351,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
337 | if (cred->thread_keyring) { | 351 | if (cred->thread_keyring) { |
338 | key_ref = keyring_search_aux( | 352 | key_ref = keyring_search_aux( |
339 | make_key_ref(cred->thread_keyring, 1), | 353 | make_key_ref(cred->thread_keyring, 1), |
340 | cred, type, description, match); | 354 | cred, type, description, match, no_state_check); |
341 | if (!IS_ERR(key_ref)) | 355 | if (!IS_ERR(key_ref)) |
342 | goto found; | 356 | goto found; |
343 | 357 | ||
@@ -358,7 +372,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
358 | if (cred->tgcred->process_keyring) { | 372 | if (cred->tgcred->process_keyring) { |
359 | key_ref = keyring_search_aux( | 373 | key_ref = keyring_search_aux( |
360 | make_key_ref(cred->tgcred->process_keyring, 1), | 374 | make_key_ref(cred->tgcred->process_keyring, 1), |
361 | cred, type, description, match); | 375 | cred, type, description, match, no_state_check); |
362 | if (!IS_ERR(key_ref)) | 376 | if (!IS_ERR(key_ref)) |
363 | goto found; | 377 | goto found; |
364 | 378 | ||
@@ -382,7 +396,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
382 | make_key_ref(rcu_dereference( | 396 | make_key_ref(rcu_dereference( |
383 | cred->tgcred->session_keyring), | 397 | cred->tgcred->session_keyring), |
384 | 1), | 398 | 1), |
385 | cred, type, description, match); | 399 | cred, type, description, match, no_state_check); |
386 | rcu_read_unlock(); | 400 | rcu_read_unlock(); |
387 | 401 | ||
388 | if (!IS_ERR(key_ref)) | 402 | if (!IS_ERR(key_ref)) |
@@ -404,7 +418,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
404 | else if (cred->user->session_keyring) { | 418 | else if (cred->user->session_keyring) { |
405 | key_ref = keyring_search_aux( | 419 | key_ref = keyring_search_aux( |
406 | make_key_ref(cred->user->session_keyring, 1), | 420 | make_key_ref(cred->user->session_keyring, 1), |
407 | cred, type, description, match); | 421 | cred, type, description, match, no_state_check); |
408 | if (!IS_ERR(key_ref)) | 422 | if (!IS_ERR(key_ref)) |
409 | goto found; | 423 | goto found; |
410 | 424 | ||
@@ -428,13 +442,13 @@ found: | |||
428 | return key_ref; | 442 | return key_ref; |
429 | } | 443 | } |
430 | 444 | ||
431 | /*****************************************************************************/ | ||
432 | /* | 445 | /* |
433 | * search the process keyrings for the first matching key | 446 | * Search the process keyrings attached to the supplied cred for the first |
434 | * - we use the supplied match function to see if the description (or other | 447 | * matching key in the manner of search_my_process_keyrings(), but also search |
435 | * feature of interest) matches | 448 | * the keys attached to the assumed authorisation key using its credentials if |
436 | * - we return -EAGAIN if we didn't find any matching key | 449 | * one is available. |
437 | * - we return -ENOKEY if we found only negative matching keys | 450 | * |
451 | * Return same as search_my_process_keyrings(). | ||
438 | */ | 452 | */ |
439 | key_ref_t search_process_keyrings(struct key_type *type, | 453 | key_ref_t search_process_keyrings(struct key_type *type, |
440 | const void *description, | 454 | const void *description, |
@@ -446,7 +460,8 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
446 | 460 | ||
447 | might_sleep(); | 461 | might_sleep(); |
448 | 462 | ||
449 | key_ref = search_my_process_keyrings(type, description, match, cred); | 463 | key_ref = search_my_process_keyrings(type, description, match, |
464 | false, cred); | ||
450 | if (!IS_ERR(key_ref)) | 465 | if (!IS_ERR(key_ref)) |
451 | goto found; | 466 | goto found; |
452 | err = key_ref; | 467 | err = key_ref; |
@@ -489,24 +504,33 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
489 | 504 | ||
490 | found: | 505 | found: |
491 | return key_ref; | 506 | return key_ref; |
507 | } | ||
492 | 508 | ||
493 | } /* end search_process_keyrings() */ | ||
494 | |||
495 | /*****************************************************************************/ | ||
496 | /* | 509 | /* |
497 | * see if the key we're looking at is the target key | 510 | * See if the key we're looking at is the target key. |
498 | */ | 511 | */ |
499 | int lookup_user_key_possessed(const struct key *key, const void *target) | 512 | int lookup_user_key_possessed(const struct key *key, const void *target) |
500 | { | 513 | { |
501 | return key == target; | 514 | return key == target; |
515 | } | ||
502 | 516 | ||
503 | } /* end lookup_user_key_possessed() */ | ||
504 | |||
505 | /*****************************************************************************/ | ||
506 | /* | 517 | /* |
507 | * lookup a key given a key ID from userspace with a given permissions mask | 518 | * Look up a key ID given us by userspace with a given permissions mask to get |
508 | * - don't create special keyrings unless so requested | 519 | * the key it refers to. |
509 | * - partially constructed keys aren't found unless requested | 520 | * |
521 | * Flags can be passed to request that special keyrings be created if referred | ||
522 | * to directly, to permit partially constructed keys to be found and to skip | ||
523 | * validity and permission checks on the found key. | ||
524 | * | ||
525 | * Returns a pointer to the key with an incremented usage count if successful; | ||
526 | * -EINVAL if the key ID is invalid; -ENOKEY if the key ID does not correspond | ||
527 | * to a key or the best found key was a negative key; -EKEYREVOKED or | ||
528 | * -EKEYEXPIRED if the best found key was revoked or expired; -EACCES if the | ||
529 | * found key doesn't grant the requested permit or the LSM denied access to it; | ||
530 | * or -ENOMEM if a special keyring couldn't be created. | ||
531 | * | ||
532 | * In the case of a successful return, the possession attribute is set on the | ||
533 | * returned key reference. | ||
510 | */ | 534 | */ |
511 | key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, | 535 | key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, |
512 | key_perm_t perm) | 536 | key_perm_t perm) |
@@ -711,15 +735,18 @@ invalid_key: | |||
711 | reget_creds: | 735 | reget_creds: |
712 | put_cred(cred); | 736 | put_cred(cred); |
713 | goto try_again; | 737 | goto try_again; |
738 | } | ||
714 | 739 | ||
715 | } /* end lookup_user_key() */ | ||
716 | |||
717 | /*****************************************************************************/ | ||
718 | /* | 740 | /* |
719 | * join the named keyring as the session keyring if possible, or attempt to | 741 | * Join the named keyring as the session keyring if possible else attempt to |
720 | * create a new one of that name if not | 742 | * create a new one of that name and join that. |
721 | * - if the name is NULL, an empty anonymous keyring is installed instead | 743 | * |
722 | * - named session keyring joining is done with a semaphore held | 744 | * If the name is NULL, an empty anonymous keyring will be installed as the |
745 | * session keyring. | ||
746 | * | ||
747 | * Named session keyrings are joined with a semaphore held to prevent the | ||
748 | * keyrings from going away whilst the attempt is made to going them and also | ||
749 | * to prevent a race in creating compatible session keyrings. | ||
723 | */ | 750 | */ |
724 | long join_session_keyring(const char *name) | 751 | long join_session_keyring(const char *name) |
725 | { | 752 | { |
@@ -791,8 +818,8 @@ error: | |||
791 | } | 818 | } |
792 | 819 | ||
793 | /* | 820 | /* |
794 | * Replace a process's session keyring when that process resumes userspace on | 821 | * Replace a process's session keyring on behalf of one of its children when |
795 | * behalf of one of its children | 822 | * the target process is about to resume userspace execution. |
796 | */ | 823 | */ |
797 | void key_replace_session_keyring(void) | 824 | void key_replace_session_keyring(void) |
798 | { | 825 | { |
@@ -820,6 +847,7 @@ void key_replace_session_keyring(void) | |||
820 | new-> sgid = old-> sgid; | 847 | new-> sgid = old-> sgid; |
821 | new->fsgid = old->fsgid; | 848 | new->fsgid = old->fsgid; |
822 | new->user = get_uid(old->user); | 849 | new->user = get_uid(old->user); |
850 | new->user_ns = new->user->user_ns; | ||
823 | new->group_info = get_group_info(old->group_info); | 851 | new->group_info = get_group_info(old->group_info); |
824 | 852 | ||
825 | new->securebits = old->securebits; | 853 | new->securebits = old->securebits; |