diff options
author | James Morris <james.l.morris@oracle.com> | 2014-07-24 07:36:19 -0400 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2014-07-24 07:36:19 -0400 |
commit | 4ca332e11df42604e784bd7da9e483160636d05e (patch) | |
tree | 82e6ba6dff978edc2132e751c19197de50218c7e /security | |
parent | 6d6f3328422a3bc56b0d8dd026a5de845d2abfa7 (diff) | |
parent | 633706a2ee81637be37b6bc02c5336950cc163b5 (diff) |
Merge tag 'keys-next-20140722' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next
Diffstat (limited to 'security')
-rw-r--r-- | security/integrity/digsig.c | 28 | ||||
-rw-r--r-- | security/integrity/ima/Kconfig | 10 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 12 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 10 | ||||
-rw-r--r-- | security/integrity/integrity.h | 5 | ||||
-rw-r--r-- | security/keys/big_key.c | 41 | ||||
-rw-r--r-- | security/keys/encrypted-keys/encrypted.c | 2 | ||||
-rw-r--r-- | security/keys/key.c | 49 | ||||
-rw-r--r-- | security/keys/keyctl.c | 21 | ||||
-rw-r--r-- | security/keys/keyring.c | 34 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 13 | ||||
-rw-r--r-- | security/keys/user_defined.c | 41 |
12 files changed, 209 insertions, 57 deletions
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index b4af4ebc5be2..8d4fbff8b87c 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c | |||
@@ -13,7 +13,9 @@ | |||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14 | 14 | ||
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/sched.h> | ||
16 | #include <linux/rbtree.h> | 17 | #include <linux/rbtree.h> |
18 | #include <linux/cred.h> | ||
17 | #include <linux/key-type.h> | 19 | #include <linux/key-type.h> |
18 | #include <linux/digsig.h> | 20 | #include <linux/digsig.h> |
19 | 21 | ||
@@ -24,7 +26,11 @@ static struct key *keyring[INTEGRITY_KEYRING_MAX]; | |||
24 | static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { | 26 | static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { |
25 | "_evm", | 27 | "_evm", |
26 | "_module", | 28 | "_module", |
29 | #ifndef CONFIG_IMA_TRUSTED_KEYRING | ||
27 | "_ima", | 30 | "_ima", |
31 | #else | ||
32 | ".ima", | ||
33 | #endif | ||
28 | }; | 34 | }; |
29 | 35 | ||
30 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | 36 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, |
@@ -56,3 +62,25 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | |||
56 | 62 | ||
57 | return -EOPNOTSUPP; | 63 | return -EOPNOTSUPP; |
58 | } | 64 | } |
65 | |||
66 | int integrity_init_keyring(const unsigned int id) | ||
67 | { | ||
68 | const struct cred *cred = current_cred(); | ||
69 | int err = 0; | ||
70 | |||
71 | keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), | ||
72 | KGIDT_INIT(0), cred, | ||
73 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
74 | KEY_USR_VIEW | KEY_USR_READ | | ||
75 | KEY_USR_WRITE | KEY_USR_SEARCH), | ||
76 | KEY_ALLOC_NOT_IN_QUOTA, NULL); | ||
77 | if (!IS_ERR(keyring[id])) | ||
78 | set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); | ||
79 | else { | ||
80 | err = PTR_ERR(keyring[id]); | ||
81 | pr_info("Can't allocate %s keyring (%d)\n", | ||
82 | keyring_name[id], err); | ||
83 | keyring[id] = NULL; | ||
84 | } | ||
85 | return err; | ||
86 | } | ||
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 81a27971d884..08758fbd496f 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig | |||
@@ -123,3 +123,13 @@ config IMA_APPRAISE | |||
123 | For more information on integrity appraisal refer to: | 123 | For more information on integrity appraisal refer to: |
124 | <http://linux-ima.sourceforge.net> | 124 | <http://linux-ima.sourceforge.net> |
125 | If unsure, say N. | 125 | If unsure, say N. |
126 | |||
127 | config IMA_TRUSTED_KEYRING | ||
128 | bool "Require all keys on the .ima keyring be signed" | ||
129 | depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING | ||
130 | depends on INTEGRITY_ASYMMETRIC_KEYS | ||
131 | select KEYS_DEBUG_PROC_KEYS | ||
132 | default y | ||
133 | help | ||
134 | This option requires that all keys added to the .ima | ||
135 | keyring be signed by a key on the system trusted keyring. | ||
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index f79fa8be203c..c42056edfc97 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -249,4 +249,16 @@ static inline int security_filter_rule_match(u32 secid, u32 field, u32 op, | |||
249 | return -EINVAL; | 249 | return -EINVAL; |
250 | } | 250 | } |
251 | #endif /* CONFIG_IMA_LSM_RULES */ | 251 | #endif /* CONFIG_IMA_LSM_RULES */ |
252 | |||
253 | #ifdef CONFIG_IMA_TRUSTED_KEYRING | ||
254 | static inline int ima_init_keyring(const unsigned int id) | ||
255 | { | ||
256 | return integrity_init_keyring(id); | ||
257 | } | ||
258 | #else | ||
259 | static inline int ima_init_keyring(const unsigned int id) | ||
260 | { | ||
261 | return 0; | ||
262 | } | ||
263 | #endif /* CONFIG_IMA_TRUSTED_KEYRING */ | ||
252 | #endif | 264 | #endif |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index f474c608fa11..0d696431209c 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -325,8 +325,14 @@ static int __init init_ima(void) | |||
325 | 325 | ||
326 | hash_setup(CONFIG_IMA_DEFAULT_HASH); | 326 | hash_setup(CONFIG_IMA_DEFAULT_HASH); |
327 | error = ima_init(); | 327 | error = ima_init(); |
328 | if (!error) | 328 | if (error) |
329 | ima_initialized = 1; | 329 | goto out; |
330 | |||
331 | error = ima_init_keyring(INTEGRITY_KEYRING_IMA); | ||
332 | if (error) | ||
333 | goto out; | ||
334 | ima_initialized = 1; | ||
335 | out: | ||
330 | return error; | 336 | return error; |
331 | } | 337 | } |
332 | 338 | ||
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 33c0a70f6b15..09c440d9aaee 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h | |||
@@ -124,6 +124,7 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | |||
124 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | 124 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, |
125 | const char *digest, int digestlen); | 125 | const char *digest, int digestlen); |
126 | 126 | ||
127 | int integrity_init_keyring(const unsigned int id); | ||
127 | #else | 128 | #else |
128 | 129 | ||
129 | static inline int integrity_digsig_verify(const unsigned int id, | 130 | static inline int integrity_digsig_verify(const unsigned int id, |
@@ -133,6 +134,10 @@ static inline int integrity_digsig_verify(const unsigned int id, | |||
133 | return -EOPNOTSUPP; | 134 | return -EOPNOTSUPP; |
134 | } | 135 | } |
135 | 136 | ||
137 | static inline int integrity_init_keyring(const unsigned int id) | ||
138 | { | ||
139 | return 0; | ||
140 | } | ||
136 | #endif /* CONFIG_INTEGRITY_SIGNATURE */ | 141 | #endif /* CONFIG_INTEGRITY_SIGNATURE */ |
137 | 142 | ||
138 | #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS | 143 | #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS |
diff --git a/security/keys/big_key.c b/security/keys/big_key.c index 8137b27d641d..c2f91a0cf889 100644 --- a/security/keys/big_key.c +++ b/security/keys/big_key.c | |||
@@ -34,7 +34,9 @@ MODULE_LICENSE("GPL"); | |||
34 | struct key_type key_type_big_key = { | 34 | struct key_type key_type_big_key = { |
35 | .name = "big_key", | 35 | .name = "big_key", |
36 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | 36 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
37 | .instantiate = big_key_instantiate, | 37 | .preparse = big_key_preparse, |
38 | .free_preparse = big_key_free_preparse, | ||
39 | .instantiate = generic_key_instantiate, | ||
38 | .match = user_match, | 40 | .match = user_match, |
39 | .revoke = big_key_revoke, | 41 | .revoke = big_key_revoke, |
40 | .destroy = big_key_destroy, | 42 | .destroy = big_key_destroy, |
@@ -43,11 +45,11 @@ struct key_type key_type_big_key = { | |||
43 | }; | 45 | }; |
44 | 46 | ||
45 | /* | 47 | /* |
46 | * Instantiate a big key | 48 | * Preparse a big key |
47 | */ | 49 | */ |
48 | int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | 50 | int big_key_preparse(struct key_preparsed_payload *prep) |
49 | { | 51 | { |
50 | struct path *path = (struct path *)&key->payload.data2; | 52 | struct path *path = (struct path *)&prep->payload; |
51 | struct file *file; | 53 | struct file *file; |
52 | ssize_t written; | 54 | ssize_t written; |
53 | size_t datalen = prep->datalen; | 55 | size_t datalen = prep->datalen; |
@@ -58,11 +60,9 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
58 | goto error; | 60 | goto error; |
59 | 61 | ||
60 | /* Set an arbitrary quota */ | 62 | /* Set an arbitrary quota */ |
61 | ret = key_payload_reserve(key, 16); | 63 | prep->quotalen = 16; |
62 | if (ret < 0) | ||
63 | goto error; | ||
64 | 64 | ||
65 | key->type_data.x[1] = datalen; | 65 | prep->type_data[1] = (void *)(unsigned long)datalen; |
66 | 66 | ||
67 | if (datalen > BIG_KEY_FILE_THRESHOLD) { | 67 | if (datalen > BIG_KEY_FILE_THRESHOLD) { |
68 | /* Create a shmem file to store the data in. This will permit the data | 68 | /* Create a shmem file to store the data in. This will permit the data |
@@ -73,7 +73,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
73 | file = shmem_kernel_file_setup("", datalen, 0); | 73 | file = shmem_kernel_file_setup("", datalen, 0); |
74 | if (IS_ERR(file)) { | 74 | if (IS_ERR(file)) { |
75 | ret = PTR_ERR(file); | 75 | ret = PTR_ERR(file); |
76 | goto err_quota; | 76 | goto error; |
77 | } | 77 | } |
78 | 78 | ||
79 | written = kernel_write(file, prep->data, prep->datalen, 0); | 79 | written = kernel_write(file, prep->data, prep->datalen, 0); |
@@ -93,24 +93,33 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
93 | } else { | 93 | } else { |
94 | /* Just store the data in a buffer */ | 94 | /* Just store the data in a buffer */ |
95 | void *data = kmalloc(datalen, GFP_KERNEL); | 95 | void *data = kmalloc(datalen, GFP_KERNEL); |
96 | if (!data) { | 96 | if (!data) |
97 | ret = -ENOMEM; | 97 | return -ENOMEM; |
98 | goto err_quota; | ||
99 | } | ||
100 | 98 | ||
101 | key->payload.data = memcpy(data, prep->data, prep->datalen); | 99 | prep->payload[0] = memcpy(data, prep->data, prep->datalen); |
102 | } | 100 | } |
103 | return 0; | 101 | return 0; |
104 | 102 | ||
105 | err_fput: | 103 | err_fput: |
106 | fput(file); | 104 | fput(file); |
107 | err_quota: | ||
108 | key_payload_reserve(key, 0); | ||
109 | error: | 105 | error: |
110 | return ret; | 106 | return ret; |
111 | } | 107 | } |
112 | 108 | ||
113 | /* | 109 | /* |
110 | * Clear preparsement. | ||
111 | */ | ||
112 | void big_key_free_preparse(struct key_preparsed_payload *prep) | ||
113 | { | ||
114 | if (prep->datalen > BIG_KEY_FILE_THRESHOLD) { | ||
115 | struct path *path = (struct path *)&prep->payload; | ||
116 | path_put(path); | ||
117 | } else { | ||
118 | kfree(prep->payload[0]); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | /* | ||
114 | * dispose of the links from a revoked keyring | 123 | * dispose of the links from a revoked keyring |
115 | * - called with the key sem write-locked | 124 | * - called with the key sem write-locked |
116 | */ | 125 | */ |
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 5fe443d120af..d252c5704f8a 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c | |||
@@ -811,7 +811,7 @@ static int encrypted_instantiate(struct key *key, | |||
811 | goto out; | 811 | goto out; |
812 | } | 812 | } |
813 | 813 | ||
814 | rcu_assign_keypointer(key, epayload); | 814 | prep->payload[0] = epayload; |
815 | out: | 815 | out: |
816 | kfree(datablob); | 816 | kfree(datablob); |
817 | return ret; | 817 | return ret; |
diff --git a/security/keys/key.c b/security/keys/key.c index 2048a110e7f1..b90a68c4e2c4 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -437,6 +437,11 @@ static int __key_instantiate_and_link(struct key *key, | |||
437 | /* disable the authorisation key */ | 437 | /* disable the authorisation key */ |
438 | if (authkey) | 438 | if (authkey) |
439 | key_revoke(authkey); | 439 | key_revoke(authkey); |
440 | |||
441 | if (prep->expiry != TIME_T_MAX) { | ||
442 | key->expiry = prep->expiry; | ||
443 | key_schedule_gc(prep->expiry + key_gc_delay); | ||
444 | } | ||
440 | } | 445 | } |
441 | } | 446 | } |
442 | 447 | ||
@@ -479,6 +484,7 @@ int key_instantiate_and_link(struct key *key, | |||
479 | prep.data = data; | 484 | prep.data = data; |
480 | prep.datalen = datalen; | 485 | prep.datalen = datalen; |
481 | prep.quotalen = key->type->def_datalen; | 486 | prep.quotalen = key->type->def_datalen; |
487 | prep.expiry = TIME_T_MAX; | ||
482 | if (key->type->preparse) { | 488 | if (key->type->preparse) { |
483 | ret = key->type->preparse(&prep); | 489 | ret = key->type->preparse(&prep); |
484 | if (ret < 0) | 490 | if (ret < 0) |
@@ -488,7 +494,7 @@ int key_instantiate_and_link(struct key *key, | |||
488 | if (keyring) { | 494 | if (keyring) { |
489 | ret = __key_link_begin(keyring, &key->index_key, &edit); | 495 | ret = __key_link_begin(keyring, &key->index_key, &edit); |
490 | if (ret < 0) | 496 | if (ret < 0) |
491 | goto error_free_preparse; | 497 | goto error; |
492 | } | 498 | } |
493 | 499 | ||
494 | ret = __key_instantiate_and_link(key, &prep, keyring, authkey, &edit); | 500 | ret = __key_instantiate_and_link(key, &prep, keyring, authkey, &edit); |
@@ -496,10 +502,9 @@ int key_instantiate_and_link(struct key *key, | |||
496 | if (keyring) | 502 | if (keyring) |
497 | __key_link_end(keyring, &key->index_key, edit); | 503 | __key_link_end(keyring, &key->index_key, edit); |
498 | 504 | ||
499 | error_free_preparse: | 505 | error: |
500 | if (key->type->preparse) | 506 | if (key->type->preparse) |
501 | key->type->free_preparse(&prep); | 507 | key->type->free_preparse(&prep); |
502 | error: | ||
503 | return ret; | 508 | return ret; |
504 | } | 509 | } |
505 | 510 | ||
@@ -811,11 +816,12 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
811 | prep.datalen = plen; | 816 | prep.datalen = plen; |
812 | prep.quotalen = index_key.type->def_datalen; | 817 | prep.quotalen = index_key.type->def_datalen; |
813 | prep.trusted = flags & KEY_ALLOC_TRUSTED; | 818 | prep.trusted = flags & KEY_ALLOC_TRUSTED; |
819 | prep.expiry = TIME_T_MAX; | ||
814 | if (index_key.type->preparse) { | 820 | if (index_key.type->preparse) { |
815 | ret = index_key.type->preparse(&prep); | 821 | ret = index_key.type->preparse(&prep); |
816 | if (ret < 0) { | 822 | if (ret < 0) { |
817 | key_ref = ERR_PTR(ret); | 823 | key_ref = ERR_PTR(ret); |
818 | goto error_put_type; | 824 | goto error_free_prep; |
819 | } | 825 | } |
820 | if (!index_key.description) | 826 | if (!index_key.description) |
821 | index_key.description = prep.description; | 827 | index_key.description = prep.description; |
@@ -941,6 +947,7 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) | |||
941 | prep.data = payload; | 947 | prep.data = payload; |
942 | prep.datalen = plen; | 948 | prep.datalen = plen; |
943 | prep.quotalen = key->type->def_datalen; | 949 | prep.quotalen = key->type->def_datalen; |
950 | prep.expiry = TIME_T_MAX; | ||
944 | if (key->type->preparse) { | 951 | if (key->type->preparse) { |
945 | ret = key->type->preparse(&prep); | 952 | ret = key->type->preparse(&prep); |
946 | if (ret < 0) | 953 | if (ret < 0) |
@@ -956,9 +963,9 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) | |||
956 | 963 | ||
957 | up_write(&key->sem); | 964 | up_write(&key->sem); |
958 | 965 | ||
966 | error: | ||
959 | if (key->type->preparse) | 967 | if (key->type->preparse) |
960 | key->type->free_preparse(&prep); | 968 | key->type->free_preparse(&prep); |
961 | error: | ||
962 | return ret; | 969 | return ret; |
963 | } | 970 | } |
964 | EXPORT_SYMBOL(key_update); | 971 | EXPORT_SYMBOL(key_update); |
@@ -1024,6 +1031,38 @@ void key_invalidate(struct key *key) | |||
1024 | EXPORT_SYMBOL(key_invalidate); | 1031 | EXPORT_SYMBOL(key_invalidate); |
1025 | 1032 | ||
1026 | /** | 1033 | /** |
1034 | * generic_key_instantiate - Simple instantiation of a key from preparsed data | ||
1035 | * @key: The key to be instantiated | ||
1036 | * @prep: The preparsed data to load. | ||
1037 | * | ||
1038 | * Instantiate a key from preparsed data. We assume we can just copy the data | ||
1039 | * in directly and clear the old pointers. | ||
1040 | * | ||
1041 | * This can be pointed to directly by the key type instantiate op pointer. | ||
1042 | */ | ||
1043 | int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | ||
1044 | { | ||
1045 | int ret; | ||
1046 | |||
1047 | pr_devel("==>%s()\n", __func__); | ||
1048 | |||
1049 | ret = key_payload_reserve(key, prep->quotalen); | ||
1050 | if (ret == 0) { | ||
1051 | key->type_data.p[0] = prep->type_data[0]; | ||
1052 | key->type_data.p[1] = prep->type_data[1]; | ||
1053 | rcu_assign_keypointer(key, prep->payload[0]); | ||
1054 | key->payload.data2[1] = prep->payload[1]; | ||
1055 | prep->type_data[0] = NULL; | ||
1056 | prep->type_data[1] = NULL; | ||
1057 | prep->payload[0] = NULL; | ||
1058 | prep->payload[1] = NULL; | ||
1059 | } | ||
1060 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
1061 | return ret; | ||
1062 | } | ||
1063 | EXPORT_SYMBOL(generic_key_instantiate); | ||
1064 | |||
1065 | /** | ||
1027 | * register_key_type - Register a type of key. | 1066 | * register_key_type - Register a type of key. |
1028 | * @ktype: The new key type. | 1067 | * @ktype: The new key type. |
1029 | * | 1068 | * |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index cd5bd0cef25d..e26f860e5f2e 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -37,8 +37,6 @@ static int key_get_type_from_user(char *type, | |||
37 | return ret; | 37 | return ret; |
38 | if (ret == 0 || ret >= len) | 38 | if (ret == 0 || ret >= len) |
39 | return -EINVAL; | 39 | return -EINVAL; |
40 | if (type[0] == '.') | ||
41 | return -EPERM; | ||
42 | type[len - 1] = '\0'; | 40 | type[len - 1] = '\0'; |
43 | return 0; | 41 | return 0; |
44 | } | 42 | } |
@@ -86,6 +84,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, | |||
86 | if (!*description) { | 84 | if (!*description) { |
87 | kfree(description); | 85 | kfree(description); |
88 | description = NULL; | 86 | description = NULL; |
87 | } else if ((description[0] == '.') && | ||
88 | (strncmp(type, "keyring", 7) == 0)) { | ||
89 | ret = -EPERM; | ||
90 | goto error2; | ||
89 | } | 91 | } |
90 | } | 92 | } |
91 | 93 | ||
@@ -404,12 +406,25 @@ long keyctl_invalidate_key(key_serial_t id) | |||
404 | key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH); | 406 | key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH); |
405 | if (IS_ERR(key_ref)) { | 407 | if (IS_ERR(key_ref)) { |
406 | ret = PTR_ERR(key_ref); | 408 | ret = PTR_ERR(key_ref); |
409 | |||
410 | /* Root is permitted to invalidate certain special keys */ | ||
411 | if (capable(CAP_SYS_ADMIN)) { | ||
412 | key_ref = lookup_user_key(id, 0, 0); | ||
413 | if (IS_ERR(key_ref)) | ||
414 | goto error; | ||
415 | if (test_bit(KEY_FLAG_ROOT_CAN_INVAL, | ||
416 | &key_ref_to_ptr(key_ref)->flags)) | ||
417 | goto invalidate; | ||
418 | goto error_put; | ||
419 | } | ||
420 | |||
407 | goto error; | 421 | goto error; |
408 | } | 422 | } |
409 | 423 | ||
424 | invalidate: | ||
410 | key_invalidate(key_ref_to_ptr(key_ref)); | 425 | key_invalidate(key_ref_to_ptr(key_ref)); |
411 | ret = 0; | 426 | ret = 0; |
412 | 427 | error_put: | |
413 | key_ref_put(key_ref); | 428 | key_ref_put(key_ref); |
414 | error: | 429 | error: |
415 | kleave(" = %ld", ret); | 430 | kleave(" = %ld", ret); |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 9cf2575f0d97..8314a7d2104d 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -73,6 +73,8 @@ static inline unsigned keyring_hash(const char *desc) | |||
73 | * can be treated as ordinary keys in addition to having their own special | 73 | * can be treated as ordinary keys in addition to having their own special |
74 | * operations. | 74 | * operations. |
75 | */ | 75 | */ |
76 | static int keyring_preparse(struct key_preparsed_payload *prep); | ||
77 | static void keyring_free_preparse(struct key_preparsed_payload *prep); | ||
76 | static int keyring_instantiate(struct key *keyring, | 78 | static int keyring_instantiate(struct key *keyring, |
77 | struct key_preparsed_payload *prep); | 79 | struct key_preparsed_payload *prep); |
78 | static void keyring_revoke(struct key *keyring); | 80 | static void keyring_revoke(struct key *keyring); |
@@ -84,6 +86,8 @@ static long keyring_read(const struct key *keyring, | |||
84 | struct key_type key_type_keyring = { | 86 | struct key_type key_type_keyring = { |
85 | .name = "keyring", | 87 | .name = "keyring", |
86 | .def_datalen = 0, | 88 | .def_datalen = 0, |
89 | .preparse = keyring_preparse, | ||
90 | .free_preparse = keyring_free_preparse, | ||
87 | .instantiate = keyring_instantiate, | 91 | .instantiate = keyring_instantiate, |
88 | .match = user_match, | 92 | .match = user_match, |
89 | .revoke = keyring_revoke, | 93 | .revoke = keyring_revoke, |
@@ -123,6 +127,21 @@ static void keyring_publish_name(struct key *keyring) | |||
123 | } | 127 | } |
124 | 128 | ||
125 | /* | 129 | /* |
130 | * Preparse a keyring payload | ||
131 | */ | ||
132 | static int keyring_preparse(struct key_preparsed_payload *prep) | ||
133 | { | ||
134 | return prep->datalen != 0 ? -EINVAL : 0; | ||
135 | } | ||
136 | |||
137 | /* | ||
138 | * Free a preparse of a user defined key payload | ||
139 | */ | ||
140 | static void keyring_free_preparse(struct key_preparsed_payload *prep) | ||
141 | { | ||
142 | } | ||
143 | |||
144 | /* | ||
126 | * Initialise a keyring. | 145 | * Initialise a keyring. |
127 | * | 146 | * |
128 | * Returns 0 on success, -EINVAL if given any data. | 147 | * Returns 0 on success, -EINVAL if given any data. |
@@ -130,17 +149,10 @@ static void keyring_publish_name(struct key *keyring) | |||
130 | static int keyring_instantiate(struct key *keyring, | 149 | static int keyring_instantiate(struct key *keyring, |
131 | struct key_preparsed_payload *prep) | 150 | struct key_preparsed_payload *prep) |
132 | { | 151 | { |
133 | int ret; | 152 | assoc_array_init(&keyring->keys); |
134 | 153 | /* make the keyring available by name if it has one */ | |
135 | ret = -EINVAL; | 154 | keyring_publish_name(keyring); |
136 | if (prep->datalen == 0) { | 155 | return 0; |
137 | assoc_array_init(&keyring->keys); | ||
138 | /* make the keyring available by name if it has one */ | ||
139 | keyring_publish_name(keyring); | ||
140 | ret = 0; | ||
141 | } | ||
142 | |||
143 | return ret; | ||
144 | } | 156 | } |
145 | 157 | ||
146 | /* | 158 | /* |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 7495a93b4b90..842e6f410d50 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | #include <keys/user-type.h> | 21 | #include <keys/user-type.h> |
22 | 22 | ||
23 | static int request_key_auth_preparse(struct key_preparsed_payload *); | ||
24 | static void request_key_auth_free_preparse(struct key_preparsed_payload *); | ||
23 | static int request_key_auth_instantiate(struct key *, | 25 | static int request_key_auth_instantiate(struct key *, |
24 | struct key_preparsed_payload *); | 26 | struct key_preparsed_payload *); |
25 | static void request_key_auth_describe(const struct key *, struct seq_file *); | 27 | static void request_key_auth_describe(const struct key *, struct seq_file *); |
@@ -33,6 +35,8 @@ static long request_key_auth_read(const struct key *, char __user *, size_t); | |||
33 | struct key_type key_type_request_key_auth = { | 35 | struct key_type key_type_request_key_auth = { |
34 | .name = ".request_key_auth", | 36 | .name = ".request_key_auth", |
35 | .def_datalen = sizeof(struct request_key_auth), | 37 | .def_datalen = sizeof(struct request_key_auth), |
38 | .preparse = request_key_auth_preparse, | ||
39 | .free_preparse = request_key_auth_free_preparse, | ||
36 | .instantiate = request_key_auth_instantiate, | 40 | .instantiate = request_key_auth_instantiate, |
37 | .describe = request_key_auth_describe, | 41 | .describe = request_key_auth_describe, |
38 | .revoke = request_key_auth_revoke, | 42 | .revoke = request_key_auth_revoke, |
@@ -40,6 +44,15 @@ struct key_type key_type_request_key_auth = { | |||
40 | .read = request_key_auth_read, | 44 | .read = request_key_auth_read, |
41 | }; | 45 | }; |
42 | 46 | ||
47 | int request_key_auth_preparse(struct key_preparsed_payload *prep) | ||
48 | { | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | void request_key_auth_free_preparse(struct key_preparsed_payload *prep) | ||
53 | { | ||
54 | } | ||
55 | |||
43 | /* | 56 | /* |
44 | * Instantiate a request-key authorisation key. | 57 | * Instantiate a request-key authorisation key. |
45 | */ | 58 | */ |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index faa2caeb593f..eee340011f2b 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -27,7 +27,9 @@ static int logon_vet_description(const char *desc); | |||
27 | struct key_type key_type_user = { | 27 | struct key_type key_type_user = { |
28 | .name = "user", | 28 | .name = "user", |
29 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | 29 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
30 | .instantiate = user_instantiate, | 30 | .preparse = user_preparse, |
31 | .free_preparse = user_free_preparse, | ||
32 | .instantiate = generic_key_instantiate, | ||
31 | .update = user_update, | 33 | .update = user_update, |
32 | .match = user_match, | 34 | .match = user_match, |
33 | .revoke = user_revoke, | 35 | .revoke = user_revoke, |
@@ -47,7 +49,9 @@ EXPORT_SYMBOL_GPL(key_type_user); | |||
47 | struct key_type key_type_logon = { | 49 | struct key_type key_type_logon = { |
48 | .name = "logon", | 50 | .name = "logon", |
49 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | 51 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
50 | .instantiate = user_instantiate, | 52 | .preparse = user_preparse, |
53 | .free_preparse = user_free_preparse, | ||
54 | .instantiate = generic_key_instantiate, | ||
51 | .update = user_update, | 55 | .update = user_update, |
52 | .match = user_match, | 56 | .match = user_match, |
53 | .revoke = user_revoke, | 57 | .revoke = user_revoke, |
@@ -58,38 +62,37 @@ struct key_type key_type_logon = { | |||
58 | EXPORT_SYMBOL_GPL(key_type_logon); | 62 | EXPORT_SYMBOL_GPL(key_type_logon); |
59 | 63 | ||
60 | /* | 64 | /* |
61 | * instantiate a user defined key | 65 | * Preparse a user defined key payload |
62 | */ | 66 | */ |
63 | int user_instantiate(struct key *key, struct key_preparsed_payload *prep) | 67 | int user_preparse(struct key_preparsed_payload *prep) |
64 | { | 68 | { |
65 | struct user_key_payload *upayload; | 69 | struct user_key_payload *upayload; |
66 | size_t datalen = prep->datalen; | 70 | size_t datalen = prep->datalen; |
67 | int ret; | ||
68 | 71 | ||
69 | ret = -EINVAL; | ||
70 | if (datalen <= 0 || datalen > 32767 || !prep->data) | 72 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
71 | goto error; | 73 | return -EINVAL; |
72 | |||
73 | ret = key_payload_reserve(key, datalen); | ||
74 | if (ret < 0) | ||
75 | goto error; | ||
76 | 74 | ||
77 | ret = -ENOMEM; | ||
78 | upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL); | 75 | upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL); |
79 | if (!upayload) | 76 | if (!upayload) |
80 | goto error; | 77 | return -ENOMEM; |
81 | 78 | ||
82 | /* attach the data */ | 79 | /* attach the data */ |
80 | prep->quotalen = datalen; | ||
81 | prep->payload[0] = upayload; | ||
83 | upayload->datalen = datalen; | 82 | upayload->datalen = datalen; |
84 | memcpy(upayload->data, prep->data, datalen); | 83 | memcpy(upayload->data, prep->data, datalen); |
85 | rcu_assign_keypointer(key, upayload); | 84 | return 0; |
86 | ret = 0; | ||
87 | |||
88 | error: | ||
89 | return ret; | ||
90 | } | 85 | } |
86 | EXPORT_SYMBOL_GPL(user_preparse); | ||
91 | 87 | ||
92 | EXPORT_SYMBOL_GPL(user_instantiate); | 88 | /* |
89 | * Free a preparse of a user defined key payload | ||
90 | */ | ||
91 | void user_free_preparse(struct key_preparsed_payload *prep) | ||
92 | { | ||
93 | kfree(prep->payload[0]); | ||
94 | } | ||
95 | EXPORT_SYMBOL_GPL(user_free_preparse); | ||
93 | 96 | ||
94 | /* | 97 | /* |
95 | * update a user defined key | 98 | * update a user defined key |