diff options
author | David Howells <dhowells@redhat.com> | 2014-07-18 18:56:36 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2014-07-22 21:46:47 +0100 |
commit | 002edaf76f09af658241029817f5ef66f6bef5e4 (patch) | |
tree | 2b04fa0c47ba3b9dfca97bb769cfae3aa0bbeffe /security/keys/big_key.c | |
parent | 8a7a3eb4ddbe7c7e639170a64adede7cbd5a9247 (diff) | |
download | lwn-002edaf76f09af658241029817f5ef66f6bef5e4.tar.gz lwn-002edaf76f09af658241029817f5ef66f6bef5e4.zip |
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>
Diffstat (limited to 'security/keys/big_key.c')
-rw-r--r-- | security/keys/big_key.c | 41 |
1 files changed, 25 insertions, 16 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"); struct key_type key_type_big_key = { .name = "big_key", .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, .revoke = big_key_revoke, .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; ssize_t written; size_t datalen = prep->datalen; @@ -58,11 +60,9 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) goto error; /* Set an arbitrary quota */ - ret = key_payload_reserve(key, 16); - if (ret < 0) - goto error; + prep->quotalen = 16; - key->type_data.x[1] = datalen; + prep->type_data[1] = (void *)(unsigned long)datalen; if (datalen > BIG_KEY_FILE_THRESHOLD) { /* 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); if (IS_ERR(file)) { ret = PTR_ERR(file); - goto err_quota; + goto error; } 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) } else { /* Just store the data in a buffer */ void *data = kmalloc(datalen, GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto err_quota; - } + if (!data) + return -ENOMEM; - key->payload.data = memcpy(data, prep->data, prep->datalen); + prep->payload[0] = memcpy(data, prep->data, prep->datalen); } return 0; err_fput: fput(file); -err_quota: - key_payload_reserve(key, 0); error: 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 * - called with the key sem write-locked */ |