diff options
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/big_key.c | 41 | ||||
-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 |
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"); | |||
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/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 |