aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/big_key.c41
-rw-r--r--security/keys/key.c49
-rw-r--r--security/keys/keyctl.c21
-rw-r--r--security/keys/keyring.c34
-rw-r--r--security/keys/request_key_auth.c13
-rw-r--r--security/keys/user_defined.c41
6 files changed, 145 insertions, 54 deletions
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");
34struct key_type key_type_big_key = { 34struct 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 */
48int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) 50int 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
105err_fput: 103err_fput:
106 fput(file); 104 fput(file);
107err_quota:
108 key_payload_reserve(key, 0);
109error: 105error:
110 return ret; 106 return ret;
111} 107}
112 108
113/* 109/*
110 * Clear preparsement.
111 */
112void 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/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
499error_free_preparse: 505error:
500 if (key->type->preparse) 506 if (key->type->preparse)
501 key->type->free_preparse(&prep); 507 key->type->free_preparse(&prep);
502error:
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
966error:
959 if (key->type->preparse) 967 if (key->type->preparse)
960 key->type->free_preparse(&prep); 968 key->type->free_preparse(&prep);
961error:
962 return ret; 969 return ret;
963} 970}
964EXPORT_SYMBOL(key_update); 971EXPORT_SYMBOL(key_update);
@@ -1024,6 +1031,38 @@ void key_invalidate(struct key *key)
1024EXPORT_SYMBOL(key_invalidate); 1031EXPORT_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 */
1043int 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}
1063EXPORT_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
424invalidate:
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 427error_put:
413 key_ref_put(key_ref); 428 key_ref_put(key_ref);
414error: 429error:
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 */
76static int keyring_preparse(struct key_preparsed_payload *prep);
77static void keyring_free_preparse(struct key_preparsed_payload *prep);
76static int keyring_instantiate(struct key *keyring, 78static int keyring_instantiate(struct key *keyring,
77 struct key_preparsed_payload *prep); 79 struct key_preparsed_payload *prep);
78static void keyring_revoke(struct key *keyring); 80static void keyring_revoke(struct key *keyring);
@@ -84,6 +86,8 @@ static long keyring_read(const struct key *keyring,
84struct key_type key_type_keyring = { 86struct 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 */
132static 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 */
140static 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)
130static int keyring_instantiate(struct key *keyring, 149static 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
23static int request_key_auth_preparse(struct key_preparsed_payload *);
24static void request_key_auth_free_preparse(struct key_preparsed_payload *);
23static int request_key_auth_instantiate(struct key *, 25static int request_key_auth_instantiate(struct key *,
24 struct key_preparsed_payload *); 26 struct key_preparsed_payload *);
25static void request_key_auth_describe(const struct key *, struct seq_file *); 27static 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);
33struct key_type key_type_request_key_auth = { 35struct 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
47int request_key_auth_preparse(struct key_preparsed_payload *prep)
48{
49 return 0;
50}
51
52void 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);
27struct key_type key_type_user = { 27struct 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);
47struct key_type key_type_logon = { 49struct 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 = {
58EXPORT_SYMBOL_GPL(key_type_logon); 62EXPORT_SYMBOL_GPL(key_type_logon);
59 63
60/* 64/*
61 * instantiate a user defined key 65 * Preparse a user defined key payload
62 */ 66 */
63int user_instantiate(struct key *key, struct key_preparsed_payload *prep) 67int 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
88error:
89 return ret;
90} 85}
86EXPORT_SYMBOL_GPL(user_preparse);
91 87
92EXPORT_SYMBOL_GPL(user_instantiate); 88/*
89 * Free a preparse of a user defined key payload
90 */
91void user_free_preparse(struct key_preparsed_payload *prep)
92{
93 kfree(prep->payload[0]);
94}
95EXPORT_SYMBOL_GPL(user_free_preparse);
93 96
94/* 97/*
95 * update a user defined key 98 * update a user defined key