summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ceph/crypto.c26
-rw-r--r--net/dns_resolver/dns_key.c43
-rw-r--r--net/rxrpc/ar-key.c165
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);
}
/*