diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/crypto.c | 26 | ||||
-rw-r--r-- | net/dns_resolver/dns_key.c | 43 | ||||
-rw-r--r-- | net/rxrpc/ar-key.c | 165 |
3 files changed, 136 insertions, 98 deletions
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 6e7a236525b6..ffeba8f9dda9 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -8,6 +8,7 @@ #include <linux/key-type.h> #include <keys/ceph-type.h> +#include <keys/user-type.h> #include <linux/ceph/decode.h> #include "crypto.h" @@ -423,8 +424,7 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, } } -static int ceph_key_instantiate(struct key *key, - struct key_preparsed_payload *prep) +static int ceph_key_preparse(struct key_preparsed_payload *prep) { struct ceph_crypto_key *ckey; size_t datalen = prep->datalen; @@ -435,10 +435,6 @@ static int ceph_key_instantiate(struct key *key, if (datalen <= 0 || datalen > 32767 || !prep->data) goto err; - ret = key_payload_reserve(key, datalen); - if (ret < 0) - goto err; - ret = -ENOMEM; ckey = kmalloc(sizeof(*ckey), GFP_KERNEL); if (!ckey) @@ -450,7 +446,8 @@ static int ceph_key_instantiate(struct key *key, if (ret < 0) goto err_ckey; - key->payload.data = ckey; + prep->payload[0] = ckey; + prep->quotalen = datalen; return 0; err_ckey: @@ -459,12 +456,15 @@ err: return ret; } -static int ceph_key_match(const struct key *key, const void *description) +static void ceph_key_free_preparse(struct key_preparsed_payload *prep) { - return strcmp(key->description, description) == 0; + struct ceph_crypto_key *ckey = prep->payload[0]; + ceph_crypto_key_destroy(ckey); + kfree(ckey); } -static void ceph_key_destroy(struct key *key) { +static void ceph_key_destroy(struct key *key) +{ struct ceph_crypto_key *ckey = key->payload.data; ceph_crypto_key_destroy(ckey); @@ -473,8 +473,10 @@ static void ceph_key_destroy(struct key *key) { struct key_type key_type_ceph = { .name = "ceph", - .instantiate = ceph_key_instantiate, - .match = ceph_key_match, + .preparse = ceph_key_preparse, + .free_preparse = ceph_key_free_preparse, + .instantiate = generic_key_instantiate, + .match = user_match, .destroy = ceph_key_destroy, }; diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index bf8584339048..f380b2c58178 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -46,7 +46,7 @@ const struct cred *dns_resolver_cache; #define DNS_ERRORNO_OPTION "dnserror" /* - * Instantiate a user defined key for dns_resolver. + * Preparse instantiation data for a dns_resolver key. * * The data must be a NUL-terminated string, with the NUL char accounted in * datalen. @@ -58,17 +58,15 @@ const struct cred *dns_resolver_cache; * "ip1,ip2,...#foo=bar" */ static int -dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) +dns_resolver_preparse(struct key_preparsed_payload *prep) { struct user_key_payload *upayload; unsigned long derrno; int ret; - size_t datalen = prep->datalen, result_len = 0; + int datalen = prep->datalen, result_len = 0; const char *data = prep->data, *end, *opt; - kenter("%%%d,%s,'%*.*s',%zu", - key->serial, key->description, - (int)datalen, (int)datalen, data, datalen); + kenter("'%*.*s',%u", datalen, datalen, data, datalen); if (datalen <= 1 || !data || data[datalen - 1] != '\0') return -EINVAL; @@ -95,8 +93,7 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) opt_len = next_opt - opt; if (!opt_len) { printk(KERN_WARNING - "Empty option to dns_resolver key %d\n", - key->serial); + "Empty option to dns_resolver key\n"); return -EINVAL; } @@ -125,30 +122,28 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) goto bad_option_value; kdebug("dns error no. = %lu", derrno); - key->type_data.x[0] = -derrno; + prep->type_data[0] = ERR_PTR(-derrno); continue; } bad_option_value: printk(KERN_WARNING - "Option '%*.*s' to dns_resolver key %d:" + "Option '%*.*s' to dns_resolver key:" " bad/missing value\n", - opt_nlen, opt_nlen, opt, key->serial); + opt_nlen, opt_nlen, opt); return -EINVAL; } while (opt = next_opt + 1, opt < end); } /* don't cache the result if we're caching an error saying there's no * result */ - if (key->type_data.x[0]) { - kleave(" = 0 [h_error %ld]", key->type_data.x[0]); + if (prep->type_data[0]) { + kleave(" = 0 [h_error %ld]", PTR_ERR(prep->type_data[0])); return 0; } kdebug("store result"); - ret = key_payload_reserve(key, result_len); - if (ret < 0) - return -EINVAL; + prep->quotalen = result_len; upayload = kmalloc(sizeof(*upayload) + result_len + 1, GFP_KERNEL); if (!upayload) { @@ -159,13 +154,23 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) upayload->datalen = result_len; memcpy(upayload->data, data, result_len); upayload->data[result_len] = '\0'; - rcu_assign_pointer(key->payload.data, upayload); + prep->payload[0] = upayload; kleave(" = 0"); return 0; } /* + * Clean up the preparse data + */ +static void dns_resolver_free_preparse(struct key_preparsed_payload *prep) +{ + pr_devel("==>%s()\n", __func__); + + kfree(prep->payload[0]); +} + +/* * The description is of the form "[<type>:]<domain_name>" * * The domain name may be a simple name or an absolute domain name (which @@ -234,7 +239,9 @@ static long dns_resolver_read(const struct key *key, struct key_type key_type_dns_resolver = { .name = "dns_resolver", - .instantiate = dns_resolver_instantiate, + .preparse = dns_resolver_preparse, + .free_preparse = dns_resolver_free_preparse, + .instantiate = generic_key_instantiate, .match = dns_resolver_match, .revoke = user_revoke, .destroy = user_destroy, diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 0ad080790a32..3907add75932 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -26,8 +26,10 @@ #include "ar-internal.h" static int rxrpc_vet_description_s(const char *); -static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); -static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); +static int rxrpc_preparse(struct key_preparsed_payload *); +static int rxrpc_preparse_s(struct key_preparsed_payload *); +static void rxrpc_free_preparse(struct key_preparsed_payload *); +static void rxrpc_free_preparse_s(struct key_preparsed_payload *); static void rxrpc_destroy(struct key *); static void rxrpc_destroy_s(struct key *); static void rxrpc_describe(const struct key *, struct seq_file *); @@ -39,7 +41,9 @@ static long rxrpc_read(const struct key *, char __user *, size_t); */ struct key_type key_type_rxrpc = { .name = "rxrpc", - .instantiate = rxrpc_instantiate, + .preparse = rxrpc_preparse, + .free_preparse = rxrpc_free_preparse, + .instantiate = generic_key_instantiate, .match = user_match, .destroy = rxrpc_destroy, .describe = rxrpc_describe, @@ -54,7 +58,9 @@ EXPORT_SYMBOL(key_type_rxrpc); struct key_type key_type_rxrpc_s = { .name = "rxrpc_s", .vet_description = rxrpc_vet_description_s, - .instantiate = rxrpc_instantiate_s, + .preparse = rxrpc_preparse_s, + .free_preparse = rxrpc_free_preparse_s, + .instantiate = generic_key_instantiate, .match = user_match, .destroy = rxrpc_destroy_s, .describe = rxrpc_describe, @@ -81,13 +87,13 @@ static int rxrpc_vet_description_s(const char *desc) * parse an RxKAD type XDR format token * - the caller guarantees we have at least 4 words */ -static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, - unsigned int toklen) +static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep, + size_t datalen, + const __be32 *xdr, unsigned int toklen) { struct rxrpc_key_token *token, **pptoken; size_t plen; u32 tktlen; - int ret; _enter(",{%x,%x,%x,%x},%u", ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]), @@ -103,9 +109,7 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, return -EKEYREJECTED; plen = sizeof(*token) + sizeof(*token->kad) + tktlen; - ret = key_payload_reserve(key, key->datalen + plen); - if (ret < 0) - return ret; + prep->quotalen = datalen + plen; plen -= sizeof(*token); token = kzalloc(sizeof(*token), GFP_KERNEL); @@ -146,16 +150,16 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, token->kad->ticket[6], token->kad->ticket[7]); /* count the number of tokens attached */ - key->type_data.x[0]++; + prep->type_data[0] = (void *)((unsigned long)prep->type_data[0] + 1); /* attach the data */ - for (pptoken = (struct rxrpc_key_token **)&key->payload.data; + for (pptoken = (struct rxrpc_key_token **)&prep->payload[0]; *pptoken; pptoken = &(*pptoken)->next) continue; *pptoken = token; - if (token->kad->expiry < key->expiry) - key->expiry = token->kad->expiry; + if (token->kad->expiry < prep->expiry) + prep->expiry = token->kad->expiry; _leave(" = 0"); return 0; @@ -418,8 +422,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, * parse an RxK5 type XDR format token * - the caller guarantees we have at least 4 words */ -static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr, - unsigned int toklen) +static int rxrpc_preparse_xdr_rxk5(struct key_preparsed_payload *prep, + size_t datalen, + const __be32 *xdr, unsigned int toklen) { struct rxrpc_key_token *token, **pptoken; struct rxk5_key *rxk5; @@ -432,9 +437,7 @@ static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr, /* reserve some payload space for this subkey - the length of the token * is a reasonable approximation */ - ret = key_payload_reserve(key, key->datalen + toklen); - if (ret < 0) - return ret; + prep->quotalen = datalen + toklen; token = kzalloc(sizeof(*token), GFP_KERNEL); if (!token) @@ -520,14 +523,14 @@ static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr, if (toklen != 0) goto inval; - /* attach the payload to the key */ - for (pptoken = (struct rxrpc_key_token **)&key->payload.data; + /* attach the payload */ + for (pptoken = (struct rxrpc_key_token **)&prep->payload[0]; *pptoken; pptoken = &(*pptoken)->next) continue; *pptoken = token; - if (token->kad->expiry < key->expiry) - key->expiry = token->kad->expiry; + if (token->kad->expiry < prep->expiry) + prep->expiry = token->kad->expiry; _leave(" = 0"); return 0; @@ -545,16 +548,17 @@ error: * attempt to parse the data as the XDR format * - the caller guarantees we have more than 7 words */ -static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datalen) +static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) { - const __be32 *xdr = data, *token; + const __be32 *xdr = prep->data, *token; const char *cp; unsigned int len, tmp, loop, ntoken, toklen, sec_ix; + size_t datalen = prep->datalen; int ret; _enter(",{%x,%x,%x,%x},%zu", ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]), - datalen); + prep->datalen); if (datalen > AFSTOKEN_LENGTH_MAX) goto not_xdr; @@ -635,13 +639,13 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal switch (sec_ix) { case RXRPC_SECURITY_RXKAD: - ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen); + ret = rxrpc_preparse_xdr_rxkad(prep, datalen, xdr, toklen); if (ret != 0) goto error; break; case RXRPC_SECURITY_RXK5: - ret = rxrpc_instantiate_xdr_rxk5(key, xdr, toklen); + ret = rxrpc_preparse_xdr_rxk5(prep, datalen, xdr, toklen); if (ret != 0) goto error; break; @@ -665,8 +669,9 @@ error: } /* - * instantiate an rxrpc defined key - * data should be of the form: + * Preparse an rxrpc defined key. + * + * Data should be of the form: * OFFSET LEN CONTENT * 0 4 key interface version number * 4 2 security index (type) @@ -678,7 +683,7 @@ error: * * if no data is provided, then a no-security key is made */ -static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) +static int rxrpc_preparse(struct key_preparsed_payload *prep) { const struct rxrpc_key_data_v1 *v1; struct rxrpc_key_token *token, **pp; @@ -686,7 +691,7 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep u32 kver; int ret; - _enter("{%x},,%zu", key_serial(key), prep->datalen); + _enter("%zu", prep->datalen); /* handle a no-security key */ if (!prep->data && prep->datalen == 0) @@ -694,7 +699,7 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep /* determine if the XDR payload format is being used */ if (prep->datalen > 7 * 4) { - ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); + ret = rxrpc_preparse_xdr(prep); if (ret != -EPROTO) return ret; } @@ -743,9 +748,7 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep goto error; plen = sizeof(*token->kad) + v1->ticket_length; - ret = key_payload_reserve(key, plen + sizeof(*token)); - if (ret < 0) - goto error; + prep->quotalen = plen + sizeof(*token); ret = -ENOMEM; token = kzalloc(sizeof(*token), GFP_KERNEL); @@ -762,15 +765,16 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep memcpy(&token->kad->session_key, &v1->session_key, 8); memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length); - /* attach the data */ - key->type_data.x[0]++; + /* count the number of tokens attached */ + prep->type_data[0] = (void *)((unsigned long)prep->type_data[0] + 1); - pp = (struct rxrpc_key_token **)&key->payload.data; + /* attach the data */ + pp = (struct rxrpc_key_token **)&prep->payload[0]; while (*pp) pp = &(*pp)->next; *pp = token; - if (token->kad->expiry < key->expiry) - key->expiry = token->kad->expiry; + if (token->kad->expiry < prep->expiry) + prep->expiry = token->kad->expiry; token = NULL; ret = 0; @@ -781,20 +785,55 @@ error: } /* - * instantiate a server secret key - * data should be a pointer to the 8-byte secret key + * Free token list. */ -static int rxrpc_instantiate_s(struct key *key, - struct key_preparsed_payload *prep) +static void rxrpc_free_token_list(struct rxrpc_key_token *token) +{ + struct rxrpc_key_token *next; + + for (; token; token = next) { + next = token->next; + switch (token->security_index) { + case RXRPC_SECURITY_RXKAD: + kfree(token->kad); + break; + case RXRPC_SECURITY_RXK5: + if (token->k5) + rxrpc_rxk5_free(token->k5); + break; + default: + printk(KERN_ERR "Unknown token type %x on rxrpc key\n", + token->security_index); + BUG(); + } + + kfree(token); + } +} + +/* + * Clean up preparse data. + */ +static void rxrpc_free_preparse(struct key_preparsed_payload *prep) +{ + rxrpc_free_token_list(prep->payload[0]); +} + +/* + * Preparse a server secret key. + * + * The data should be the 8-byte secret key. + */ +static int rxrpc_preparse_s(struct key_preparsed_payload *prep) { struct crypto_blkcipher *ci; - _enter("{%x},,%zu", key_serial(key), prep->datalen); + _enter("%zu", prep->datalen); if (prep->datalen != 8) return -EINVAL; - memcpy(&key->type_data, prep->data, 8); + memcpy(&prep->type_data, prep->data, 8); ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(ci)) { @@ -805,36 +844,26 @@ static int rxrpc_instantiate_s(struct key *key, if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) BUG(); - key->payload.data = ci; + prep->payload[0] = ci; _leave(" = 0"); return 0; } /* + * Clean up preparse data. + */ +static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep) +{ + if (prep->payload[0]) + crypto_free_blkcipher(prep->payload[0]); +} + +/* * dispose of the data dangling from the corpse of a rxrpc key */ static void rxrpc_destroy(struct key *key) { - struct rxrpc_key_token *token; - - while ((token = key->payload.data)) { - key->payload.data = token->next; - switch (token->security_index) { - case RXRPC_SECURITY_RXKAD: - kfree(token->kad); - break; - case RXRPC_SECURITY_RXK5: - if (token->k5) - rxrpc_rxk5_free(token->k5); - break; - default: - printk(KERN_ERR "Unknown token type %x on rxrpc key\n", - token->security_index); - BUG(); - } - - kfree(token); - } + rxrpc_free_token_list(key->payload.data); } /* |