diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/keys/internal.h | 4 | ||||
-rw-r--r-- | security/keys/key.c | 45 | ||||
-rw-r--r-- | security/keys/keyring.c | 19 | ||||
-rw-r--r-- | security/keys/process_keys.c | 142 | ||||
-rw-r--r-- | security/selinux/hooks.c | 8 |
5 files changed, 92 insertions, 126 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h index 6361d3736dbc..2ab38854c47f 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -77,8 +77,6 @@ extern struct mutex key_construction_mutex; | |||
77 | extern wait_queue_head_t request_key_conswq; | 77 | extern wait_queue_head_t request_key_conswq; |
78 | 78 | ||
79 | 79 | ||
80 | extern void keyring_publish_name(struct key *keyring); | ||
81 | |||
82 | extern int __key_link(struct key *keyring, struct key *key); | 80 | extern int __key_link(struct key *keyring, struct key *key); |
83 | 81 | ||
84 | extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, | 82 | extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, |
@@ -102,7 +100,7 @@ extern key_ref_t search_process_keyrings(struct key_type *type, | |||
102 | key_match_func_t match, | 100 | key_match_func_t match, |
103 | struct task_struct *tsk); | 101 | struct task_struct *tsk); |
104 | 102 | ||
105 | extern struct key *find_keyring_by_name(const char *name, key_serial_t bound); | 103 | extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); |
106 | 104 | ||
107 | extern int install_thread_keyring(struct task_struct *tsk); | 105 | extern int install_thread_keyring(struct task_struct *tsk); |
108 | extern int install_process_keyring(struct task_struct *tsk); | 106 | extern int install_process_keyring(struct task_struct *tsk); |
diff --git a/security/keys/key.c b/security/keys/key.c index d98c61953be6..46f125aa7fa3 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* Basic authentication token and access key management | 1 | /* Basic authentication token and access key management |
2 | * | 2 | * |
3 | * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -139,36 +139,6 @@ void key_user_put(struct key_user *user) | |||
139 | 139 | ||
140 | /*****************************************************************************/ | 140 | /*****************************************************************************/ |
141 | /* | 141 | /* |
142 | * insert a key with a fixed serial number | ||
143 | */ | ||
144 | static void __init __key_insert_serial(struct key *key) | ||
145 | { | ||
146 | struct rb_node *parent, **p; | ||
147 | struct key *xkey; | ||
148 | |||
149 | parent = NULL; | ||
150 | p = &key_serial_tree.rb_node; | ||
151 | |||
152 | while (*p) { | ||
153 | parent = *p; | ||
154 | xkey = rb_entry(parent, struct key, serial_node); | ||
155 | |||
156 | if (key->serial < xkey->serial) | ||
157 | p = &(*p)->rb_left; | ||
158 | else if (key->serial > xkey->serial) | ||
159 | p = &(*p)->rb_right; | ||
160 | else | ||
161 | BUG(); | ||
162 | } | ||
163 | |||
164 | /* we've found a suitable hole - arrange for this key to occupy it */ | ||
165 | rb_link_node(&key->serial_node, parent, p); | ||
166 | rb_insert_color(&key->serial_node, &key_serial_tree); | ||
167 | |||
168 | } /* end __key_insert_serial() */ | ||
169 | |||
170 | /*****************************************************************************/ | ||
171 | /* | ||
172 | * assign a key the next unique serial number | 142 | * assign a key the next unique serial number |
173 | * - these are assigned randomly to avoid security issues through covert | 143 | * - these are assigned randomly to avoid security issues through covert |
174 | * channel problems | 144 | * channel problems |
@@ -1020,17 +990,4 @@ void __init key_init(void) | |||
1020 | rb_insert_color(&root_key_user.node, | 990 | rb_insert_color(&root_key_user.node, |
1021 | &key_user_tree); | 991 | &key_user_tree); |
1022 | 992 | ||
1023 | /* record root's user standard keyrings */ | ||
1024 | key_check(&root_user_keyring); | ||
1025 | key_check(&root_session_keyring); | ||
1026 | |||
1027 | __key_insert_serial(&root_user_keyring); | ||
1028 | __key_insert_serial(&root_session_keyring); | ||
1029 | |||
1030 | keyring_publish_name(&root_user_keyring); | ||
1031 | keyring_publish_name(&root_session_keyring); | ||
1032 | |||
1033 | /* link the two root keyrings together */ | ||
1034 | key_link(&root_session_keyring, &root_user_keyring); | ||
1035 | |||
1036 | } /* end key_init() */ | 993 | } /* end key_init() */ |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 70f0c313c888..a9ab8affc092 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* keyring.c: keyring handling | 1 | /* Keyring handling |
2 | * | 2 | * |
3 | * Copyright (C) 2004-5 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) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -79,7 +79,7 @@ static DECLARE_RWSEM(keyring_serialise_link_sem); | |||
79 | * publish the name of a keyring so that it can be found by name (if it has | 79 | * publish the name of a keyring so that it can be found by name (if it has |
80 | * one) | 80 | * one) |
81 | */ | 81 | */ |
82 | void keyring_publish_name(struct key *keyring) | 82 | static void keyring_publish_name(struct key *keyring) |
83 | { | 83 | { |
84 | int bucket; | 84 | int bucket; |
85 | 85 | ||
@@ -516,10 +516,9 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, | |||
516 | /* | 516 | /* |
517 | * find a keyring with the specified name | 517 | * find a keyring with the specified name |
518 | * - all named keyrings are searched | 518 | * - all named keyrings are searched |
519 | * - only find keyrings with search permission for the process | 519 | * - normally only finds keyrings with search permission for the current process |
520 | * - only find keyrings with a serial number greater than the one specified | ||
521 | */ | 520 | */ |
522 | struct key *find_keyring_by_name(const char *name, key_serial_t bound) | 521 | struct key *find_keyring_by_name(const char *name, bool skip_perm_check) |
523 | { | 522 | { |
524 | struct key *keyring; | 523 | struct key *keyring; |
525 | int bucket; | 524 | int bucket; |
@@ -545,15 +544,11 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound) | |||
545 | if (strcmp(keyring->description, name) != 0) | 544 | if (strcmp(keyring->description, name) != 0) |
546 | continue; | 545 | continue; |
547 | 546 | ||
548 | if (key_permission(make_key_ref(keyring, 0), | 547 | if (!skip_perm_check && |
548 | key_permission(make_key_ref(keyring, 0), | ||
549 | KEY_SEARCH) < 0) | 549 | KEY_SEARCH) < 0) |
550 | continue; | 550 | continue; |
551 | 551 | ||
552 | /* found a potential candidate, but we still need to | ||
553 | * check the serial number */ | ||
554 | if (keyring->serial <= bound) | ||
555 | continue; | ||
556 | |||
557 | /* we've got a match */ | 552 | /* we've got a match */ |
558 | atomic_inc(&keyring->usage); | 553 | atomic_inc(&keyring->usage); |
559 | read_unlock(&keyring_name_lock); | 554 | read_unlock(&keyring_name_lock); |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index c886a2bb792a..5be6d018759a 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* process_keys.c: management of a process's keyrings | 1 | /* Management of a process's keyrings |
2 | * | 2 | * |
3 | * Copyright (C) 2004-5 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) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -23,6 +23,9 @@ | |||
23 | /* session keyring create vs join semaphore */ | 23 | /* session keyring create vs join semaphore */ |
24 | static DEFINE_MUTEX(key_session_mutex); | 24 | static DEFINE_MUTEX(key_session_mutex); |
25 | 25 | ||
26 | /* user keyring creation semaphore */ | ||
27 | static DEFINE_MUTEX(key_user_keyring_mutex); | ||
28 | |||
26 | /* the root user's tracking struct */ | 29 | /* the root user's tracking struct */ |
27 | struct key_user root_key_user = { | 30 | struct key_user root_key_user = { |
28 | .usage = ATOMIC_INIT(3), | 31 | .usage = ATOMIC_INIT(3), |
@@ -33,78 +36,84 @@ struct key_user root_key_user = { | |||
33 | .uid = 0, | 36 | .uid = 0, |
34 | }; | 37 | }; |
35 | 38 | ||
36 | /* the root user's UID keyring */ | ||
37 | struct key root_user_keyring = { | ||
38 | .usage = ATOMIC_INIT(1), | ||
39 | .serial = 2, | ||
40 | .type = &key_type_keyring, | ||
41 | .user = &root_key_user, | ||
42 | .sem = __RWSEM_INITIALIZER(root_user_keyring.sem), | ||
43 | .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | ||
44 | .flags = 1 << KEY_FLAG_INSTANTIATED, | ||
45 | .description = "_uid.0", | ||
46 | #ifdef KEY_DEBUGGING | ||
47 | .magic = KEY_DEBUG_MAGIC, | ||
48 | #endif | ||
49 | }; | ||
50 | |||
51 | /* the root user's default session keyring */ | ||
52 | struct key root_session_keyring = { | ||
53 | .usage = ATOMIC_INIT(1), | ||
54 | .serial = 1, | ||
55 | .type = &key_type_keyring, | ||
56 | .user = &root_key_user, | ||
57 | .sem = __RWSEM_INITIALIZER(root_session_keyring.sem), | ||
58 | .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | ||
59 | .flags = 1 << KEY_FLAG_INSTANTIATED, | ||
60 | .description = "_uid_ses.0", | ||
61 | #ifdef KEY_DEBUGGING | ||
62 | .magic = KEY_DEBUG_MAGIC, | ||
63 | #endif | ||
64 | }; | ||
65 | |||
66 | /*****************************************************************************/ | 39 | /*****************************************************************************/ |
67 | /* | 40 | /* |
68 | * allocate the keyrings to be associated with a UID | 41 | * install user and user session keyrings for a particular UID |
69 | */ | 42 | */ |
70 | int alloc_uid_keyring(struct user_struct *user, | 43 | static int install_user_keyrings(struct task_struct *tsk) |
71 | struct task_struct *ctx) | ||
72 | { | 44 | { |
45 | struct user_struct *user = tsk->user; | ||
73 | struct key *uid_keyring, *session_keyring; | 46 | struct key *uid_keyring, *session_keyring; |
74 | char buf[20]; | 47 | char buf[20]; |
75 | int ret; | 48 | int ret; |
76 | 49 | ||
77 | /* concoct a default session keyring */ | 50 | kenter("%p{%u}", user, user->uid); |
78 | sprintf(buf, "_uid_ses.%u", user->uid); | ||
79 | 51 | ||
80 | session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, | 52 | if (user->uid_keyring) { |
81 | KEY_ALLOC_IN_QUOTA, NULL); | 53 | kleave(" = 0 [exist]"); |
82 | if (IS_ERR(session_keyring)) { | 54 | return 0; |
83 | ret = PTR_ERR(session_keyring); | ||
84 | goto error; | ||
85 | } | 55 | } |
86 | 56 | ||
87 | /* and a UID specific keyring, pointed to by the default session | 57 | mutex_lock(&key_user_keyring_mutex); |
88 | * keyring */ | 58 | ret = 0; |
89 | sprintf(buf, "_uid.%u", user->uid); | ||
90 | 59 | ||
91 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, | 60 | if (!user->uid_keyring) { |
92 | KEY_ALLOC_IN_QUOTA, session_keyring); | 61 | /* get the UID-specific keyring |
93 | if (IS_ERR(uid_keyring)) { | 62 | * - there may be one in existence already as it may have been |
94 | key_put(session_keyring); | 63 | * pinned by a session, but the user_struct pointing to it |
95 | ret = PTR_ERR(uid_keyring); | 64 | * may have been destroyed by setuid */ |
96 | goto error; | 65 | sprintf(buf, "_uid.%u", user->uid); |
66 | |||
67 | uid_keyring = find_keyring_by_name(buf, true); | ||
68 | if (IS_ERR(uid_keyring)) { | ||
69 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, | ||
70 | tsk, KEY_ALLOC_IN_QUOTA, | ||
71 | NULL); | ||
72 | if (IS_ERR(uid_keyring)) { | ||
73 | ret = PTR_ERR(uid_keyring); | ||
74 | goto error; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | /* get a default session keyring (which might also exist | ||
79 | * already) */ | ||
80 | sprintf(buf, "_uid_ses.%u", user->uid); | ||
81 | |||
82 | session_keyring = find_keyring_by_name(buf, true); | ||
83 | if (IS_ERR(session_keyring)) { | ||
84 | session_keyring = | ||
85 | keyring_alloc(buf, user->uid, (gid_t) -1, | ||
86 | tsk, KEY_ALLOC_IN_QUOTA, NULL); | ||
87 | if (IS_ERR(session_keyring)) { | ||
88 | ret = PTR_ERR(session_keyring); | ||
89 | goto error_release; | ||
90 | } | ||
91 | |||
92 | /* we install a link from the user session keyring to | ||
93 | * the user keyring */ | ||
94 | ret = key_link(session_keyring, uid_keyring); | ||
95 | if (ret < 0) | ||
96 | goto error_release_both; | ||
97 | } | ||
98 | |||
99 | /* install the keyrings */ | ||
100 | user->uid_keyring = uid_keyring; | ||
101 | user->session_keyring = session_keyring; | ||
97 | } | 102 | } |
98 | 103 | ||
99 | /* install the keyrings */ | 104 | mutex_unlock(&key_user_keyring_mutex); |
100 | user->uid_keyring = uid_keyring; | 105 | kleave(" = 0"); |
101 | user->session_keyring = session_keyring; | 106 | return 0; |
102 | ret = 0; | ||
103 | 107 | ||
108 | error_release_both: | ||
109 | key_put(session_keyring); | ||
110 | error_release: | ||
111 | key_put(uid_keyring); | ||
104 | error: | 112 | error: |
113 | mutex_unlock(&key_user_keyring_mutex); | ||
114 | kleave(" = %d", ret); | ||
105 | return ret; | 115 | return ret; |
106 | 116 | } | |
107 | } /* end alloc_uid_keyring() */ | ||
108 | 117 | ||
109 | /*****************************************************************************/ | 118 | /*****************************************************************************/ |
110 | /* | 119 | /* |
@@ -481,7 +490,7 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
481 | } | 490 | } |
482 | } | 491 | } |
483 | /* or search the user-session keyring */ | 492 | /* or search the user-session keyring */ |
484 | else { | 493 | else if (context->user->session_keyring) { |
485 | key_ref = keyring_search_aux( | 494 | key_ref = keyring_search_aux( |
486 | make_key_ref(context->user->session_keyring, 1), | 495 | make_key_ref(context->user->session_keyring, 1), |
487 | context, type, description, match); | 496 | context, type, description, match); |
@@ -614,6 +623,9 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, | |||
614 | if (!context->signal->session_keyring) { | 623 | if (!context->signal->session_keyring) { |
615 | /* always install a session keyring upon access if one | 624 | /* always install a session keyring upon access if one |
616 | * doesn't exist yet */ | 625 | * doesn't exist yet */ |
626 | ret = install_user_keyrings(context); | ||
627 | if (ret < 0) | ||
628 | goto error; | ||
617 | ret = install_session_keyring( | 629 | ret = install_session_keyring( |
618 | context, context->user->session_keyring); | 630 | context, context->user->session_keyring); |
619 | if (ret < 0) | 631 | if (ret < 0) |
@@ -628,12 +640,24 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, | |||
628 | break; | 640 | break; |
629 | 641 | ||
630 | case KEY_SPEC_USER_KEYRING: | 642 | case KEY_SPEC_USER_KEYRING: |
643 | if (!context->user->uid_keyring) { | ||
644 | ret = install_user_keyrings(context); | ||
645 | if (ret < 0) | ||
646 | goto error; | ||
647 | } | ||
648 | |||
631 | key = context->user->uid_keyring; | 649 | key = context->user->uid_keyring; |
632 | atomic_inc(&key->usage); | 650 | atomic_inc(&key->usage); |
633 | key_ref = make_key_ref(key, 1); | 651 | key_ref = make_key_ref(key, 1); |
634 | break; | 652 | break; |
635 | 653 | ||
636 | case KEY_SPEC_USER_SESSION_KEYRING: | 654 | case KEY_SPEC_USER_SESSION_KEYRING: |
655 | if (!context->user->session_keyring) { | ||
656 | ret = install_user_keyrings(context); | ||
657 | if (ret < 0) | ||
658 | goto error; | ||
659 | } | ||
660 | |||
637 | key = context->user->session_keyring; | 661 | key = context->user->session_keyring; |
638 | atomic_inc(&key->usage); | 662 | atomic_inc(&key->usage); |
639 | key_ref = make_key_ref(key, 1); | 663 | key_ref = make_key_ref(key, 1); |
@@ -744,7 +768,7 @@ long join_session_keyring(const char *name) | |||
744 | mutex_lock(&key_session_mutex); | 768 | mutex_lock(&key_session_mutex); |
745 | 769 | ||
746 | /* look for an existing keyring of this name */ | 770 | /* look for an existing keyring of this name */ |
747 | keyring = find_keyring_by_name(name, 0); | 771 | keyring = find_keyring_by_name(name, false); |
748 | if (PTR_ERR(keyring) == -ENOKEY) { | 772 | if (PTR_ERR(keyring) == -ENOKEY) { |
749 | /* not found - try and create a new one */ | 773 | /* not found - try and create a new one */ |
750 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, | 774 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 838d1e5e63a1..4e4de98941ae 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -5551,14 +5551,6 @@ static __init int selinux_init(void) | |||
5551 | else | 5551 | else |
5552 | printk(KERN_DEBUG "SELinux: Starting in permissive mode\n"); | 5552 | printk(KERN_DEBUG "SELinux: Starting in permissive mode\n"); |
5553 | 5553 | ||
5554 | #ifdef CONFIG_KEYS | ||
5555 | /* Add security information to initial keyrings */ | ||
5556 | selinux_key_alloc(&root_user_keyring, current, | ||
5557 | KEY_ALLOC_NOT_IN_QUOTA); | ||
5558 | selinux_key_alloc(&root_session_keyring, current, | ||
5559 | KEY_ALLOC_NOT_IN_QUOTA); | ||
5560 | #endif | ||
5561 | |||
5562 | return 0; | 5554 | return 0; |
5563 | } | 5555 | } |
5564 | 5556 | ||