diff options
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/gc.c | 6 | ||||
-rw-r--r-- | security/keys/keyctl.c | 12 | ||||
-rw-r--r-- | security/keys/keyring.c | 45 | ||||
-rw-r--r-- | security/keys/proc.c | 1 | ||||
-rw-r--r-- | security/keys/process_keys.c | 1 | ||||
-rw-r--r-- | security/keys/request_key.c | 24 | ||||
-rw-r--r-- | security/keys/sysctl.c | 17 | ||||
-rw-r--r-- | security/keys/user_defined.c | 3 |
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 | ||
92 | unlock_dont_gc: | ||
93 | rcu_read_unlock(); | ||
91 | dont_gc: | 94 | dont_gc: |
92 | kleave(" = false"); | 95 | kleave(" = false"); |
93 | return false; | 96 | return false; |
94 | 97 | ||
95 | do_gc: | 98 | do_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 | */ |
1237 | long keyctl_session_to_parent(void) | 1237 | long 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: | |||
1326 | error_keyring: | 1327 | error_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 | 571 | out: | |
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 | */ |
990 | static void keyring_revoke(struct key *keyring) | 993 | static 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 | ||
337 | key_already_present: | 340 | key_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 | ||
18 | ctl_table key_sysctls[] = { | 18 | ctl_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 */ |