diff options
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r-- | security/keys/process_keys.c | 135 |
1 files changed, 80 insertions, 55 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 504bdd2452bd..930634e45149 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 | { |
@@ -214,7 +218,7 @@ static int install_process_keyring(void) | |||
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,16 +305,28 @@ 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, |
@@ -428,13 +441,13 @@ found: | |||
428 | return key_ref; | 441 | return key_ref; |
429 | } | 442 | } |
430 | 443 | ||
431 | /*****************************************************************************/ | ||
432 | /* | 444 | /* |
433 | * search the process keyrings for the first matching key | 445 | * 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 | 446 | * matching key in the manner of search_my_process_keyrings(), but also search |
435 | * feature of interest) matches | 447 | * the keys attached to the assumed authorisation key using its credentials if |
436 | * - we return -EAGAIN if we didn't find any matching key | 448 | * one is available. |
437 | * - we return -ENOKEY if we found only negative matching keys | 449 | * |
450 | * Return same as search_my_process_keyrings(). | ||
438 | */ | 451 | */ |
439 | key_ref_t search_process_keyrings(struct key_type *type, | 452 | key_ref_t search_process_keyrings(struct key_type *type, |
440 | const void *description, | 453 | const void *description, |
@@ -489,24 +502,33 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
489 | 502 | ||
490 | found: | 503 | found: |
491 | return key_ref; | 504 | return key_ref; |
505 | } | ||
492 | 506 | ||
493 | } /* end search_process_keyrings() */ | ||
494 | |||
495 | /*****************************************************************************/ | ||
496 | /* | 507 | /* |
497 | * see if the key we're looking at is the target key | 508 | * See if the key we're looking at is the target key. |
498 | */ | 509 | */ |
499 | int lookup_user_key_possessed(const struct key *key, const void *target) | 510 | int lookup_user_key_possessed(const struct key *key, const void *target) |
500 | { | 511 | { |
501 | return key == target; | 512 | return key == target; |
513 | } | ||
502 | 514 | ||
503 | } /* end lookup_user_key_possessed() */ | ||
504 | |||
505 | /*****************************************************************************/ | ||
506 | /* | 515 | /* |
507 | * lookup a key given a key ID from userspace with a given permissions mask | 516 | * 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 | 517 | * the key it refers to. |
509 | * - partially constructed keys aren't found unless requested | 518 | * |
519 | * Flags can be passed to request that special keyrings be created if referred | ||
520 | * to directly, to permit partially constructed keys to be found and to skip | ||
521 | * validity and permission checks on the found key. | ||
522 | * | ||
523 | * Returns a pointer to the key with an incremented usage count if successful; | ||
524 | * -EINVAL if the key ID is invalid; -ENOKEY if the key ID does not correspond | ||
525 | * to a key or the best found key was a negative key; -EKEYREVOKED or | ||
526 | * -EKEYEXPIRED if the best found key was revoked or expired; -EACCES if the | ||
527 | * found key doesn't grant the requested permit or the LSM denied access to it; | ||
528 | * or -ENOMEM if a special keyring couldn't be created. | ||
529 | * | ||
530 | * In the case of a successful return, the possession attribute is set on the | ||
531 | * returned key reference. | ||
510 | */ | 532 | */ |
511 | key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, | 533 | key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, |
512 | key_perm_t perm) | 534 | key_perm_t perm) |
@@ -711,15 +733,18 @@ invalid_key: | |||
711 | reget_creds: | 733 | reget_creds: |
712 | put_cred(cred); | 734 | put_cred(cred); |
713 | goto try_again; | 735 | goto try_again; |
736 | } | ||
714 | 737 | ||
715 | } /* end lookup_user_key() */ | ||
716 | |||
717 | /*****************************************************************************/ | ||
718 | /* | 738 | /* |
719 | * join the named keyring as the session keyring if possible, or attempt to | 739 | * Join the named keyring as the session keyring if possible else attempt to |
720 | * create a new one of that name if not | 740 | * create a new one of that name and join that. |
721 | * - if the name is NULL, an empty anonymous keyring is installed instead | 741 | * |
722 | * - named session keyring joining is done with a semaphore held | 742 | * If the name is NULL, an empty anonymous keyring will be installed as the |
743 | * session keyring. | ||
744 | * | ||
745 | * Named session keyrings are joined with a semaphore held to prevent the | ||
746 | * keyrings from going away whilst the attempt is made to going them and also | ||
747 | * to prevent a race in creating compatible session keyrings. | ||
723 | */ | 748 | */ |
724 | long join_session_keyring(const char *name) | 749 | long join_session_keyring(const char *name) |
725 | { | 750 | { |
@@ -791,8 +816,8 @@ error: | |||
791 | } | 816 | } |
792 | 817 | ||
793 | /* | 818 | /* |
794 | * Replace a process's session keyring when that process resumes userspace on | 819 | * Replace a process's session keyring on behalf of one of its children when |
795 | * behalf of one of its children | 820 | * the target process is about to resume userspace execution. |
796 | */ | 821 | */ |
797 | void key_replace_session_keyring(void) | 822 | void key_replace_session_keyring(void) |
798 | { | 823 | { |