diff options
author | Jiri Kosina <jkosina@suse.cz> | 2012-10-28 14:28:52 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2012-10-28 14:29:19 -0400 |
commit | 3bd7bf1f0fe14f591c089ae61bbfa9bd356f178a (patch) | |
tree | 0058693cc9e70b7461dae551f8a19aff2efd13ca /security/keys | |
parent | f16f84937d769c893492160b1a8c3672e3992beb (diff) | |
parent | e657e078d3dfa9f96976db7a2b5fd7d7c9f1f1a6 (diff) |
Merge branch 'master' into for-next
Sync up with Linus' tree to be able to apply Cesar's patch
against newer version of the code.
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/encrypted-keys/encrypted.c | 16 | ||||
-rw-r--r-- | security/keys/gc.c | 8 | ||||
-rw-r--r-- | security/keys/internal.h | 6 | ||||
-rw-r--r-- | security/keys/key.c | 139 | ||||
-rw-r--r-- | security/keys/keyctl.c | 70 | ||||
-rw-r--r-- | security/keys/keyring.c | 10 | ||||
-rw-r--r-- | security/keys/permission.c | 14 | ||||
-rw-r--r-- | security/keys/proc.c | 44 | ||||
-rw-r--r-- | security/keys/process_keys.c | 15 | ||||
-rw-r--r-- | security/keys/request_key.c | 6 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 8 | ||||
-rw-r--r-- | security/keys/trusted.c | 70 | ||||
-rw-r--r-- | security/keys/user_defined.c | 14 |
13 files changed, 225 insertions, 195 deletions
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 2d1bb8af7696..9e1e005c7596 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c | |||
@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, | |||
773 | * | 773 | * |
774 | * On success, return 0. Otherwise return errno. | 774 | * On success, return 0. Otherwise return errno. |
775 | */ | 775 | */ |
776 | static int encrypted_instantiate(struct key *key, const void *data, | 776 | static int encrypted_instantiate(struct key *key, |
777 | size_t datalen) | 777 | struct key_preparsed_payload *prep) |
778 | { | 778 | { |
779 | struct encrypted_key_payload *epayload = NULL; | 779 | struct encrypted_key_payload *epayload = NULL; |
780 | char *datablob = NULL; | 780 | char *datablob = NULL; |
@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
782 | char *master_desc = NULL; | 782 | char *master_desc = NULL; |
783 | char *decrypted_datalen = NULL; | 783 | char *decrypted_datalen = NULL; |
784 | char *hex_encoded_iv = NULL; | 784 | char *hex_encoded_iv = NULL; |
785 | size_t datalen = prep->datalen; | ||
785 | int ret; | 786 | int ret; |
786 | 787 | ||
787 | if (datalen <= 0 || datalen > 32767 || !data) | 788 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
788 | return -EINVAL; | 789 | return -EINVAL; |
789 | 790 | ||
790 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 791 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
791 | if (!datablob) | 792 | if (!datablob) |
792 | return -ENOMEM; | 793 | return -ENOMEM; |
793 | datablob[datalen] = 0; | 794 | datablob[datalen] = 0; |
794 | memcpy(datablob, data, datalen); | 795 | memcpy(datablob, prep->data, datalen); |
795 | ret = datablob_parse(datablob, &format, &master_desc, | 796 | ret = datablob_parse(datablob, &format, &master_desc, |
796 | &decrypted_datalen, &hex_encoded_iv); | 797 | &decrypted_datalen, &hex_encoded_iv); |
797 | if (ret < 0) | 798 | if (ret < 0) |
@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu) | |||
834 | * | 835 | * |
835 | * On success, return 0. Otherwise return errno. | 836 | * On success, return 0. Otherwise return errno. |
836 | */ | 837 | */ |
837 | static int encrypted_update(struct key *key, const void *data, size_t datalen) | 838 | static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) |
838 | { | 839 | { |
839 | struct encrypted_key_payload *epayload = key->payload.data; | 840 | struct encrypted_key_payload *epayload = key->payload.data; |
840 | struct encrypted_key_payload *new_epayload; | 841 | struct encrypted_key_payload *new_epayload; |
841 | char *buf; | 842 | char *buf; |
842 | char *new_master_desc = NULL; | 843 | char *new_master_desc = NULL; |
843 | const char *format = NULL; | 844 | const char *format = NULL; |
845 | size_t datalen = prep->datalen; | ||
844 | int ret = 0; | 846 | int ret = 0; |
845 | 847 | ||
846 | if (datalen <= 0 || datalen > 32767 || !data) | 848 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
847 | return -EINVAL; | 849 | return -EINVAL; |
848 | 850 | ||
849 | buf = kmalloc(datalen + 1, GFP_KERNEL); | 851 | buf = kmalloc(datalen + 1, GFP_KERNEL); |
@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) | |||
851 | return -ENOMEM; | 853 | return -ENOMEM; |
852 | 854 | ||
853 | buf[datalen] = 0; | 855 | buf[datalen] = 0; |
854 | memcpy(buf, data, datalen); | 856 | memcpy(buf, prep->data, datalen); |
855 | ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); | 857 | ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); |
856 | if (ret < 0) | 858 | if (ret < 0) |
857 | goto out; | 859 | goto out; |
diff --git a/security/keys/gc.c b/security/keys/gc.c index 61ab7c82ebb1..d67c97bb1025 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c | |||
@@ -62,7 +62,7 @@ void key_schedule_gc(time_t gc_at) | |||
62 | 62 | ||
63 | if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) { | 63 | if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) { |
64 | kdebug("IMMEDIATE"); | 64 | kdebug("IMMEDIATE"); |
65 | queue_work(system_nrt_wq, &key_gc_work); | 65 | schedule_work(&key_gc_work); |
66 | } else if (gc_at < key_gc_next_run) { | 66 | } else if (gc_at < key_gc_next_run) { |
67 | kdebug("DEFERRED"); | 67 | kdebug("DEFERRED"); |
68 | key_gc_next_run = gc_at; | 68 | key_gc_next_run = gc_at; |
@@ -77,7 +77,7 @@ void key_schedule_gc(time_t gc_at) | |||
77 | void key_schedule_gc_links(void) | 77 | void key_schedule_gc_links(void) |
78 | { | 78 | { |
79 | set_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags); | 79 | set_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags); |
80 | queue_work(system_nrt_wq, &key_gc_work); | 80 | schedule_work(&key_gc_work); |
81 | } | 81 | } |
82 | 82 | ||
83 | /* | 83 | /* |
@@ -120,7 +120,7 @@ void key_gc_keytype(struct key_type *ktype) | |||
120 | set_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags); | 120 | set_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags); |
121 | 121 | ||
122 | kdebug("schedule"); | 122 | kdebug("schedule"); |
123 | queue_work(system_nrt_wq, &key_gc_work); | 123 | schedule_work(&key_gc_work); |
124 | 124 | ||
125 | kdebug("sleep"); | 125 | kdebug("sleep"); |
126 | wait_on_bit(&key_gc_flags, KEY_GC_REAPING_KEYTYPE, key_gc_wait_bit, | 126 | wait_on_bit(&key_gc_flags, KEY_GC_REAPING_KEYTYPE, key_gc_wait_bit, |
@@ -369,7 +369,7 @@ maybe_resched: | |||
369 | } | 369 | } |
370 | 370 | ||
371 | if (gc_state & KEY_GC_REAP_AGAIN) | 371 | if (gc_state & KEY_GC_REAP_AGAIN) |
372 | queue_work(system_nrt_wq, &key_gc_work); | 372 | schedule_work(&key_gc_work); |
373 | kleave(" [end %x]", gc_state); | 373 | kleave(" [end %x]", gc_state); |
374 | return; | 374 | return; |
375 | 375 | ||
diff --git a/security/keys/internal.h b/security/keys/internal.h index 22ff05269e3d..8bbefc3b55d4 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -52,8 +52,7 @@ struct key_user { | |||
52 | atomic_t usage; /* for accessing qnkeys & qnbytes */ | 52 | atomic_t usage; /* for accessing qnkeys & qnbytes */ |
53 | atomic_t nkeys; /* number of keys */ | 53 | atomic_t nkeys; /* number of keys */ |
54 | atomic_t nikeys; /* number of instantiated keys */ | 54 | atomic_t nikeys; /* number of instantiated keys */ |
55 | uid_t uid; | 55 | kuid_t uid; |
56 | struct user_namespace *user_ns; | ||
57 | int qnkeys; /* number of keys allocated to this user */ | 56 | int qnkeys; /* number of keys allocated to this user */ |
58 | int qnbytes; /* number of bytes allocated to this user */ | 57 | int qnbytes; /* number of bytes allocated to this user */ |
59 | }; | 58 | }; |
@@ -62,8 +61,7 @@ extern struct rb_root key_user_tree; | |||
62 | extern spinlock_t key_user_lock; | 61 | extern spinlock_t key_user_lock; |
63 | extern struct key_user root_key_user; | 62 | extern struct key_user root_key_user; |
64 | 63 | ||
65 | extern struct key_user *key_user_lookup(uid_t uid, | 64 | extern struct key_user *key_user_lookup(kuid_t uid); |
66 | struct user_namespace *user_ns); | ||
67 | extern void key_user_put(struct key_user *user); | 65 | extern void key_user_put(struct key_user *user); |
68 | 66 | ||
69 | /* | 67 | /* |
diff --git a/security/keys/key.c b/security/keys/key.c index 50d96d4e06f2..a15c9da8f971 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/workqueue.h> | 18 | #include <linux/workqueue.h> |
19 | #include <linux/random.h> | 19 | #include <linux/random.h> |
20 | #include <linux/err.h> | 20 | #include <linux/err.h> |
21 | #include <linux/user_namespace.h> | ||
22 | #include "internal.h" | 21 | #include "internal.h" |
23 | 22 | ||
24 | struct kmem_cache *key_jar; | 23 | struct kmem_cache *key_jar; |
@@ -52,7 +51,7 @@ void __key_check(const struct key *key) | |||
52 | * Get the key quota record for a user, allocating a new record if one doesn't | 51 | * Get the key quota record for a user, allocating a new record if one doesn't |
53 | * already exist. | 52 | * already exist. |
54 | */ | 53 | */ |
55 | struct key_user *key_user_lookup(uid_t uid, struct user_namespace *user_ns) | 54 | struct key_user *key_user_lookup(kuid_t uid) |
56 | { | 55 | { |
57 | struct key_user *candidate = NULL, *user; | 56 | struct key_user *candidate = NULL, *user; |
58 | struct rb_node *parent = NULL; | 57 | struct rb_node *parent = NULL; |
@@ -67,13 +66,9 @@ try_again: | |||
67 | parent = *p; | 66 | parent = *p; |
68 | user = rb_entry(parent, struct key_user, node); | 67 | user = rb_entry(parent, struct key_user, node); |
69 | 68 | ||
70 | if (uid < user->uid) | 69 | if (uid_lt(uid, user->uid)) |
71 | p = &(*p)->rb_left; | 70 | p = &(*p)->rb_left; |
72 | else if (uid > user->uid) | 71 | else if (uid_gt(uid, user->uid)) |
73 | p = &(*p)->rb_right; | ||
74 | else if (user_ns < user->user_ns) | ||
75 | p = &(*p)->rb_left; | ||
76 | else if (user_ns > user->user_ns) | ||
77 | p = &(*p)->rb_right; | 72 | p = &(*p)->rb_right; |
78 | else | 73 | else |
79 | goto found; | 74 | goto found; |
@@ -102,7 +97,6 @@ try_again: | |||
102 | atomic_set(&candidate->nkeys, 0); | 97 | atomic_set(&candidate->nkeys, 0); |
103 | atomic_set(&candidate->nikeys, 0); | 98 | atomic_set(&candidate->nikeys, 0); |
104 | candidate->uid = uid; | 99 | candidate->uid = uid; |
105 | candidate->user_ns = get_user_ns(user_ns); | ||
106 | candidate->qnkeys = 0; | 100 | candidate->qnkeys = 0; |
107 | candidate->qnbytes = 0; | 101 | candidate->qnbytes = 0; |
108 | spin_lock_init(&candidate->lock); | 102 | spin_lock_init(&candidate->lock); |
@@ -131,7 +125,6 @@ void key_user_put(struct key_user *user) | |||
131 | if (atomic_dec_and_lock(&user->usage, &key_user_lock)) { | 125 | if (atomic_dec_and_lock(&user->usage, &key_user_lock)) { |
132 | rb_erase(&user->node, &key_user_tree); | 126 | rb_erase(&user->node, &key_user_tree); |
133 | spin_unlock(&key_user_lock); | 127 | spin_unlock(&key_user_lock); |
134 | put_user_ns(user->user_ns); | ||
135 | 128 | ||
136 | kfree(user); | 129 | kfree(user); |
137 | } | 130 | } |
@@ -229,7 +222,7 @@ serial_exists: | |||
229 | * key_alloc() calls don't race with module unloading. | 222 | * key_alloc() calls don't race with module unloading. |
230 | */ | 223 | */ |
231 | struct key *key_alloc(struct key_type *type, const char *desc, | 224 | struct key *key_alloc(struct key_type *type, const char *desc, |
232 | uid_t uid, gid_t gid, const struct cred *cred, | 225 | kuid_t uid, kgid_t gid, const struct cred *cred, |
233 | key_perm_t perm, unsigned long flags) | 226 | key_perm_t perm, unsigned long flags) |
234 | { | 227 | { |
235 | struct key_user *user = NULL; | 228 | struct key_user *user = NULL; |
@@ -253,16 +246,16 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
253 | quotalen = desclen + type->def_datalen; | 246 | quotalen = desclen + type->def_datalen; |
254 | 247 | ||
255 | /* get hold of the key tracking for this user */ | 248 | /* get hold of the key tracking for this user */ |
256 | user = key_user_lookup(uid, cred->user_ns); | 249 | user = key_user_lookup(uid); |
257 | if (!user) | 250 | if (!user) |
258 | goto no_memory_1; | 251 | goto no_memory_1; |
259 | 252 | ||
260 | /* check that the user's quota permits allocation of another key and | 253 | /* check that the user's quota permits allocation of another key and |
261 | * its description */ | 254 | * its description */ |
262 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { | 255 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { |
263 | unsigned maxkeys = (uid == 0) ? | 256 | unsigned maxkeys = uid_eq(uid, GLOBAL_ROOT_UID) ? |
264 | key_quota_root_maxkeys : key_quota_maxkeys; | 257 | key_quota_root_maxkeys : key_quota_maxkeys; |
265 | unsigned maxbytes = (uid == 0) ? | 258 | unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ? |
266 | key_quota_root_maxbytes : key_quota_maxbytes; | 259 | key_quota_root_maxbytes : key_quota_maxbytes; |
267 | 260 | ||
268 | spin_lock(&user->lock); | 261 | spin_lock(&user->lock); |
@@ -380,7 +373,7 @@ int key_payload_reserve(struct key *key, size_t datalen) | |||
380 | 373 | ||
381 | /* contemplate the quota adjustment */ | 374 | /* contemplate the quota adjustment */ |
382 | if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { | 375 | if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
383 | unsigned maxbytes = (key->user->uid == 0) ? | 376 | unsigned maxbytes = uid_eq(key->user->uid, GLOBAL_ROOT_UID) ? |
384 | key_quota_root_maxbytes : key_quota_maxbytes; | 377 | key_quota_root_maxbytes : key_quota_maxbytes; |
385 | 378 | ||
386 | spin_lock(&key->user->lock); | 379 | spin_lock(&key->user->lock); |
@@ -412,8 +405,7 @@ EXPORT_SYMBOL(key_payload_reserve); | |||
412 | * key_construction_mutex. | 405 | * key_construction_mutex. |
413 | */ | 406 | */ |
414 | static int __key_instantiate_and_link(struct key *key, | 407 | static int __key_instantiate_and_link(struct key *key, |
415 | const void *data, | 408 | struct key_preparsed_payload *prep, |
416 | size_t datalen, | ||
417 | struct key *keyring, | 409 | struct key *keyring, |
418 | struct key *authkey, | 410 | struct key *authkey, |
419 | unsigned long *_prealloc) | 411 | unsigned long *_prealloc) |
@@ -431,7 +423,7 @@ static int __key_instantiate_and_link(struct key *key, | |||
431 | /* can't instantiate twice */ | 423 | /* can't instantiate twice */ |
432 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 424 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
433 | /* instantiate the key */ | 425 | /* instantiate the key */ |
434 | ret = key->type->instantiate(key, data, datalen); | 426 | ret = key->type->instantiate(key, prep); |
435 | 427 | ||
436 | if (ret == 0) { | 428 | if (ret == 0) { |
437 | /* mark the key as being instantiated */ | 429 | /* mark the key as being instantiated */ |
@@ -482,22 +474,37 @@ int key_instantiate_and_link(struct key *key, | |||
482 | struct key *keyring, | 474 | struct key *keyring, |
483 | struct key *authkey) | 475 | struct key *authkey) |
484 | { | 476 | { |
477 | struct key_preparsed_payload prep; | ||
485 | unsigned long prealloc; | 478 | unsigned long prealloc; |
486 | int ret; | 479 | int ret; |
487 | 480 | ||
481 | memset(&prep, 0, sizeof(prep)); | ||
482 | prep.data = data; | ||
483 | prep.datalen = datalen; | ||
484 | prep.quotalen = key->type->def_datalen; | ||
485 | if (key->type->preparse) { | ||
486 | ret = key->type->preparse(&prep); | ||
487 | if (ret < 0) | ||
488 | goto error; | ||
489 | } | ||
490 | |||
488 | if (keyring) { | 491 | if (keyring) { |
489 | ret = __key_link_begin(keyring, key->type, key->description, | 492 | ret = __key_link_begin(keyring, key->type, key->description, |
490 | &prealloc); | 493 | &prealloc); |
491 | if (ret < 0) | 494 | if (ret < 0) |
492 | return ret; | 495 | goto error_free_preparse; |
493 | } | 496 | } |
494 | 497 | ||
495 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, | 498 | ret = __key_instantiate_and_link(key, &prep, keyring, authkey, |
496 | &prealloc); | 499 | &prealloc); |
497 | 500 | ||
498 | if (keyring) | 501 | if (keyring) |
499 | __key_link_end(keyring, key->type, prealloc); | 502 | __key_link_end(keyring, key->type, prealloc); |
500 | 503 | ||
504 | error_free_preparse: | ||
505 | if (key->type->preparse) | ||
506 | key->type->free_preparse(&prep); | ||
507 | error: | ||
501 | return ret; | 508 | return ret; |
502 | } | 509 | } |
503 | 510 | ||
@@ -598,7 +605,7 @@ void key_put(struct key *key) | |||
598 | key_check(key); | 605 | key_check(key); |
599 | 606 | ||
600 | if (atomic_dec_and_test(&key->usage)) | 607 | if (atomic_dec_and_test(&key->usage)) |
601 | queue_work(system_nrt_wq, &key_gc_work); | 608 | schedule_work(&key_gc_work); |
602 | } | 609 | } |
603 | } | 610 | } |
604 | EXPORT_SYMBOL(key_put); | 611 | EXPORT_SYMBOL(key_put); |
@@ -706,7 +713,7 @@ void key_type_put(struct key_type *ktype) | |||
706 | * if we get an error. | 713 | * if we get an error. |
707 | */ | 714 | */ |
708 | static inline key_ref_t __key_update(key_ref_t key_ref, | 715 | static inline key_ref_t __key_update(key_ref_t key_ref, |
709 | const void *payload, size_t plen) | 716 | struct key_preparsed_payload *prep) |
710 | { | 717 | { |
711 | struct key *key = key_ref_to_ptr(key_ref); | 718 | struct key *key = key_ref_to_ptr(key_ref); |
712 | int ret; | 719 | int ret; |
@@ -722,7 +729,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, | |||
722 | 729 | ||
723 | down_write(&key->sem); | 730 | down_write(&key->sem); |
724 | 731 | ||
725 | ret = key->type->update(key, payload, plen); | 732 | ret = key->type->update(key, prep); |
726 | if (ret == 0) | 733 | if (ret == 0) |
727 | /* updating a negative key instantiates it */ | 734 | /* updating a negative key instantiates it */ |
728 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | 735 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |
@@ -774,6 +781,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
774 | unsigned long flags) | 781 | unsigned long flags) |
775 | { | 782 | { |
776 | unsigned long prealloc; | 783 | unsigned long prealloc; |
784 | struct key_preparsed_payload prep; | ||
777 | const struct cred *cred = current_cred(); | 785 | const struct cred *cred = current_cred(); |
778 | struct key_type *ktype; | 786 | struct key_type *ktype; |
779 | struct key *keyring, *key = NULL; | 787 | struct key *keyring, *key = NULL; |
@@ -789,8 +797,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
789 | } | 797 | } |
790 | 798 | ||
791 | key_ref = ERR_PTR(-EINVAL); | 799 | key_ref = ERR_PTR(-EINVAL); |
792 | if (!ktype->match || !ktype->instantiate) | 800 | if (!ktype->match || !ktype->instantiate || |
793 | goto error_2; | 801 | (!description && !ktype->preparse)) |
802 | goto error_put_type; | ||
794 | 803 | ||
795 | keyring = key_ref_to_ptr(keyring_ref); | 804 | keyring = key_ref_to_ptr(keyring_ref); |
796 | 805 | ||
@@ -798,18 +807,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
798 | 807 | ||
799 | key_ref = ERR_PTR(-ENOTDIR); | 808 | key_ref = ERR_PTR(-ENOTDIR); |
800 | if (keyring->type != &key_type_keyring) | 809 | if (keyring->type != &key_type_keyring) |
801 | goto error_2; | 810 | goto error_put_type; |
811 | |||
812 | memset(&prep, 0, sizeof(prep)); | ||
813 | prep.data = payload; | ||
814 | prep.datalen = plen; | ||
815 | prep.quotalen = ktype->def_datalen; | ||
816 | if (ktype->preparse) { | ||
817 | ret = ktype->preparse(&prep); | ||
818 | if (ret < 0) { | ||
819 | key_ref = ERR_PTR(ret); | ||
820 | goto error_put_type; | ||
821 | } | ||
822 | if (!description) | ||
823 | description = prep.description; | ||
824 | key_ref = ERR_PTR(-EINVAL); | ||
825 | if (!description) | ||
826 | goto error_free_prep; | ||
827 | } | ||
802 | 828 | ||
803 | ret = __key_link_begin(keyring, ktype, description, &prealloc); | 829 | ret = __key_link_begin(keyring, ktype, description, &prealloc); |
804 | if (ret < 0) | 830 | if (ret < 0) { |
805 | goto error_2; | 831 | key_ref = ERR_PTR(ret); |
832 | goto error_free_prep; | ||
833 | } | ||
806 | 834 | ||
807 | /* if we're going to allocate a new key, we're going to have | 835 | /* if we're going to allocate a new key, we're going to have |
808 | * to modify the keyring */ | 836 | * to modify the keyring */ |
809 | ret = key_permission(keyring_ref, KEY_WRITE); | 837 | ret = key_permission(keyring_ref, KEY_WRITE); |
810 | if (ret < 0) { | 838 | if (ret < 0) { |
811 | key_ref = ERR_PTR(ret); | 839 | key_ref = ERR_PTR(ret); |
812 | goto error_3; | 840 | goto error_link_end; |
813 | } | 841 | } |
814 | 842 | ||
815 | /* if it's possible to update this type of key, search for an existing | 843 | /* if it's possible to update this type of key, search for an existing |
@@ -840,25 +868,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
840 | perm, flags); | 868 | perm, flags); |
841 | if (IS_ERR(key)) { | 869 | if (IS_ERR(key)) { |
842 | key_ref = ERR_CAST(key); | 870 | key_ref = ERR_CAST(key); |
843 | goto error_3; | 871 | goto error_link_end; |
844 | } | 872 | } |
845 | 873 | ||
846 | /* instantiate it and link it into the target keyring */ | 874 | /* instantiate it and link it into the target keyring */ |
847 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, | 875 | ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); |
848 | &prealloc); | ||
849 | if (ret < 0) { | 876 | if (ret < 0) { |
850 | key_put(key); | 877 | key_put(key); |
851 | key_ref = ERR_PTR(ret); | 878 | key_ref = ERR_PTR(ret); |
852 | goto error_3; | 879 | goto error_link_end; |
853 | } | 880 | } |
854 | 881 | ||
855 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); | 882 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); |
856 | 883 | ||
857 | error_3: | 884 | error_link_end: |
858 | __key_link_end(keyring, ktype, prealloc); | 885 | __key_link_end(keyring, ktype, prealloc); |
859 | error_2: | 886 | error_free_prep: |
887 | if (ktype->preparse) | ||
888 | ktype->free_preparse(&prep); | ||
889 | error_put_type: | ||
860 | key_type_put(ktype); | 890 | key_type_put(ktype); |
861 | error: | 891 | error: |
862 | return key_ref; | 892 | return key_ref; |
863 | 893 | ||
864 | found_matching_key: | 894 | found_matching_key: |
@@ -866,10 +896,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
866 | * - we can drop the locks first as we have the key pinned | 896 | * - we can drop the locks first as we have the key pinned |
867 | */ | 897 | */ |
868 | __key_link_end(keyring, ktype, prealloc); | 898 | __key_link_end(keyring, ktype, prealloc); |
869 | key_type_put(ktype); | ||
870 | 899 | ||
871 | key_ref = __key_update(key_ref, payload, plen); | 900 | key_ref = __key_update(key_ref, &prep); |
872 | goto error; | 901 | goto error_free_prep; |
873 | } | 902 | } |
874 | EXPORT_SYMBOL(key_create_or_update); | 903 | EXPORT_SYMBOL(key_create_or_update); |
875 | 904 | ||
@@ -888,6 +917,7 @@ EXPORT_SYMBOL(key_create_or_update); | |||
888 | */ | 917 | */ |
889 | int key_update(key_ref_t key_ref, const void *payload, size_t plen) | 918 | int key_update(key_ref_t key_ref, const void *payload, size_t plen) |
890 | { | 919 | { |
920 | struct key_preparsed_payload prep; | ||
891 | struct key *key = key_ref_to_ptr(key_ref); | 921 | struct key *key = key_ref_to_ptr(key_ref); |
892 | int ret; | 922 | int ret; |
893 | 923 | ||
@@ -900,18 +930,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) | |||
900 | 930 | ||
901 | /* attempt to update it if supported */ | 931 | /* attempt to update it if supported */ |
902 | ret = -EOPNOTSUPP; | 932 | ret = -EOPNOTSUPP; |
903 | if (key->type->update) { | 933 | if (!key->type->update) |
904 | down_write(&key->sem); | 934 | goto error; |
905 | |||
906 | ret = key->type->update(key, payload, plen); | ||
907 | if (ret == 0) | ||
908 | /* updating a negative key instantiates it */ | ||
909 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
910 | 935 | ||
911 | up_write(&key->sem); | 936 | memset(&prep, 0, sizeof(prep)); |
937 | prep.data = payload; | ||
938 | prep.datalen = plen; | ||
939 | prep.quotalen = key->type->def_datalen; | ||
940 | if (key->type->preparse) { | ||
941 | ret = key->type->preparse(&prep); | ||
942 | if (ret < 0) | ||
943 | goto error; | ||
912 | } | 944 | } |
913 | 945 | ||
914 | error: | 946 | down_write(&key->sem); |
947 | |||
948 | ret = key->type->update(key, &prep); | ||
949 | if (ret == 0) | ||
950 | /* updating a negative key instantiates it */ | ||
951 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
952 | |||
953 | up_write(&key->sem); | ||
954 | |||
955 | if (key->type->preparse) | ||
956 | key->type->free_preparse(&prep); | ||
957 | error: | ||
915 | return ret; | 958 | return ret; |
916 | } | 959 | } |
917 | EXPORT_SYMBOL(key_update); | 960 | EXPORT_SYMBOL(key_update); |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 3364fbf46807..5d34b4e827d6 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type, | |||
46 | * Extract the description of a new key from userspace and either add it as a | 46 | * Extract the description of a new key from userspace and either add it as a |
47 | * new key to the specified keyring or update a matching key in that keyring. | 47 | * new key to the specified keyring or update a matching key in that keyring. |
48 | * | 48 | * |
49 | * If the description is NULL or an empty string, the key type is asked to | ||
50 | * generate one from the payload. | ||
51 | * | ||
49 | * The keyring must be writable so that we can attach the key to it. | 52 | * The keyring must be writable so that we can attach the key to it. |
50 | * | 53 | * |
51 | * If successful, the new key's serial number is returned, otherwise an error | 54 | * If successful, the new key's serial number is returned, otherwise an error |
@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, | |||
72 | if (ret < 0) | 75 | if (ret < 0) |
73 | goto error; | 76 | goto error; |
74 | 77 | ||
75 | description = strndup_user(_description, PAGE_SIZE); | 78 | description = NULL; |
76 | if (IS_ERR(description)) { | 79 | if (_description) { |
77 | ret = PTR_ERR(description); | 80 | description = strndup_user(_description, PAGE_SIZE); |
78 | goto error; | 81 | if (IS_ERR(description)) { |
82 | ret = PTR_ERR(description); | ||
83 | goto error; | ||
84 | } | ||
85 | if (!*description) { | ||
86 | kfree(description); | ||
87 | description = NULL; | ||
88 | } | ||
79 | } | 89 | } |
80 | 90 | ||
81 | /* pull the payload in if one was supplied */ | 91 | /* pull the payload in if one was supplied */ |
@@ -569,8 +579,8 @@ okay: | |||
569 | ret = snprintf(tmpbuf, PAGE_SIZE - 1, | 579 | ret = snprintf(tmpbuf, PAGE_SIZE - 1, |
570 | "%s;%d;%d;%08x;%s", | 580 | "%s;%d;%d;%08x;%s", |
571 | key->type->name, | 581 | key->type->name, |
572 | key->uid, | 582 | from_kuid_munged(current_user_ns(), key->uid), |
573 | key->gid, | 583 | from_kgid_munged(current_user_ns(), key->gid), |
574 | key->perm, | 584 | key->perm, |
575 | key->description ?: ""); | 585 | key->description ?: ""); |
576 | 586 | ||
@@ -766,15 +776,25 @@ error: | |||
766 | * | 776 | * |
767 | * If successful, 0 will be returned. | 777 | * If successful, 0 will be returned. |
768 | */ | 778 | */ |
769 | long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | 779 | long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) |
770 | { | 780 | { |
771 | struct key_user *newowner, *zapowner = NULL; | 781 | struct key_user *newowner, *zapowner = NULL; |
772 | struct key *key; | 782 | struct key *key; |
773 | key_ref_t key_ref; | 783 | key_ref_t key_ref; |
774 | long ret; | 784 | long ret; |
785 | kuid_t uid; | ||
786 | kgid_t gid; | ||
787 | |||
788 | uid = make_kuid(current_user_ns(), user); | ||
789 | gid = make_kgid(current_user_ns(), group); | ||
790 | ret = -EINVAL; | ||
791 | if ((user != (uid_t) -1) && !uid_valid(uid)) | ||
792 | goto error; | ||
793 | if ((group != (gid_t) -1) && !gid_valid(gid)) | ||
794 | goto error; | ||
775 | 795 | ||
776 | ret = 0; | 796 | ret = 0; |
777 | if (uid == (uid_t) -1 && gid == (gid_t) -1) | 797 | if (user == (uid_t) -1 && group == (gid_t) -1) |
778 | goto error; | 798 | goto error; |
779 | 799 | ||
780 | key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, | 800 | key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, |
@@ -792,27 +812,27 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
792 | 812 | ||
793 | if (!capable(CAP_SYS_ADMIN)) { | 813 | if (!capable(CAP_SYS_ADMIN)) { |
794 | /* only the sysadmin can chown a key to some other UID */ | 814 | /* only the sysadmin can chown a key to some other UID */ |
795 | if (uid != (uid_t) -1 && key->uid != uid) | 815 | if (user != (uid_t) -1 && !uid_eq(key->uid, uid)) |
796 | goto error_put; | 816 | goto error_put; |
797 | 817 | ||
798 | /* only the sysadmin can set the key's GID to a group other | 818 | /* only the sysadmin can set the key's GID to a group other |
799 | * than one of those that the current process subscribes to */ | 819 | * than one of those that the current process subscribes to */ |
800 | if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid)) | 820 | if (group != (gid_t) -1 && !gid_eq(gid, key->gid) && !in_group_p(gid)) |
801 | goto error_put; | 821 | goto error_put; |
802 | } | 822 | } |
803 | 823 | ||
804 | /* change the UID */ | 824 | /* change the UID */ |
805 | if (uid != (uid_t) -1 && uid != key->uid) { | 825 | if (user != (uid_t) -1 && !uid_eq(uid, key->uid)) { |
806 | ret = -ENOMEM; | 826 | ret = -ENOMEM; |
807 | newowner = key_user_lookup(uid, current_user_ns()); | 827 | newowner = key_user_lookup(uid); |
808 | if (!newowner) | 828 | if (!newowner) |
809 | goto error_put; | 829 | goto error_put; |
810 | 830 | ||
811 | /* transfer the quota burden to the new user */ | 831 | /* transfer the quota burden to the new user */ |
812 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { | 832 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
813 | unsigned maxkeys = (uid == 0) ? | 833 | unsigned maxkeys = uid_eq(uid, GLOBAL_ROOT_UID) ? |
814 | key_quota_root_maxkeys : key_quota_maxkeys; | 834 | key_quota_root_maxkeys : key_quota_maxkeys; |
815 | unsigned maxbytes = (uid == 0) ? | 835 | unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ? |
816 | key_quota_root_maxbytes : key_quota_maxbytes; | 836 | key_quota_root_maxbytes : key_quota_maxbytes; |
817 | 837 | ||
818 | spin_lock(&newowner->lock); | 838 | spin_lock(&newowner->lock); |
@@ -846,7 +866,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
846 | } | 866 | } |
847 | 867 | ||
848 | /* change the GID */ | 868 | /* change the GID */ |
849 | if (gid != (gid_t) -1) | 869 | if (group != (gid_t) -1) |
850 | key->gid = gid; | 870 | key->gid = gid; |
851 | 871 | ||
852 | ret = 0; | 872 | ret = 0; |
@@ -897,7 +917,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) | |||
897 | down_write(&key->sem); | 917 | down_write(&key->sem); |
898 | 918 | ||
899 | /* if we're not the sysadmin, we can only change a key that we own */ | 919 | /* if we're not the sysadmin, we can only change a key that we own */ |
900 | if (capable(CAP_SYS_ADMIN) || key->uid == current_fsuid()) { | 920 | if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid())) { |
901 | key->perm = perm; | 921 | key->perm = perm; |
902 | ret = 0; | 922 | ret = 0; |
903 | } | 923 | } |
@@ -1486,7 +1506,6 @@ long keyctl_session_to_parent(void) | |||
1486 | oldwork = NULL; | 1506 | oldwork = NULL; |
1487 | parent = me->real_parent; | 1507 | parent = me->real_parent; |
1488 | 1508 | ||
1489 | task_lock(parent); | ||
1490 | /* the parent mustn't be init and mustn't be a kernel thread */ | 1509 | /* the parent mustn't be init and mustn't be a kernel thread */ |
1491 | if (parent->pid <= 1 || !parent->mm) | 1510 | if (parent->pid <= 1 || !parent->mm) |
1492 | goto unlock; | 1511 | goto unlock; |
@@ -1507,18 +1526,18 @@ long keyctl_session_to_parent(void) | |||
1507 | 1526 | ||
1508 | /* the parent must have the same effective ownership and mustn't be | 1527 | /* the parent must have the same effective ownership and mustn't be |
1509 | * SUID/SGID */ | 1528 | * SUID/SGID */ |
1510 | if (pcred->uid != mycred->euid || | 1529 | if (!uid_eq(pcred->uid, mycred->euid) || |
1511 | pcred->euid != mycred->euid || | 1530 | !uid_eq(pcred->euid, mycred->euid) || |
1512 | pcred->suid != mycred->euid || | 1531 | !uid_eq(pcred->suid, mycred->euid) || |
1513 | pcred->gid != mycred->egid || | 1532 | !gid_eq(pcred->gid, mycred->egid) || |
1514 | pcred->egid != mycred->egid || | 1533 | !gid_eq(pcred->egid, mycred->egid) || |
1515 | pcred->sgid != mycred->egid) | 1534 | !gid_eq(pcred->sgid, mycred->egid)) |
1516 | goto unlock; | 1535 | goto unlock; |
1517 | 1536 | ||
1518 | /* the keyrings must have the same UID */ | 1537 | /* the keyrings must have the same UID */ |
1519 | if ((pcred->tgcred->session_keyring && | 1538 | if ((pcred->tgcred->session_keyring && |
1520 | pcred->tgcred->session_keyring->uid != mycred->euid) || | 1539 | !uid_eq(pcred->tgcred->session_keyring->uid, mycred->euid)) || |
1521 | mycred->tgcred->session_keyring->uid != mycred->euid) | 1540 | !uid_eq(mycred->tgcred->session_keyring->uid, mycred->euid)) |
1522 | goto unlock; | 1541 | goto unlock; |
1523 | 1542 | ||
1524 | /* cancel an already pending keyring replacement */ | 1543 | /* cancel an already pending keyring replacement */ |
@@ -1530,7 +1549,6 @@ long keyctl_session_to_parent(void) | |||
1530 | if (!ret) | 1549 | if (!ret) |
1531 | newwork = NULL; | 1550 | newwork = NULL; |
1532 | unlock: | 1551 | unlock: |
1533 | task_unlock(parent); | ||
1534 | write_unlock_irq(&tasklist_lock); | 1552 | write_unlock_irq(&tasklist_lock); |
1535 | rcu_read_unlock(); | 1553 | rcu_read_unlock(); |
1536 | if (oldwork) | 1554 | if (oldwork) |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 81e7852d281d..6e42df15a24c 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc) | |||
66 | * operations. | 66 | * operations. |
67 | */ | 67 | */ |
68 | static int keyring_instantiate(struct key *keyring, | 68 | static int keyring_instantiate(struct key *keyring, |
69 | const void *data, size_t datalen); | 69 | struct key_preparsed_payload *prep); |
70 | static int keyring_match(const struct key *keyring, const void *criterion); | 70 | static int keyring_match(const struct key *keyring, const void *criterion); |
71 | static void keyring_revoke(struct key *keyring); | 71 | static void keyring_revoke(struct key *keyring); |
72 | static void keyring_destroy(struct key *keyring); | 72 | static void keyring_destroy(struct key *keyring); |
@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring) | |||
121 | * Returns 0 on success, -EINVAL if given any data. | 121 | * Returns 0 on success, -EINVAL if given any data. |
122 | */ | 122 | */ |
123 | static int keyring_instantiate(struct key *keyring, | 123 | static int keyring_instantiate(struct key *keyring, |
124 | const void *data, size_t datalen) | 124 | struct key_preparsed_payload *prep) |
125 | { | 125 | { |
126 | int ret; | 126 | int ret; |
127 | 127 | ||
128 | ret = -EINVAL; | 128 | ret = -EINVAL; |
129 | if (datalen == 0) { | 129 | if (prep->datalen == 0) { |
130 | /* make the keyring available by name if it has one */ | 130 | /* make the keyring available by name if it has one */ |
131 | keyring_publish_name(keyring); | 131 | keyring_publish_name(keyring); |
132 | ret = 0; | 132 | ret = 0; |
@@ -256,7 +256,7 @@ error: | |||
256 | /* | 256 | /* |
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, uid_t uid, gid_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, unsigned long flags, |
261 | struct key *dest) | 261 | struct key *dest) |
262 | { | 262 | { |
@@ -612,7 +612,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) | |||
612 | &keyring_name_hash[bucket], | 612 | &keyring_name_hash[bucket], |
613 | type_data.link | 613 | type_data.link |
614 | ) { | 614 | ) { |
615 | if (keyring->user->user_ns != current_user_ns()) | 615 | if (!kuid_has_mapping(current_user_ns(), keyring->user->uid)) |
616 | continue; | 616 | continue; |
617 | 617 | ||
618 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | 618 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
diff --git a/security/keys/permission.c b/security/keys/permission.c index 0b4d019e027d..efcc0c855a0d 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c | |||
@@ -36,33 +36,27 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred, | |||
36 | 36 | ||
37 | key = key_ref_to_ptr(key_ref); | 37 | key = key_ref_to_ptr(key_ref); |
38 | 38 | ||
39 | if (key->user->user_ns != cred->user_ns) | ||
40 | goto use_other_perms; | ||
41 | |||
42 | /* use the second 8-bits of permissions for keys the caller owns */ | 39 | /* use the second 8-bits of permissions for keys the caller owns */ |
43 | if (key->uid == cred->fsuid) { | 40 | if (uid_eq(key->uid, cred->fsuid)) { |
44 | kperm = key->perm >> 16; | 41 | kperm = key->perm >> 16; |
45 | goto use_these_perms; | 42 | goto use_these_perms; |
46 | } | 43 | } |
47 | 44 | ||
48 | /* use the third 8-bits of permissions for keys the caller has a group | 45 | /* use the third 8-bits of permissions for keys the caller has a group |
49 | * membership in common with */ | 46 | * membership in common with */ |
50 | if (key->gid != -1 && key->perm & KEY_GRP_ALL) { | 47 | if (gid_valid(key->gid) && key->perm & KEY_GRP_ALL) { |
51 | if (key->gid == cred->fsgid) { | 48 | if (gid_eq(key->gid, cred->fsgid)) { |
52 | kperm = key->perm >> 8; | 49 | kperm = key->perm >> 8; |
53 | goto use_these_perms; | 50 | goto use_these_perms; |
54 | } | 51 | } |
55 | 52 | ||
56 | ret = groups_search(cred->group_info, | 53 | ret = groups_search(cred->group_info, key->gid); |
57 | make_kgid(current_user_ns(), key->gid)); | ||
58 | if (ret) { | 54 | if (ret) { |
59 | kperm = key->perm >> 8; | 55 | kperm = key->perm >> 8; |
60 | goto use_these_perms; | 56 | goto use_these_perms; |
61 | } | 57 | } |
62 | } | 58 | } |
63 | 59 | ||
64 | use_other_perms: | ||
65 | |||
66 | /* otherwise use the least-significant 8-bits */ | 60 | /* otherwise use the least-significant 8-bits */ |
67 | kperm = key->perm; | 61 | kperm = key->perm; |
68 | 62 | ||
diff --git a/security/keys/proc.c b/security/keys/proc.c index 30d1ddfd9cef..217b6855e815 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -88,14 +88,14 @@ __initcall(key_proc_init); | |||
88 | */ | 88 | */ |
89 | #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS | 89 | #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS |
90 | 90 | ||
91 | static struct rb_node *key_serial_next(struct rb_node *n) | 91 | static struct rb_node *key_serial_next(struct seq_file *p, struct rb_node *n) |
92 | { | 92 | { |
93 | struct user_namespace *user_ns = current_user_ns(); | 93 | struct user_namespace *user_ns = seq_user_ns(p); |
94 | 94 | ||
95 | n = rb_next(n); | 95 | n = rb_next(n); |
96 | while (n) { | 96 | while (n) { |
97 | struct key *key = rb_entry(n, struct key, serial_node); | 97 | struct key *key = rb_entry(n, struct key, serial_node); |
98 | if (key->user->user_ns == user_ns) | 98 | if (kuid_has_mapping(user_ns, key->user->uid)) |
99 | break; | 99 | break; |
100 | n = rb_next(n); | 100 | n = rb_next(n); |
101 | } | 101 | } |
@@ -107,9 +107,9 @@ static int proc_keys_open(struct inode *inode, struct file *file) | |||
107 | return seq_open(file, &proc_keys_ops); | 107 | return seq_open(file, &proc_keys_ops); |
108 | } | 108 | } |
109 | 109 | ||
110 | static struct key *find_ge_key(key_serial_t id) | 110 | static struct key *find_ge_key(struct seq_file *p, key_serial_t id) |
111 | { | 111 | { |
112 | struct user_namespace *user_ns = current_user_ns(); | 112 | struct user_namespace *user_ns = seq_user_ns(p); |
113 | struct rb_node *n = key_serial_tree.rb_node; | 113 | struct rb_node *n = key_serial_tree.rb_node; |
114 | struct key *minkey = NULL; | 114 | struct key *minkey = NULL; |
115 | 115 | ||
@@ -132,7 +132,7 @@ static struct key *find_ge_key(key_serial_t id) | |||
132 | return NULL; | 132 | return NULL; |
133 | 133 | ||
134 | for (;;) { | 134 | for (;;) { |
135 | if (minkey->user->user_ns == user_ns) | 135 | if (kuid_has_mapping(user_ns, minkey->user->uid)) |
136 | return minkey; | 136 | return minkey; |
137 | n = rb_next(&minkey->serial_node); | 137 | n = rb_next(&minkey->serial_node); |
138 | if (!n) | 138 | if (!n) |
@@ -151,7 +151,7 @@ static void *proc_keys_start(struct seq_file *p, loff_t *_pos) | |||
151 | 151 | ||
152 | if (*_pos > INT_MAX) | 152 | if (*_pos > INT_MAX) |
153 | return NULL; | 153 | return NULL; |
154 | key = find_ge_key(pos); | 154 | key = find_ge_key(p, pos); |
155 | if (!key) | 155 | if (!key) |
156 | return NULL; | 156 | return NULL; |
157 | *_pos = key->serial; | 157 | *_pos = key->serial; |
@@ -168,7 +168,7 @@ static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos) | |||
168 | { | 168 | { |
169 | struct rb_node *n; | 169 | struct rb_node *n; |
170 | 170 | ||
171 | n = key_serial_next(v); | 171 | n = key_serial_next(p, v); |
172 | if (n) | 172 | if (n) |
173 | *_pos = key_node_serial(n); | 173 | *_pos = key_node_serial(n); |
174 | return n; | 174 | return n; |
@@ -254,8 +254,8 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
254 | atomic_read(&key->usage), | 254 | atomic_read(&key->usage), |
255 | xbuf, | 255 | xbuf, |
256 | key->perm, | 256 | key->perm, |
257 | key->uid, | 257 | from_kuid_munged(seq_user_ns(m), key->uid), |
258 | key->gid, | 258 | from_kgid_munged(seq_user_ns(m), key->gid), |
259 | key->type->name); | 259 | key->type->name); |
260 | 260 | ||
261 | #undef showflag | 261 | #undef showflag |
@@ -270,26 +270,26 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
270 | 270 | ||
271 | #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ | 271 | #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ |
272 | 272 | ||
273 | static struct rb_node *__key_user_next(struct rb_node *n) | 273 | static struct rb_node *__key_user_next(struct user_namespace *user_ns, struct rb_node *n) |
274 | { | 274 | { |
275 | while (n) { | 275 | while (n) { |
276 | struct key_user *user = rb_entry(n, struct key_user, node); | 276 | struct key_user *user = rb_entry(n, struct key_user, node); |
277 | if (user->user_ns == current_user_ns()) | 277 | if (kuid_has_mapping(user_ns, user->uid)) |
278 | break; | 278 | break; |
279 | n = rb_next(n); | 279 | n = rb_next(n); |
280 | } | 280 | } |
281 | return n; | 281 | return n; |
282 | } | 282 | } |
283 | 283 | ||
284 | static struct rb_node *key_user_next(struct rb_node *n) | 284 | static struct rb_node *key_user_next(struct user_namespace *user_ns, struct rb_node *n) |
285 | { | 285 | { |
286 | return __key_user_next(rb_next(n)); | 286 | return __key_user_next(user_ns, rb_next(n)); |
287 | } | 287 | } |
288 | 288 | ||
289 | static struct rb_node *key_user_first(struct rb_root *r) | 289 | static struct rb_node *key_user_first(struct user_namespace *user_ns, struct rb_root *r) |
290 | { | 290 | { |
291 | struct rb_node *n = rb_first(r); | 291 | struct rb_node *n = rb_first(r); |
292 | return __key_user_next(n); | 292 | return __key_user_next(user_ns, n); |
293 | } | 293 | } |
294 | 294 | ||
295 | /* | 295 | /* |
@@ -309,10 +309,10 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) | |||
309 | 309 | ||
310 | spin_lock(&key_user_lock); | 310 | spin_lock(&key_user_lock); |
311 | 311 | ||
312 | _p = key_user_first(&key_user_tree); | 312 | _p = key_user_first(seq_user_ns(p), &key_user_tree); |
313 | while (pos > 0 && _p) { | 313 | while (pos > 0 && _p) { |
314 | pos--; | 314 | pos--; |
315 | _p = key_user_next(_p); | 315 | _p = key_user_next(seq_user_ns(p), _p); |
316 | } | 316 | } |
317 | 317 | ||
318 | return _p; | 318 | return _p; |
@@ -321,7 +321,7 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) | |||
321 | static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) | 321 | static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) |
322 | { | 322 | { |
323 | (*_pos)++; | 323 | (*_pos)++; |
324 | return key_user_next((struct rb_node *)v); | 324 | return key_user_next(seq_user_ns(p), (struct rb_node *)v); |
325 | } | 325 | } |
326 | 326 | ||
327 | static void proc_key_users_stop(struct seq_file *p, void *v) | 327 | static void proc_key_users_stop(struct seq_file *p, void *v) |
@@ -334,13 +334,13 @@ static int proc_key_users_show(struct seq_file *m, void *v) | |||
334 | { | 334 | { |
335 | struct rb_node *_p = v; | 335 | struct rb_node *_p = v; |
336 | struct key_user *user = rb_entry(_p, struct key_user, node); | 336 | struct key_user *user = rb_entry(_p, struct key_user, node); |
337 | unsigned maxkeys = (user->uid == 0) ? | 337 | unsigned maxkeys = uid_eq(user->uid, GLOBAL_ROOT_UID) ? |
338 | key_quota_root_maxkeys : key_quota_maxkeys; | 338 | key_quota_root_maxkeys : key_quota_maxkeys; |
339 | unsigned maxbytes = (user->uid == 0) ? | 339 | unsigned maxbytes = uid_eq(user->uid, GLOBAL_ROOT_UID) ? |
340 | key_quota_root_maxbytes : key_quota_maxbytes; | 340 | key_quota_root_maxbytes : key_quota_maxbytes; |
341 | 341 | ||
342 | seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", | 342 | seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", |
343 | user->uid, | 343 | from_kuid_munged(seq_user_ns(m), user->uid), |
344 | atomic_read(&user->usage), | 344 | atomic_read(&user->usage), |
345 | atomic_read(&user->nkeys), | 345 | atomic_read(&user->nkeys), |
346 | atomic_read(&user->nikeys), | 346 | atomic_read(&user->nikeys), |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 178b8c3b130a..86468f385fc8 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -34,8 +34,7 @@ struct key_user root_key_user = { | |||
34 | .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), | 34 | .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), |
35 | .nkeys = ATOMIC_INIT(2), | 35 | .nkeys = ATOMIC_INIT(2), |
36 | .nikeys = ATOMIC_INIT(2), | 36 | .nikeys = ATOMIC_INIT(2), |
37 | .uid = 0, | 37 | .uid = GLOBAL_ROOT_UID, |
38 | .user_ns = &init_user_ns, | ||
39 | }; | 38 | }; |
40 | 39 | ||
41 | /* | 40 | /* |
@@ -48,11 +47,13 @@ int install_user_keyrings(void) | |||
48 | struct key *uid_keyring, *session_keyring; | 47 | struct key *uid_keyring, *session_keyring; |
49 | char buf[20]; | 48 | char buf[20]; |
50 | int ret; | 49 | int ret; |
50 | uid_t uid; | ||
51 | 51 | ||
52 | cred = current_cred(); | 52 | cred = current_cred(); |
53 | user = cred->user; | 53 | user = cred->user; |
54 | uid = from_kuid(cred->user_ns, user->uid); | ||
54 | 55 | ||
55 | kenter("%p{%u}", user, user->uid); | 56 | kenter("%p{%u}", user, uid); |
56 | 57 | ||
57 | if (user->uid_keyring) { | 58 | if (user->uid_keyring) { |
58 | kleave(" = 0 [exist]"); | 59 | kleave(" = 0 [exist]"); |
@@ -67,11 +68,11 @@ int install_user_keyrings(void) | |||
67 | * - there may be one in existence already as it may have been | 68 | * - there may be one in existence already as it may have been |
68 | * pinned by a session, but the user_struct pointing to it | 69 | * pinned by a session, but the user_struct pointing to it |
69 | * may have been destroyed by setuid */ | 70 | * may have been destroyed by setuid */ |
70 | sprintf(buf, "_uid.%u", user->uid); | 71 | sprintf(buf, "_uid.%u", uid); |
71 | 72 | ||
72 | uid_keyring = find_keyring_by_name(buf, true); | 73 | uid_keyring = find_keyring_by_name(buf, true); |
73 | if (IS_ERR(uid_keyring)) { | 74 | if (IS_ERR(uid_keyring)) { |
74 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, | 75 | uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, |
75 | cred, KEY_ALLOC_IN_QUOTA, | 76 | cred, KEY_ALLOC_IN_QUOTA, |
76 | NULL); | 77 | NULL); |
77 | if (IS_ERR(uid_keyring)) { | 78 | if (IS_ERR(uid_keyring)) { |
@@ -82,12 +83,12 @@ int install_user_keyrings(void) | |||
82 | 83 | ||
83 | /* get a default session keyring (which might also exist | 84 | /* get a default session keyring (which might also exist |
84 | * already) */ | 85 | * already) */ |
85 | sprintf(buf, "_uid_ses.%u", user->uid); | 86 | sprintf(buf, "_uid_ses.%u", uid); |
86 | 87 | ||
87 | session_keyring = find_keyring_by_name(buf, true); | 88 | session_keyring = find_keyring_by_name(buf, true); |
88 | if (IS_ERR(session_keyring)) { | 89 | if (IS_ERR(session_keyring)) { |
89 | session_keyring = | 90 | session_keyring = |
90 | keyring_alloc(buf, user->uid, (gid_t) -1, | 91 | keyring_alloc(buf, user->uid, INVALID_GID, |
91 | cred, KEY_ALLOC_IN_QUOTA, NULL); | 92 | cred, KEY_ALLOC_IN_QUOTA, NULL); |
92 | if (IS_ERR(session_keyring)) { | 93 | if (IS_ERR(session_keyring)) { |
93 | ret = PTR_ERR(session_keyring); | 94 | ret = PTR_ERR(session_keyring); |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 000e75017520..66e21184b559 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -139,8 +139,8 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
139 | goto error_link; | 139 | goto error_link; |
140 | 140 | ||
141 | /* record the UID and GID */ | 141 | /* record the UID and GID */ |
142 | sprintf(uid_str, "%d", cred->fsuid); | 142 | sprintf(uid_str, "%d", from_kuid(&init_user_ns, cred->fsuid)); |
143 | sprintf(gid_str, "%d", cred->fsgid); | 143 | sprintf(gid_str, "%d", from_kgid(&init_user_ns, cred->fsgid)); |
144 | 144 | ||
145 | /* we say which key is under construction */ | 145 | /* we say which key is under construction */ |
146 | sprintf(key_str, "%d", key->serial); | 146 | sprintf(key_str, "%d", key->serial); |
@@ -442,7 +442,7 @@ static struct key *construct_key_and_link(struct key_type *type, | |||
442 | 442 | ||
443 | kenter(""); | 443 | kenter(""); |
444 | 444 | ||
445 | user = key_user_lookup(current_fsuid(), current_user_ns()); | 445 | user = key_user_lookup(current_fsuid()); |
446 | if (!user) | 446 | if (!user) |
447 | return ERR_PTR(-ENOMEM); | 447 | return ERR_PTR(-ENOMEM); |
448 | 448 | ||
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 60d4e3f5e4bb..85730d5a5a59 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -19,7 +19,8 @@ | |||
19 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | 21 | ||
22 | static int request_key_auth_instantiate(struct key *, const void *, size_t); | 22 | static int request_key_auth_instantiate(struct key *, |
23 | struct key_preparsed_payload *); | ||
23 | static void request_key_auth_describe(const struct key *, struct seq_file *); | 24 | static void request_key_auth_describe(const struct key *, struct seq_file *); |
24 | static void request_key_auth_revoke(struct key *); | 25 | static void request_key_auth_revoke(struct key *); |
25 | static void request_key_auth_destroy(struct key *); | 26 | static void request_key_auth_destroy(struct key *); |
@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = { | |||
42 | * Instantiate a request-key authorisation key. | 43 | * Instantiate a request-key authorisation key. |
43 | */ | 44 | */ |
44 | static int request_key_auth_instantiate(struct key *key, | 45 | static int request_key_auth_instantiate(struct key *key, |
45 | const void *data, | 46 | struct key_preparsed_payload *prep) |
46 | size_t datalen) | ||
47 | { | 47 | { |
48 | key->payload.data = (struct request_key_auth *) data; | 48 | key->payload.data = (struct request_key_auth *)prep->data; |
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 2d5d041f2049..e13fcf7636f7 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
@@ -369,38 +369,6 @@ static int trusted_tpm_send(const u32 chip_num, unsigned char *cmd, | |||
369 | } | 369 | } |
370 | 370 | ||
371 | /* | 371 | /* |
372 | * get a random value from TPM | ||
373 | */ | ||
374 | static int tpm_get_random(struct tpm_buf *tb, unsigned char *buf, uint32_t len) | ||
375 | { | ||
376 | int ret; | ||
377 | |||
378 | INIT_BUF(tb); | ||
379 | store16(tb, TPM_TAG_RQU_COMMAND); | ||
380 | store32(tb, TPM_GETRANDOM_SIZE); | ||
381 | store32(tb, TPM_ORD_GETRANDOM); | ||
382 | store32(tb, len); | ||
383 | ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data); | ||
384 | if (!ret) | ||
385 | memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len); | ||
386 | return ret; | ||
387 | } | ||
388 | |||
389 | static int my_get_random(unsigned char *buf, int len) | ||
390 | { | ||
391 | struct tpm_buf *tb; | ||
392 | int ret; | ||
393 | |||
394 | tb = kmalloc(sizeof *tb, GFP_KERNEL); | ||
395 | if (!tb) | ||
396 | return -ENOMEM; | ||
397 | ret = tpm_get_random(tb, buf, len); | ||
398 | |||
399 | kfree(tb); | ||
400 | return ret; | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | * Lock a trusted key, by extending a selected PCR. | 372 | * Lock a trusted key, by extending a selected PCR. |
405 | * | 373 | * |
406 | * Prevents a trusted key that is sealed to PCRs from being accessed. | 374 | * Prevents a trusted key that is sealed to PCRs from being accessed. |
@@ -413,8 +381,8 @@ static int pcrlock(const int pcrnum) | |||
413 | 381 | ||
414 | if (!capable(CAP_SYS_ADMIN)) | 382 | if (!capable(CAP_SYS_ADMIN)) |
415 | return -EPERM; | 383 | return -EPERM; |
416 | ret = my_get_random(hash, SHA1_DIGEST_SIZE); | 384 | ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE); |
417 | if (ret < 0) | 385 | if (ret != SHA1_DIGEST_SIZE) |
418 | return ret; | 386 | return ret; |
419 | return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; | 387 | return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; |
420 | } | 388 | } |
@@ -429,8 +397,8 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, | |||
429 | unsigned char ononce[TPM_NONCE_SIZE]; | 397 | unsigned char ononce[TPM_NONCE_SIZE]; |
430 | int ret; | 398 | int ret; |
431 | 399 | ||
432 | ret = tpm_get_random(tb, ononce, TPM_NONCE_SIZE); | 400 | ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE); |
433 | if (ret < 0) | 401 | if (ret != TPM_NONCE_SIZE) |
434 | return ret; | 402 | return ret; |
435 | 403 | ||
436 | INIT_BUF(tb); | 404 | INIT_BUF(tb); |
@@ -524,8 +492,8 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, | |||
524 | if (ret < 0) | 492 | if (ret < 0) |
525 | goto out; | 493 | goto out; |
526 | 494 | ||
527 | ret = tpm_get_random(tb, td->nonceodd, TPM_NONCE_SIZE); | 495 | ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE); |
528 | if (ret < 0) | 496 | if (ret != TPM_NONCE_SIZE) |
529 | goto out; | 497 | goto out; |
530 | ordinal = htonl(TPM_ORD_SEAL); | 498 | ordinal = htonl(TPM_ORD_SEAL); |
531 | datsize = htonl(datalen); | 499 | datsize = htonl(datalen); |
@@ -634,8 +602,8 @@ static int tpm_unseal(struct tpm_buf *tb, | |||
634 | 602 | ||
635 | ordinal = htonl(TPM_ORD_UNSEAL); | 603 | ordinal = htonl(TPM_ORD_UNSEAL); |
636 | keyhndl = htonl(SRKHANDLE); | 604 | keyhndl = htonl(SRKHANDLE); |
637 | ret = tpm_get_random(tb, nonceodd, TPM_NONCE_SIZE); | 605 | ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE); |
638 | if (ret < 0) { | 606 | if (ret != TPM_NONCE_SIZE) { |
639 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); | 607 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); |
640 | return ret; | 608 | return ret; |
641 | } | 609 | } |
@@ -927,22 +895,24 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) | |||
927 | * | 895 | * |
928 | * On success, return 0. Otherwise return errno. | 896 | * On success, return 0. Otherwise return errno. |
929 | */ | 897 | */ |
930 | static int trusted_instantiate(struct key *key, const void *data, | 898 | static int trusted_instantiate(struct key *key, |
931 | size_t datalen) | 899 | struct key_preparsed_payload *prep) |
932 | { | 900 | { |
933 | struct trusted_key_payload *payload = NULL; | 901 | struct trusted_key_payload *payload = NULL; |
934 | struct trusted_key_options *options = NULL; | 902 | struct trusted_key_options *options = NULL; |
903 | size_t datalen = prep->datalen; | ||
935 | char *datablob; | 904 | char *datablob; |
936 | int ret = 0; | 905 | int ret = 0; |
937 | int key_cmd; | 906 | int key_cmd; |
907 | size_t key_len; | ||
938 | 908 | ||
939 | if (datalen <= 0 || datalen > 32767 || !data) | 909 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
940 | return -EINVAL; | 910 | return -EINVAL; |
941 | 911 | ||
942 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 912 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
943 | if (!datablob) | 913 | if (!datablob) |
944 | return -ENOMEM; | 914 | return -ENOMEM; |
945 | memcpy(datablob, data, datalen); | 915 | memcpy(datablob, prep->data, datalen); |
946 | datablob[datalen] = '\0'; | 916 | datablob[datalen] = '\0'; |
947 | 917 | ||
948 | options = trusted_options_alloc(); | 918 | options = trusted_options_alloc(); |
@@ -974,8 +944,9 @@ static int trusted_instantiate(struct key *key, const void *data, | |||
974 | pr_info("trusted_key: key_unseal failed (%d)\n", ret); | 944 | pr_info("trusted_key: key_unseal failed (%d)\n", ret); |
975 | break; | 945 | break; |
976 | case Opt_new: | 946 | case Opt_new: |
977 | ret = my_get_random(payload->key, payload->key_len); | 947 | key_len = payload->key_len; |
978 | if (ret < 0) { | 948 | ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len); |
949 | if (ret != key_len) { | ||
979 | pr_info("trusted_key: key_create failed (%d)\n", ret); | 950 | pr_info("trusted_key: key_create failed (%d)\n", ret); |
980 | goto out; | 951 | goto out; |
981 | } | 952 | } |
@@ -1011,17 +982,18 @@ static void trusted_rcu_free(struct rcu_head *rcu) | |||
1011 | /* | 982 | /* |
1012 | * trusted_update - reseal an existing key with new PCR values | 983 | * trusted_update - reseal an existing key with new PCR values |
1013 | */ | 984 | */ |
1014 | static int trusted_update(struct key *key, const void *data, size_t datalen) | 985 | static int trusted_update(struct key *key, struct key_preparsed_payload *prep) |
1015 | { | 986 | { |
1016 | struct trusted_key_payload *p = key->payload.data; | 987 | struct trusted_key_payload *p = key->payload.data; |
1017 | struct trusted_key_payload *new_p; | 988 | struct trusted_key_payload *new_p; |
1018 | struct trusted_key_options *new_o; | 989 | struct trusted_key_options *new_o; |
990 | size_t datalen = prep->datalen; | ||
1019 | char *datablob; | 991 | char *datablob; |
1020 | int ret = 0; | 992 | int ret = 0; |
1021 | 993 | ||
1022 | if (!p->migratable) | 994 | if (!p->migratable) |
1023 | return -EPERM; | 995 | return -EPERM; |
1024 | if (datalen <= 0 || datalen > 32767 || !data) | 996 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
1025 | return -EINVAL; | 997 | return -EINVAL; |
1026 | 998 | ||
1027 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 999 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
@@ -1038,7 +1010,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) | |||
1038 | goto out; | 1010 | goto out; |
1039 | } | 1011 | } |
1040 | 1012 | ||
1041 | memcpy(datablob, data, datalen); | 1013 | memcpy(datablob, prep->data, datalen); |
1042 | datablob[datalen] = '\0'; | 1014 | datablob[datalen] = '\0'; |
1043 | ret = datablob_parse(datablob, new_p, new_o); | 1015 | ret = datablob_parse(datablob, new_p, new_o); |
1044 | if (ret != Opt_update) { | 1016 | if (ret != Opt_update) { |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index c7660a25a3e4..55dc88939185 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon); | |||
58 | /* | 58 | /* |
59 | * instantiate a user defined key | 59 | * instantiate a user defined key |
60 | */ | 60 | */ |
61 | int user_instantiate(struct key *key, const void *data, size_t datalen) | 61 | int user_instantiate(struct key *key, struct key_preparsed_payload *prep) |
62 | { | 62 | { |
63 | struct user_key_payload *upayload; | 63 | struct user_key_payload *upayload; |
64 | size_t datalen = prep->datalen; | ||
64 | int ret; | 65 | int ret; |
65 | 66 | ||
66 | ret = -EINVAL; | 67 | ret = -EINVAL; |
67 | if (datalen <= 0 || datalen > 32767 || !data) | 68 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
68 | goto error; | 69 | goto error; |
69 | 70 | ||
70 | ret = key_payload_reserve(key, datalen); | 71 | ret = key_payload_reserve(key, datalen); |
@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) | |||
78 | 79 | ||
79 | /* attach the data */ | 80 | /* attach the data */ |
80 | upayload->datalen = datalen; | 81 | upayload->datalen = datalen; |
81 | memcpy(upayload->data, data, datalen); | 82 | memcpy(upayload->data, prep->data, datalen); |
82 | rcu_assign_keypointer(key, upayload); | 83 | rcu_assign_keypointer(key, upayload); |
83 | ret = 0; | 84 | ret = 0; |
84 | 85 | ||
@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate); | |||
92 | * update a user defined key | 93 | * update a user defined key |
93 | * - the key's semaphore is write-locked | 94 | * - the key's semaphore is write-locked |
94 | */ | 95 | */ |
95 | int user_update(struct key *key, const void *data, size_t datalen) | 96 | int user_update(struct key *key, struct key_preparsed_payload *prep) |
96 | { | 97 | { |
97 | struct user_key_payload *upayload, *zap; | 98 | struct user_key_payload *upayload, *zap; |
99 | size_t datalen = prep->datalen; | ||
98 | int ret; | 100 | int ret; |
99 | 101 | ||
100 | ret = -EINVAL; | 102 | ret = -EINVAL; |
101 | if (datalen <= 0 || datalen > 32767 || !data) | 103 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
102 | goto error; | 104 | goto error; |
103 | 105 | ||
104 | /* construct a replacement payload */ | 106 | /* construct a replacement payload */ |
@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen) | |||
108 | goto error; | 110 | goto error; |
109 | 111 | ||
110 | upayload->datalen = datalen; | 112 | upayload->datalen = datalen; |
111 | memcpy(upayload->data, data, datalen); | 113 | memcpy(upayload->data, prep->data, datalen); |
112 | 114 | ||
113 | /* check the quota and attach the new data */ | 115 | /* check the quota and attach the new data */ |
114 | zap = upayload; | 116 | zap = upayload; |