aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/gc.c6
-rw-r--r--security/keys/keyctl.c12
-rw-r--r--security/keys/keyring.c45
-rw-r--r--security/keys/proc.c1
-rw-r--r--security/keys/process_keys.c1
-rw-r--r--security/keys/request_key.c24
-rw-r--r--security/keys/sysctl.c17
-rw-r--r--security/keys/user_defined.c3
8 files changed, 66 insertions, 43 deletions
diff --git a/security/keys/gc.c b/security/keys/gc.c
index 4770be375ffe..a46e825cbf02 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -77,9 +77,10 @@ static bool key_gc_keyring(struct key *keyring, time_t limit)
77 goto dont_gc; 77 goto dont_gc;
78 78
79 /* scan the keyring looking for dead keys */ 79 /* scan the keyring looking for dead keys */
80 rcu_read_lock();
80 klist = rcu_dereference(keyring->payload.subscriptions); 81 klist = rcu_dereference(keyring->payload.subscriptions);
81 if (!klist) 82 if (!klist)
82 goto dont_gc; 83 goto unlock_dont_gc;
83 84
84 for (loop = klist->nkeys - 1; loop >= 0; loop--) { 85 for (loop = klist->nkeys - 1; loop >= 0; loop--) {
85 key = klist->keys[loop]; 86 key = klist->keys[loop];
@@ -88,11 +89,14 @@ static bool key_gc_keyring(struct key *keyring, time_t limit)
88 goto do_gc; 89 goto do_gc;
89 } 90 }
90 91
92unlock_dont_gc:
93 rcu_read_unlock();
91dont_gc: 94dont_gc:
92 kleave(" = false"); 95 kleave(" = false");
93 return false; 96 return false;
94 97
95do_gc: 98do_gc:
99 rcu_read_unlock();
96 key_gc_cursor = keyring->serial; 100 key_gc_cursor = keyring->serial;
97 key_get(keyring); 101 key_get(keyring);
98 spin_unlock(&key_serial_lock); 102 spin_unlock(&key_serial_lock);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 06ec722897be..e9c2e7c584d9 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1194,7 +1194,7 @@ long keyctl_get_security(key_serial_t keyid,
1194 * have the authorisation token handy */ 1194 * have the authorisation token handy */
1195 instkey = key_get_instantiation_authkey(keyid); 1195 instkey = key_get_instantiation_authkey(keyid);
1196 if (IS_ERR(instkey)) 1196 if (IS_ERR(instkey))
1197 return PTR_ERR(key_ref); 1197 return PTR_ERR(instkey);
1198 key_put(instkey); 1198 key_put(instkey);
1199 1199
1200 key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0); 1200 key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0);
@@ -1236,6 +1236,7 @@ long keyctl_get_security(key_serial_t keyid,
1236 */ 1236 */
1237long keyctl_session_to_parent(void) 1237long keyctl_session_to_parent(void)
1238{ 1238{
1239#ifdef TIF_NOTIFY_RESUME
1239 struct task_struct *me, *parent; 1240 struct task_struct *me, *parent;
1240 const struct cred *mycred, *pcred; 1241 const struct cred *mycred, *pcred;
1241 struct cred *cred, *oldcred; 1242 struct cred *cred, *oldcred;
@@ -1326,6 +1327,15 @@ not_permitted:
1326error_keyring: 1327error_keyring:
1327 key_ref_put(keyring_r); 1328 key_ref_put(keyring_r);
1328 return ret; 1329 return ret;
1330
1331#else /* !TIF_NOTIFY_RESUME */
1332 /*
1333 * To be removed when TIF_NOTIFY_RESUME has been implemented on
1334 * m68k/xtensa
1335 */
1336#warning TIF_NOTIFY_RESUME not implemented
1337 return -EOPNOTSUPP;
1338#endif /* !TIF_NOTIFY_RESUME */
1329} 1339}
1330 1340
1331/*****************************************************************************/ 1341/*****************************************************************************/
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 8ec02746ca99..1e4b0037935c 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -20,6 +20,11 @@
20#include <asm/uaccess.h> 20#include <asm/uaccess.h>
21#include "internal.h" 21#include "internal.h"
22 22
23#define rcu_dereference_locked_keyring(keyring) \
24 (rcu_dereference_protected( \
25 (keyring)->payload.subscriptions, \
26 rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem)))
27
23/* 28/*
24 * when plumbing the depths of the key tree, this sets a hard limit set on how 29 * when plumbing the depths of the key tree, this sets a hard limit set on how
25 * deep we're willing to go 30 * deep we're willing to go
@@ -151,7 +156,9 @@ static void keyring_destroy(struct key *keyring)
151 write_unlock(&keyring_name_lock); 156 write_unlock(&keyring_name_lock);
152 } 157 }
153 158
154 klist = rcu_dereference(keyring->payload.subscriptions); 159 klist = rcu_dereference_check(keyring->payload.subscriptions,
160 rcu_read_lock_held() ||
161 atomic_read(&keyring->usage) == 0);
155 if (klist) { 162 if (klist) {
156 for (loop = klist->nkeys - 1; loop >= 0; loop--) 163 for (loop = klist->nkeys - 1; loop >= 0; loop--)
157 key_put(klist->keys[loop]); 164 key_put(klist->keys[loop]);
@@ -199,8 +206,7 @@ static long keyring_read(const struct key *keyring,
199 int loop, ret; 206 int loop, ret;
200 207
201 ret = 0; 208 ret = 0;
202 klist = rcu_dereference(keyring->payload.subscriptions); 209 klist = rcu_dereference_locked_keyring(keyring);
203
204 if (klist) { 210 if (klist) {
205 /* calculate how much data we could return */ 211 /* calculate how much data we could return */
206 qty = klist->nkeys * sizeof(key_serial_t); 212 qty = klist->nkeys * sizeof(key_serial_t);
@@ -524,9 +530,8 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
524 struct key *keyring; 530 struct key *keyring;
525 int bucket; 531 int bucket;
526 532
527 keyring = ERR_PTR(-EINVAL);
528 if (!name) 533 if (!name)
529 goto error; 534 return ERR_PTR(-EINVAL);
530 535
531 bucket = keyring_hash(name); 536 bucket = keyring_hash(name);
532 537
@@ -553,17 +558,18 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
553 KEY_SEARCH) < 0) 558 KEY_SEARCH) < 0)
554 continue; 559 continue;
555 560
556 /* we've got a match */ 561 /* we've got a match but we might end up racing with
557 atomic_inc(&keyring->usage); 562 * key_cleanup() if the keyring is currently 'dead'
558 read_unlock(&keyring_name_lock); 563 * (ie. it has a zero usage count) */
559 goto error; 564 if (!atomic_inc_not_zero(&keyring->usage))
565 continue;
566 goto out;
560 } 567 }
561 } 568 }
562 569
563 read_unlock(&keyring_name_lock);
564 keyring = ERR_PTR(-ENOKEY); 570 keyring = ERR_PTR(-ENOKEY);
565 571out:
566 error: 572 read_unlock(&keyring_name_lock);
567 return keyring; 573 return keyring;
568 574
569} /* end find_keyring_by_name() */ 575} /* end find_keyring_by_name() */
@@ -718,8 +724,7 @@ int __key_link(struct key *keyring, struct key *key)
718 } 724 }
719 725
720 /* see if there's a matching key we can displace */ 726 /* see if there's a matching key we can displace */
721 klist = keyring->payload.subscriptions; 727 klist = rcu_dereference_locked_keyring(keyring);
722
723 if (klist && klist->nkeys > 0) { 728 if (klist && klist->nkeys > 0) {
724 struct key_type *type = key->type; 729 struct key_type *type = key->type;
725 730
@@ -763,8 +768,6 @@ int __key_link(struct key *keyring, struct key *key)
763 if (ret < 0) 768 if (ret < 0)
764 goto error2; 769 goto error2;
765 770
766 klist = keyring->payload.subscriptions;
767
768 if (klist && klist->nkeys < klist->maxkeys) { 771 if (klist && klist->nkeys < klist->maxkeys) {
769 /* there's sufficient slack space to add directly */ 772 /* there's sufficient slack space to add directly */
770 atomic_inc(&key->usage); 773 atomic_inc(&key->usage);
@@ -866,7 +869,7 @@ int key_unlink(struct key *keyring, struct key *key)
866 869
867 down_write(&keyring->sem); 870 down_write(&keyring->sem);
868 871
869 klist = keyring->payload.subscriptions; 872 klist = rcu_dereference_locked_keyring(keyring);
870 if (klist) { 873 if (klist) {
871 /* search the keyring for the key */ 874 /* search the keyring for the key */
872 for (loop = 0; loop < klist->nkeys; loop++) 875 for (loop = 0; loop < klist->nkeys; loop++)
@@ -957,7 +960,7 @@ int keyring_clear(struct key *keyring)
957 /* detach the pointer block with the locks held */ 960 /* detach the pointer block with the locks held */
958 down_write(&keyring->sem); 961 down_write(&keyring->sem);
959 962
960 klist = keyring->payload.subscriptions; 963 klist = rcu_dereference_locked_keyring(keyring);
961 if (klist) { 964 if (klist) {
962 /* adjust the quota */ 965 /* adjust the quota */
963 key_payload_reserve(keyring, 966 key_payload_reserve(keyring,
@@ -989,7 +992,9 @@ EXPORT_SYMBOL(keyring_clear);
989 */ 992 */
990static void keyring_revoke(struct key *keyring) 993static void keyring_revoke(struct key *keyring)
991{ 994{
992 struct keyring_list *klist = keyring->payload.subscriptions; 995 struct keyring_list *klist;
996
997 klist = rcu_dereference_locked_keyring(keyring);
993 998
994 /* adjust the quota */ 999 /* adjust the quota */
995 key_payload_reserve(keyring, 0); 1000 key_payload_reserve(keyring, 0);
@@ -1023,7 +1028,7 @@ void keyring_gc(struct key *keyring, time_t limit)
1023 1028
1024 down_write(&keyring->sem); 1029 down_write(&keyring->sem);
1025 1030
1026 klist = keyring->payload.subscriptions; 1031 klist = rcu_dereference_locked_keyring(keyring);
1027 if (!klist) 1032 if (!klist)
1028 goto no_klist; 1033 goto no_klist;
1029 1034
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 9d01021ca0c8..706d63f4f185 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -12,7 +12,6 @@
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/slab.h>
16#include <linux/fs.h> 15#include <linux/fs.h>
17#include <linux/proc_fs.h> 16#include <linux/proc_fs.h>
18#include <linux/seq_file.h> 17#include <linux/seq_file.h>
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 5c23afb31ece..06c2ccf26ed3 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -12,7 +12,6 @@
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/slab.h>
16#include <linux/keyctl.h> 15#include <linux/keyctl.h>
17#include <linux/fs.h> 16#include <linux/fs.h>
18#include <linux/err.h> 17#include <linux/err.h>
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 03fe63ed55bd..d8c1a6a0fb08 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -68,7 +68,8 @@ static int call_sbin_request_key(struct key_construction *cons,
68{ 68{
69 const struct cred *cred = current_cred(); 69 const struct cred *cred = current_cred();
70 key_serial_t prkey, sskey; 70 key_serial_t prkey, sskey;
71 struct key *key = cons->key, *authkey = cons->authkey, *keyring; 71 struct key *key = cons->key, *authkey = cons->authkey, *keyring,
72 *session;
72 char *argv[9], *envp[3], uid_str[12], gid_str[12]; 73 char *argv[9], *envp[3], uid_str[12], gid_str[12];
73 char key_str[12], keyring_str[3][12]; 74 char key_str[12], keyring_str[3][12];
74 char desc[20]; 75 char desc[20];
@@ -93,7 +94,7 @@ static int call_sbin_request_key(struct key_construction *cons,
93 } 94 }
94 95
95 /* attach the auth key to the session keyring */ 96 /* attach the auth key to the session keyring */
96 ret = __key_link(keyring, authkey); 97 ret = key_link(keyring, authkey);
97 if (ret < 0) 98 if (ret < 0)
98 goto error_link; 99 goto error_link;
99 100
@@ -112,10 +113,12 @@ static int call_sbin_request_key(struct key_construction *cons,
112 if (cred->tgcred->process_keyring) 113 if (cred->tgcred->process_keyring)
113 prkey = cred->tgcred->process_keyring->serial; 114 prkey = cred->tgcred->process_keyring->serial;
114 115
115 if (cred->tgcred->session_keyring) 116 rcu_read_lock();
116 sskey = rcu_dereference(cred->tgcred->session_keyring)->serial; 117 session = rcu_dereference(cred->tgcred->session_keyring);
117 else 118 if (!session)
118 sskey = cred->user->session_keyring->serial; 119 session = cred->user->session_keyring;
120 sskey = session->serial;
121 rcu_read_unlock();
119 122
120 sprintf(keyring_str[2], "%d", sskey); 123 sprintf(keyring_str[2], "%d", sskey);
121 124
@@ -336,8 +339,10 @@ static int construct_alloc_key(struct key_type *type,
336 339
337key_already_present: 340key_already_present:
338 mutex_unlock(&key_construction_mutex); 341 mutex_unlock(&key_construction_mutex);
339 if (dest_keyring) 342 if (dest_keyring) {
343 __key_link(dest_keyring, key_ref_to_ptr(key_ref));
340 up_write(&dest_keyring->sem); 344 up_write(&dest_keyring->sem);
345 }
341 mutex_unlock(&user->cons_lock); 346 mutex_unlock(&user->cons_lock);
342 key_put(key); 347 key_put(key);
343 *_key = key = key_ref_to_ptr(key_ref); 348 *_key = key = key_ref_to_ptr(key_ref);
@@ -428,6 +433,11 @@ struct key *request_key_and_link(struct key_type *type,
428 433
429 if (!IS_ERR(key_ref)) { 434 if (!IS_ERR(key_ref)) {
430 key = key_ref_to_ptr(key_ref); 435 key = key_ref_to_ptr(key_ref);
436 if (dest_keyring) {
437 construct_get_dest_keyring(&dest_keyring);
438 key_link(dest_keyring, key);
439 key_put(dest_keyring);
440 }
431 } else if (PTR_ERR(key_ref) != -EAGAIN) { 441 } else if (PTR_ERR(key_ref) != -EAGAIN) {
432 key = ERR_CAST(key_ref); 442 key = ERR_CAST(key_ref);
433 } else { 443 } else {
diff --git a/security/keys/sysctl.c b/security/keys/sysctl.c
index 5e05dc09e2db..ee32d181764a 100644
--- a/security/keys/sysctl.c
+++ b/security/keys/sysctl.c
@@ -17,54 +17,49 @@ static const int zero, one = 1, max = INT_MAX;
17 17
18ctl_table key_sysctls[] = { 18ctl_table key_sysctls[] = {
19 { 19 {
20 .ctl_name = CTL_UNNUMBERED,
21 .procname = "maxkeys", 20 .procname = "maxkeys",
22 .data = &key_quota_maxkeys, 21 .data = &key_quota_maxkeys,
23 .maxlen = sizeof(unsigned), 22 .maxlen = sizeof(unsigned),
24 .mode = 0644, 23 .mode = 0644,
25 .proc_handler = &proc_dointvec_minmax, 24 .proc_handler = proc_dointvec_minmax,
26 .extra1 = (void *) &one, 25 .extra1 = (void *) &one,
27 .extra2 = (void *) &max, 26 .extra2 = (void *) &max,
28 }, 27 },
29 { 28 {
30 .ctl_name = CTL_UNNUMBERED,
31 .procname = "maxbytes", 29 .procname = "maxbytes",
32 .data = &key_quota_maxbytes, 30 .data = &key_quota_maxbytes,
33 .maxlen = sizeof(unsigned), 31 .maxlen = sizeof(unsigned),
34 .mode = 0644, 32 .mode = 0644,
35 .proc_handler = &proc_dointvec_minmax, 33 .proc_handler = proc_dointvec_minmax,
36 .extra1 = (void *) &one, 34 .extra1 = (void *) &one,
37 .extra2 = (void *) &max, 35 .extra2 = (void *) &max,
38 }, 36 },
39 { 37 {
40 .ctl_name = CTL_UNNUMBERED,
41 .procname = "root_maxkeys", 38 .procname = "root_maxkeys",
42 .data = &key_quota_root_maxkeys, 39 .data = &key_quota_root_maxkeys,
43 .maxlen = sizeof(unsigned), 40 .maxlen = sizeof(unsigned),
44 .mode = 0644, 41 .mode = 0644,
45 .proc_handler = &proc_dointvec_minmax, 42 .proc_handler = proc_dointvec_minmax,
46 .extra1 = (void *) &one, 43 .extra1 = (void *) &one,
47 .extra2 = (void *) &max, 44 .extra2 = (void *) &max,
48 }, 45 },
49 { 46 {
50 .ctl_name = CTL_UNNUMBERED,
51 .procname = "root_maxbytes", 47 .procname = "root_maxbytes",
52 .data = &key_quota_root_maxbytes, 48 .data = &key_quota_root_maxbytes,
53 .maxlen = sizeof(unsigned), 49 .maxlen = sizeof(unsigned),
54 .mode = 0644, 50 .mode = 0644,
55 .proc_handler = &proc_dointvec_minmax, 51 .proc_handler = proc_dointvec_minmax,
56 .extra1 = (void *) &one, 52 .extra1 = (void *) &one,
57 .extra2 = (void *) &max, 53 .extra2 = (void *) &max,
58 }, 54 },
59 { 55 {
60 .ctl_name = CTL_UNNUMBERED,
61 .procname = "gc_delay", 56 .procname = "gc_delay",
62 .data = &key_gc_delay, 57 .data = &key_gc_delay,
63 .maxlen = sizeof(unsigned), 58 .maxlen = sizeof(unsigned),
64 .mode = 0644, 59 .mode = 0644,
65 .proc_handler = &proc_dointvec_minmax, 60 .proc_handler = proc_dointvec_minmax,
66 .extra1 = (void *) &zero, 61 .extra1 = (void *) &zero,
67 .extra2 = (void *) &max, 62 .extra2 = (void *) &max,
68 }, 63 },
69 { .ctl_name = 0 } 64 { }
70}; 65};
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 7c687d568221..e9aa07929656 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -199,7 +199,8 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
199 struct user_key_payload *upayload; 199 struct user_key_payload *upayload;
200 long ret; 200 long ret;
201 201
202 upayload = rcu_dereference(key->payload.data); 202 upayload = rcu_dereference_protected(
203 key->payload.data, rwsem_is_locked(&((struct key *)key)->sem));
203 ret = upayload->datalen; 204 ret = upayload->datalen;
204 205
205 /* we can return the data as is */ 206 /* we can return the data as is */