KEYS: big_key: Use key preparsing

Make use of key preparsing in the big key type so that quota size determination
can take place prior to keyring locking when a key is being added.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
This commit is contained in:
David Howells 2014-07-18 18:56:36 +01:00
parent 8a7a3eb4dd
commit 002edaf76f
2 changed files with 27 additions and 17 deletions

View File

@ -16,7 +16,8 @@
extern struct key_type key_type_big_key; extern struct key_type key_type_big_key;
extern int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep); extern int big_key_preparse(struct key_preparsed_payload *prep);
extern void big_key_free_preparse(struct key_preparsed_payload *prep);
extern void big_key_revoke(struct key *key); extern void big_key_revoke(struct key *key);
extern void big_key_destroy(struct key *key); extern void big_key_destroy(struct key *key);
extern void big_key_describe(const struct key *big_key, struct seq_file *m); extern void big_key_describe(const struct key *big_key, struct seq_file *m);

View File

@ -34,7 +34,9 @@ MODULE_LICENSE("GPL");
struct key_type key_type_big_key = { struct key_type key_type_big_key = {
.name = "big_key", .name = "big_key",
.def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
.instantiate = big_key_instantiate, .preparse = big_key_preparse,
.free_preparse = big_key_free_preparse,
.instantiate = generic_key_instantiate,
.match = user_match, .match = user_match,
.revoke = big_key_revoke, .revoke = big_key_revoke,
.destroy = big_key_destroy, .destroy = big_key_destroy,
@ -43,11 +45,11 @@ struct key_type key_type_big_key = {
}; };
/* /*
* Instantiate a big key * Preparse a big key
*/ */
int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) int big_key_preparse(struct key_preparsed_payload *prep)
{ {
struct path *path = (struct path *)&key->payload.data2; struct path *path = (struct path *)&prep->payload;
struct file *file; struct file *file;
ssize_t written; ssize_t written;
size_t datalen = prep->datalen; size_t datalen = prep->datalen;
@ -58,11 +60,9 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
goto error; goto error;
/* Set an arbitrary quota */ /* Set an arbitrary quota */
ret = key_payload_reserve(key, 16); prep->quotalen = 16;
if (ret < 0)
goto error;
key->type_data.x[1] = datalen; prep->type_data[1] = (void *)(unsigned long)datalen;
if (datalen > BIG_KEY_FILE_THRESHOLD) { if (datalen > BIG_KEY_FILE_THRESHOLD) {
/* Create a shmem file to store the data in. This will permit the data /* 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)
file = shmem_kernel_file_setup("", datalen, 0); file = shmem_kernel_file_setup("", datalen, 0);
if (IS_ERR(file)) { if (IS_ERR(file)) {
ret = PTR_ERR(file); ret = PTR_ERR(file);
goto err_quota; goto error;
} }
written = kernel_write(file, prep->data, prep->datalen, 0); written = kernel_write(file, prep->data, prep->datalen, 0);
@ -93,23 +93,32 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
} else { } else {
/* Just store the data in a buffer */ /* Just store the data in a buffer */
void *data = kmalloc(datalen, GFP_KERNEL); void *data = kmalloc(datalen, GFP_KERNEL);
if (!data) { if (!data)
ret = -ENOMEM; return -ENOMEM;
goto err_quota;
}
key->payload.data = memcpy(data, prep->data, prep->datalen); prep->payload[0] = memcpy(data, prep->data, prep->datalen);
} }
return 0; return 0;
err_fput: err_fput:
fput(file); fput(file);
err_quota:
key_payload_reserve(key, 0);
error: error:
return ret; return ret;
} }
/*
* Clear preparsement.
*/
void big_key_free_preparse(struct key_preparsed_payload *prep)
{
if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
struct path *path = (struct path *)&prep->payload;
path_put(path);
} else {
kfree(prep->payload[0]);
}
}
/* /*
* dispose of the links from a revoked keyring * dispose of the links from a revoked keyring
* - called with the key sem write-locked * - called with the key sem write-locked