diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-16 18:40:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-16 18:40:50 -0500 |
commit | 2a74dbb9a86e8102dcd07d284135b4530a84826e (patch) | |
tree | a54403e312b6062dfb57bd904ba8b8ce3b11e720 /security/keys | |
parent | 770b6cb4d21fb3e3df2a7a51e186a3c14db1ec30 (diff) | |
parent | e93072374112db9dc86635934ee761249be28370 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"A quiet cycle for the security subsystem with just a few maintenance
updates."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
Smack: create a sysfs mount point for smackfs
Smack: use select not depends in Kconfig
Yama: remove locking from delete path
Yama: add RCU to drop read locking
drivers/char/tpm: remove tasklet and cleanup
KEYS: Use keyring_alloc() to create special keyrings
KEYS: Reduce initial permissions on keys
KEYS: Make the session and process keyrings per-thread
seccomp: Make syscall skipping and nr changes more consistent
key: Fix resource leak
keys: Fix unreachable code
KEYS: Add payload preparsing opportunity prior to key instantiate or update
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/key.c | 6 | ||||
-rw-r--r-- | security/keys/keyctl.c | 15 | ||||
-rw-r--r-- | security/keys/keyring.c | 10 | ||||
-rw-r--r-- | security/keys/process_keys.c | 92 | ||||
-rw-r--r-- | security/keys/request_key.c | 21 |
5 files changed, 69 insertions, 75 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index a15c9da8f971..8fb7c7bd4657 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -854,13 +854,13 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
854 | /* if the client doesn't provide, decide on the permissions we want */ | 854 | /* if the client doesn't provide, decide on the permissions we want */ |
855 | if (perm == KEY_PERM_UNDEF) { | 855 | if (perm == KEY_PERM_UNDEF) { |
856 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; | 856 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; |
857 | perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR; | 857 | perm |= KEY_USR_VIEW; |
858 | 858 | ||
859 | if (ktype->read) | 859 | if (ktype->read) |
860 | perm |= KEY_POS_READ | KEY_USR_READ; | 860 | perm |= KEY_POS_READ; |
861 | 861 | ||
862 | if (ktype == &key_type_keyring || ktype->update) | 862 | if (ktype == &key_type_keyring || ktype->update) |
863 | perm |= KEY_USR_WRITE; | 863 | perm |= KEY_POS_WRITE; |
864 | } | 864 | } |
865 | 865 | ||
866 | /* allocate a new key */ | 866 | /* allocate a new key */ |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 5d34b4e827d6..4b5c948eb414 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -1132,12 +1132,12 @@ long keyctl_instantiate_key_iov(key_serial_t id, | |||
1132 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, | 1132 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, |
1133 | ARRAY_SIZE(iovstack), iovstack, &iov); | 1133 | ARRAY_SIZE(iovstack), iovstack, &iov); |
1134 | if (ret < 0) | 1134 | if (ret < 0) |
1135 | return ret; | 1135 | goto err; |
1136 | if (ret == 0) | 1136 | if (ret == 0) |
1137 | goto no_payload_free; | 1137 | goto no_payload_free; |
1138 | 1138 | ||
1139 | ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); | 1139 | ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); |
1140 | 1140 | err: | |
1141 | if (iov != iovstack) | 1141 | if (iov != iovstack) |
1142 | kfree(iov); | 1142 | kfree(iov); |
1143 | return ret; | 1143 | return ret; |
@@ -1495,7 +1495,8 @@ long keyctl_session_to_parent(void) | |||
1495 | goto error_keyring; | 1495 | goto error_keyring; |
1496 | newwork = &cred->rcu; | 1496 | newwork = &cred->rcu; |
1497 | 1497 | ||
1498 | cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); | 1498 | cred->session_keyring = key_ref_to_ptr(keyring_r); |
1499 | keyring_r = NULL; | ||
1499 | init_task_work(newwork, key_change_session_keyring); | 1500 | init_task_work(newwork, key_change_session_keyring); |
1500 | 1501 | ||
1501 | me = current; | 1502 | me = current; |
@@ -1519,7 +1520,7 @@ long keyctl_session_to_parent(void) | |||
1519 | mycred = current_cred(); | 1520 | mycred = current_cred(); |
1520 | pcred = __task_cred(parent); | 1521 | pcred = __task_cred(parent); |
1521 | if (mycred == pcred || | 1522 | if (mycred == pcred || |
1522 | mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) { | 1523 | mycred->session_keyring == pcred->session_keyring) { |
1523 | ret = 0; | 1524 | ret = 0; |
1524 | goto unlock; | 1525 | goto unlock; |
1525 | } | 1526 | } |
@@ -1535,9 +1536,9 @@ long keyctl_session_to_parent(void) | |||
1535 | goto unlock; | 1536 | goto unlock; |
1536 | 1537 | ||
1537 | /* the keyrings must have the same UID */ | 1538 | /* the keyrings must have the same UID */ |
1538 | if ((pcred->tgcred->session_keyring && | 1539 | if ((pcred->session_keyring && |
1539 | !uid_eq(pcred->tgcred->session_keyring->uid, mycred->euid)) || | 1540 | !uid_eq(pcred->session_keyring->uid, mycred->euid)) || |
1540 | !uid_eq(mycred->tgcred->session_keyring->uid, mycred->euid)) | 1541 | !uid_eq(mycred->session_keyring->uid, mycred->euid)) |
1541 | goto unlock; | 1542 | goto unlock; |
1542 | 1543 | ||
1543 | /* cancel an already pending keyring replacement */ | 1544 | /* cancel an already pending keyring replacement */ |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 6e42df15a24c..6ece7f2e5707 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -257,17 +257,14 @@ error: | |||
257 | * Allocate a keyring and link into the destination keyring. | 257 | * Allocate a keyring and link into the destination keyring. |
258 | */ | 258 | */ |
259 | struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, | 259 | struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, |
260 | const struct cred *cred, unsigned long flags, | 260 | const struct cred *cred, key_perm_t perm, |
261 | struct key *dest) | 261 | unsigned long flags, struct key *dest) |
262 | { | 262 | { |
263 | struct key *keyring; | 263 | struct key *keyring; |
264 | int ret; | 264 | int ret; |
265 | 265 | ||
266 | keyring = key_alloc(&key_type_keyring, description, | 266 | keyring = key_alloc(&key_type_keyring, description, |
267 | uid, gid, cred, | 267 | uid, gid, cred, perm, flags); |
268 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | ||
269 | flags); | ||
270 | |||
271 | if (!IS_ERR(keyring)) { | 268 | if (!IS_ERR(keyring)) { |
272 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); | 269 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); |
273 | if (ret < 0) { | 270 | if (ret < 0) { |
@@ -278,6 +275,7 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, | |||
278 | 275 | ||
279 | return keyring; | 276 | return keyring; |
280 | } | 277 | } |
278 | EXPORT_SYMBOL(keyring_alloc); | ||
281 | 279 | ||
282 | /** | 280 | /** |
283 | * keyring_search_aux - Search a keyring tree for a key matching some criteria | 281 | * keyring_search_aux - Search a keyring tree for a key matching some criteria |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 86468f385fc8..58dfe0890947 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -45,10 +45,12 @@ int install_user_keyrings(void) | |||
45 | struct user_struct *user; | 45 | struct user_struct *user; |
46 | const struct cred *cred; | 46 | const struct cred *cred; |
47 | struct key *uid_keyring, *session_keyring; | 47 | struct key *uid_keyring, *session_keyring; |
48 | key_perm_t user_keyring_perm; | ||
48 | char buf[20]; | 49 | char buf[20]; |
49 | int ret; | 50 | int ret; |
50 | uid_t uid; | 51 | uid_t uid; |
51 | 52 | ||
53 | user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL; | ||
52 | cred = current_cred(); | 54 | cred = current_cred(); |
53 | user = cred->user; | 55 | user = cred->user; |
54 | uid = from_kuid(cred->user_ns, user->uid); | 56 | uid = from_kuid(cred->user_ns, user->uid); |
@@ -73,8 +75,8 @@ int install_user_keyrings(void) | |||
73 | uid_keyring = find_keyring_by_name(buf, true); | 75 | uid_keyring = find_keyring_by_name(buf, true); |
74 | if (IS_ERR(uid_keyring)) { | 76 | if (IS_ERR(uid_keyring)) { |
75 | uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, | 77 | uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, |
76 | cred, KEY_ALLOC_IN_QUOTA, | 78 | cred, user_keyring_perm, |
77 | NULL); | 79 | KEY_ALLOC_IN_QUOTA, NULL); |
78 | if (IS_ERR(uid_keyring)) { | 80 | if (IS_ERR(uid_keyring)) { |
79 | ret = PTR_ERR(uid_keyring); | 81 | ret = PTR_ERR(uid_keyring); |
80 | goto error; | 82 | goto error; |
@@ -89,7 +91,8 @@ int install_user_keyrings(void) | |||
89 | if (IS_ERR(session_keyring)) { | 91 | if (IS_ERR(session_keyring)) { |
90 | session_keyring = | 92 | session_keyring = |
91 | keyring_alloc(buf, user->uid, INVALID_GID, | 93 | keyring_alloc(buf, user->uid, INVALID_GID, |
92 | cred, KEY_ALLOC_IN_QUOTA, NULL); | 94 | cred, user_keyring_perm, |
95 | KEY_ALLOC_IN_QUOTA, NULL); | ||
93 | if (IS_ERR(session_keyring)) { | 96 | if (IS_ERR(session_keyring)) { |
94 | ret = PTR_ERR(session_keyring); | 97 | ret = PTR_ERR(session_keyring); |
95 | goto error_release; | 98 | goto error_release; |
@@ -130,6 +133,7 @@ int install_thread_keyring_to_cred(struct cred *new) | |||
130 | struct key *keyring; | 133 | struct key *keyring; |
131 | 134 | ||
132 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, | 135 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, |
136 | KEY_POS_ALL | KEY_USR_VIEW, | ||
133 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 137 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
134 | if (IS_ERR(keyring)) | 138 | if (IS_ERR(keyring)) |
135 | return PTR_ERR(keyring); | 139 | return PTR_ERR(keyring); |
@@ -170,27 +174,18 @@ static int install_thread_keyring(void) | |||
170 | int install_process_keyring_to_cred(struct cred *new) | 174 | int install_process_keyring_to_cred(struct cred *new) |
171 | { | 175 | { |
172 | struct key *keyring; | 176 | struct key *keyring; |
173 | int ret; | ||
174 | 177 | ||
175 | if (new->tgcred->process_keyring) | 178 | if (new->process_keyring) |
176 | return -EEXIST; | 179 | return -EEXIST; |
177 | 180 | ||
178 | keyring = keyring_alloc("_pid", new->uid, new->gid, | 181 | keyring = keyring_alloc("_pid", new->uid, new->gid, new, |
179 | new, KEY_ALLOC_QUOTA_OVERRUN, NULL); | 182 | KEY_POS_ALL | KEY_USR_VIEW, |
183 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | ||
180 | if (IS_ERR(keyring)) | 184 | if (IS_ERR(keyring)) |
181 | return PTR_ERR(keyring); | 185 | return PTR_ERR(keyring); |
182 | 186 | ||
183 | spin_lock_irq(&new->tgcred->lock); | 187 | new->process_keyring = keyring; |
184 | if (!new->tgcred->process_keyring) { | 188 | return 0; |
185 | new->tgcred->process_keyring = keyring; | ||
186 | keyring = NULL; | ||
187 | ret = 0; | ||
188 | } else { | ||
189 | ret = -EEXIST; | ||
190 | } | ||
191 | spin_unlock_irq(&new->tgcred->lock); | ||
192 | key_put(keyring); | ||
193 | return ret; | ||
194 | } | 189 | } |
195 | 190 | ||
196 | /* | 191 | /* |
@@ -231,11 +226,12 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) | |||
231 | /* create an empty session keyring */ | 226 | /* create an empty session keyring */ |
232 | if (!keyring) { | 227 | if (!keyring) { |
233 | flags = KEY_ALLOC_QUOTA_OVERRUN; | 228 | flags = KEY_ALLOC_QUOTA_OVERRUN; |
234 | if (cred->tgcred->session_keyring) | 229 | if (cred->session_keyring) |
235 | flags = KEY_ALLOC_IN_QUOTA; | 230 | flags = KEY_ALLOC_IN_QUOTA; |
236 | 231 | ||
237 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, | 232 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred, |
238 | cred, flags, NULL); | 233 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, |
234 | flags, NULL); | ||
239 | if (IS_ERR(keyring)) | 235 | if (IS_ERR(keyring)) |
240 | return PTR_ERR(keyring); | 236 | return PTR_ERR(keyring); |
241 | } else { | 237 | } else { |
@@ -243,17 +239,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) | |||
243 | } | 239 | } |
244 | 240 | ||
245 | /* install the keyring */ | 241 | /* install the keyring */ |
246 | spin_lock_irq(&cred->tgcred->lock); | 242 | old = cred->session_keyring; |
247 | old = cred->tgcred->session_keyring; | 243 | rcu_assign_pointer(cred->session_keyring, keyring); |
248 | rcu_assign_pointer(cred->tgcred->session_keyring, keyring); | 244 | |
249 | spin_unlock_irq(&cred->tgcred->lock); | 245 | if (old) |
250 | |||
251 | /* we're using RCU on the pointer, but there's no point synchronising | ||
252 | * on it if it didn't previously point to anything */ | ||
253 | if (old) { | ||
254 | synchronize_rcu(); | ||
255 | key_put(old); | 246 | key_put(old); |
256 | } | ||
257 | 247 | ||
258 | return 0; | 248 | return 0; |
259 | } | 249 | } |
@@ -368,9 +358,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
368 | } | 358 | } |
369 | 359 | ||
370 | /* search the process keyring second */ | 360 | /* search the process keyring second */ |
371 | if (cred->tgcred->process_keyring) { | 361 | if (cred->process_keyring) { |
372 | key_ref = keyring_search_aux( | 362 | key_ref = keyring_search_aux( |
373 | make_key_ref(cred->tgcred->process_keyring, 1), | 363 | make_key_ref(cred->process_keyring, 1), |
374 | cred, type, description, match, no_state_check); | 364 | cred, type, description, match, no_state_check); |
375 | if (!IS_ERR(key_ref)) | 365 | if (!IS_ERR(key_ref)) |
376 | goto found; | 366 | goto found; |
@@ -389,12 +379,10 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
389 | } | 379 | } |
390 | 380 | ||
391 | /* search the session keyring */ | 381 | /* search the session keyring */ |
392 | if (cred->tgcred->session_keyring) { | 382 | if (cred->session_keyring) { |
393 | rcu_read_lock(); | 383 | rcu_read_lock(); |
394 | key_ref = keyring_search_aux( | 384 | key_ref = keyring_search_aux( |
395 | make_key_ref(rcu_dereference( | 385 | make_key_ref(rcu_dereference(cred->session_keyring), 1), |
396 | cred->tgcred->session_keyring), | ||
397 | 1), | ||
398 | cred, type, description, match, no_state_check); | 386 | cred, type, description, match, no_state_check); |
399 | rcu_read_unlock(); | 387 | rcu_read_unlock(); |
400 | 388 | ||
@@ -564,7 +552,7 @@ try_again: | |||
564 | break; | 552 | break; |
565 | 553 | ||
566 | case KEY_SPEC_PROCESS_KEYRING: | 554 | case KEY_SPEC_PROCESS_KEYRING: |
567 | if (!cred->tgcred->process_keyring) { | 555 | if (!cred->process_keyring) { |
568 | if (!(lflags & KEY_LOOKUP_CREATE)) | 556 | if (!(lflags & KEY_LOOKUP_CREATE)) |
569 | goto error; | 557 | goto error; |
570 | 558 | ||
@@ -576,13 +564,13 @@ try_again: | |||
576 | goto reget_creds; | 564 | goto reget_creds; |
577 | } | 565 | } |
578 | 566 | ||
579 | key = cred->tgcred->process_keyring; | 567 | key = cred->process_keyring; |
580 | atomic_inc(&key->usage); | 568 | atomic_inc(&key->usage); |
581 | key_ref = make_key_ref(key, 1); | 569 | key_ref = make_key_ref(key, 1); |
582 | break; | 570 | break; |
583 | 571 | ||
584 | case KEY_SPEC_SESSION_KEYRING: | 572 | case KEY_SPEC_SESSION_KEYRING: |
585 | if (!cred->tgcred->session_keyring) { | 573 | if (!cred->session_keyring) { |
586 | /* always install a session keyring upon access if one | 574 | /* always install a session keyring upon access if one |
587 | * doesn't exist yet */ | 575 | * doesn't exist yet */ |
588 | ret = install_user_keyrings(); | 576 | ret = install_user_keyrings(); |
@@ -597,7 +585,7 @@ try_again: | |||
597 | if (ret < 0) | 585 | if (ret < 0) |
598 | goto error; | 586 | goto error; |
599 | goto reget_creds; | 587 | goto reget_creds; |
600 | } else if (cred->tgcred->session_keyring == | 588 | } else if (cred->session_keyring == |
601 | cred->user->session_keyring && | 589 | cred->user->session_keyring && |
602 | lflags & KEY_LOOKUP_CREATE) { | 590 | lflags & KEY_LOOKUP_CREATE) { |
603 | ret = join_session_keyring(NULL); | 591 | ret = join_session_keyring(NULL); |
@@ -607,7 +595,7 @@ try_again: | |||
607 | } | 595 | } |
608 | 596 | ||
609 | rcu_read_lock(); | 597 | rcu_read_lock(); |
610 | key = rcu_dereference(cred->tgcred->session_keyring); | 598 | key = rcu_dereference(cred->session_keyring); |
611 | atomic_inc(&key->usage); | 599 | atomic_inc(&key->usage); |
612 | rcu_read_unlock(); | 600 | rcu_read_unlock(); |
613 | key_ref = make_key_ref(key, 1); | 601 | key_ref = make_key_ref(key, 1); |
@@ -767,12 +755,6 @@ long join_session_keyring(const char *name) | |||
767 | struct key *keyring; | 755 | struct key *keyring; |
768 | long ret, serial; | 756 | long ret, serial; |
769 | 757 | ||
770 | /* only permit this if there's a single thread in the thread group - | ||
771 | * this avoids us having to adjust the creds on all threads and risking | ||
772 | * ENOMEM */ | ||
773 | if (!current_is_single_threaded()) | ||
774 | return -EMLINK; | ||
775 | |||
776 | new = prepare_creds(); | 758 | new = prepare_creds(); |
777 | if (!new) | 759 | if (!new) |
778 | return -ENOMEM; | 760 | return -ENOMEM; |
@@ -784,7 +766,7 @@ long join_session_keyring(const char *name) | |||
784 | if (ret < 0) | 766 | if (ret < 0) |
785 | goto error; | 767 | goto error; |
786 | 768 | ||
787 | serial = new->tgcred->session_keyring->serial; | 769 | serial = new->session_keyring->serial; |
788 | ret = commit_creds(new); | 770 | ret = commit_creds(new); |
789 | if (ret == 0) | 771 | if (ret == 0) |
790 | ret = serial; | 772 | ret = serial; |
@@ -798,8 +780,10 @@ long join_session_keyring(const char *name) | |||
798 | keyring = find_keyring_by_name(name, false); | 780 | keyring = find_keyring_by_name(name, false); |
799 | if (PTR_ERR(keyring) == -ENOKEY) { | 781 | if (PTR_ERR(keyring) == -ENOKEY) { |
800 | /* not found - try and create a new one */ | 782 | /* not found - try and create a new one */ |
801 | keyring = keyring_alloc(name, old->uid, old->gid, old, | 783 | keyring = keyring_alloc( |
802 | KEY_ALLOC_IN_QUOTA, NULL); | 784 | name, old->uid, old->gid, old, |
785 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK, | ||
786 | KEY_ALLOC_IN_QUOTA, NULL); | ||
803 | if (IS_ERR(keyring)) { | 787 | if (IS_ERR(keyring)) { |
804 | ret = PTR_ERR(keyring); | 788 | ret = PTR_ERR(keyring); |
805 | goto error2; | 789 | goto error2; |
@@ -807,6 +791,9 @@ long join_session_keyring(const char *name) | |||
807 | } else if (IS_ERR(keyring)) { | 791 | } else if (IS_ERR(keyring)) { |
808 | ret = PTR_ERR(keyring); | 792 | ret = PTR_ERR(keyring); |
809 | goto error2; | 793 | goto error2; |
794 | } else if (keyring == new->session_keyring) { | ||
795 | ret = 0; | ||
796 | goto error2; | ||
810 | } | 797 | } |
811 | 798 | ||
812 | /* we've got a keyring - now to install it */ | 799 | /* we've got a keyring - now to install it */ |
@@ -863,8 +850,7 @@ void key_change_session_keyring(struct callback_head *twork) | |||
863 | 850 | ||
864 | new->jit_keyring = old->jit_keyring; | 851 | new->jit_keyring = old->jit_keyring; |
865 | new->thread_keyring = key_get(old->thread_keyring); | 852 | new->thread_keyring = key_get(old->thread_keyring); |
866 | new->tgcred->tgid = old->tgcred->tgid; | 853 | new->process_keyring = key_get(old->process_keyring); |
867 | new->tgcred->process_keyring = key_get(old->tgcred->process_keyring); | ||
868 | 854 | ||
869 | security_transfer_creds(new, old); | 855 | security_transfer_creds(new, old); |
870 | 856 | ||
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 66e21184b559..4bd6bdb74193 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -126,6 +126,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
126 | 126 | ||
127 | cred = get_current_cred(); | 127 | cred = get_current_cred(); |
128 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, | 128 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, |
129 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, | ||
129 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 130 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
130 | put_cred(cred); | 131 | put_cred(cred); |
131 | if (IS_ERR(keyring)) { | 132 | if (IS_ERR(keyring)) { |
@@ -150,12 +151,12 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
150 | cred->thread_keyring ? cred->thread_keyring->serial : 0); | 151 | cred->thread_keyring ? cred->thread_keyring->serial : 0); |
151 | 152 | ||
152 | prkey = 0; | 153 | prkey = 0; |
153 | if (cred->tgcred->process_keyring) | 154 | if (cred->process_keyring) |
154 | prkey = cred->tgcred->process_keyring->serial; | 155 | prkey = cred->process_keyring->serial; |
155 | sprintf(keyring_str[1], "%d", prkey); | 156 | sprintf(keyring_str[1], "%d", prkey); |
156 | 157 | ||
157 | rcu_read_lock(); | 158 | rcu_read_lock(); |
158 | session = rcu_dereference(cred->tgcred->session_keyring); | 159 | session = rcu_dereference(cred->session_keyring); |
159 | if (!session) | 160 | if (!session) |
160 | session = cred->user->session_keyring; | 161 | session = cred->user->session_keyring; |
161 | sskey = session->serial; | 162 | sskey = session->serial; |
@@ -297,14 +298,14 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) | |||
297 | break; | 298 | break; |
298 | 299 | ||
299 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | 300 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: |
300 | dest_keyring = key_get(cred->tgcred->process_keyring); | 301 | dest_keyring = key_get(cred->process_keyring); |
301 | if (dest_keyring) | 302 | if (dest_keyring) |
302 | break; | 303 | break; |
303 | 304 | ||
304 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | 305 | case KEY_REQKEY_DEFL_SESSION_KEYRING: |
305 | rcu_read_lock(); | 306 | rcu_read_lock(); |
306 | dest_keyring = key_get( | 307 | dest_keyring = key_get( |
307 | rcu_dereference(cred->tgcred->session_keyring)); | 308 | rcu_dereference(cred->session_keyring)); |
308 | rcu_read_unlock(); | 309 | rcu_read_unlock(); |
309 | 310 | ||
310 | if (dest_keyring) | 311 | if (dest_keyring) |
@@ -347,6 +348,7 @@ static int construct_alloc_key(struct key_type *type, | |||
347 | const struct cred *cred = current_cred(); | 348 | const struct cred *cred = current_cred(); |
348 | unsigned long prealloc; | 349 | unsigned long prealloc; |
349 | struct key *key; | 350 | struct key *key; |
351 | key_perm_t perm; | ||
350 | key_ref_t key_ref; | 352 | key_ref_t key_ref; |
351 | int ret; | 353 | int ret; |
352 | 354 | ||
@@ -355,8 +357,15 @@ static int construct_alloc_key(struct key_type *type, | |||
355 | *_key = NULL; | 357 | *_key = NULL; |
356 | mutex_lock(&user->cons_lock); | 358 | mutex_lock(&user->cons_lock); |
357 | 359 | ||
360 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; | ||
361 | perm |= KEY_USR_VIEW; | ||
362 | if (type->read) | ||
363 | perm |= KEY_POS_READ; | ||
364 | if (type == &key_type_keyring || type->update) | ||
365 | perm |= KEY_POS_WRITE; | ||
366 | |||
358 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, | 367 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, |
359 | KEY_POS_ALL, flags); | 368 | perm, flags); |
360 | if (IS_ERR(key)) | 369 | if (IS_ERR(key)) |
361 | goto alloc_failed; | 370 | goto alloc_failed; |
362 | 371 | ||