Commit d46d4942 authored by David Howells's avatar David Howells

KEYS: DNS: Use key preparsing

Make use of key preparsing in the DNS resolver so that quota size determination
can take place prior to keyring locking when a key is being added.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarSteve Dickson <steved@redhat.com>
Acked-by: default avatarJeff Layton <jlayton@primarydata.com>
parent 7c3bec0a
...@@ -46,7 +46,7 @@ const struct cred *dns_resolver_cache; ...@@ -46,7 +46,7 @@ const struct cred *dns_resolver_cache;
#define DNS_ERRORNO_OPTION "dnserror" #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 * The data must be a NUL-terminated string, with the NUL char accounted in
* datalen. * datalen.
...@@ -58,17 +58,15 @@ const struct cred *dns_resolver_cache; ...@@ -58,17 +58,15 @@ const struct cred *dns_resolver_cache;
* "ip1,ip2,...#foo=bar" * "ip1,ip2,...#foo=bar"
*/ */
static int 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; struct user_key_payload *upayload;
unsigned long derrno; unsigned long derrno;
int ret; int ret;
size_t datalen = prep->datalen, result_len = 0; int datalen = prep->datalen, result_len = 0;
const char *data = prep->data, *end, *opt; const char *data = prep->data, *end, *opt;
kenter("%%%d,%s,'%*.*s',%zu", kenter("'%*.*s',%u", datalen, datalen, data, datalen);
key->serial, key->description,
(int)datalen, (int)datalen, data, datalen);
if (datalen <= 1 || !data || data[datalen - 1] != '\0') if (datalen <= 1 || !data || data[datalen - 1] != '\0')
return -EINVAL; return -EINVAL;
...@@ -95,8 +93,7 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) ...@@ -95,8 +93,7 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep)
opt_len = next_opt - opt; opt_len = next_opt - opt;
if (!opt_len) { if (!opt_len) {
printk(KERN_WARNING printk(KERN_WARNING
"Empty option to dns_resolver key %d\n", "Empty option to dns_resolver key\n");
key->serial);
return -EINVAL; return -EINVAL;
} }
...@@ -125,30 +122,28 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) ...@@ -125,30 +122,28 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep)
goto bad_option_value; goto bad_option_value;
kdebug("dns error no. = %lu", derrno); kdebug("dns error no. = %lu", derrno);
key->type_data.x[0] = -derrno; prep->type_data[0] = ERR_PTR(-derrno);
continue; continue;
} }
bad_option_value: bad_option_value:
printk(KERN_WARNING printk(KERN_WARNING
"Option '%*.*s' to dns_resolver key %d:" "Option '%*.*s' to dns_resolver key:"
" bad/missing value\n", " bad/missing value\n",
opt_nlen, opt_nlen, opt, key->serial); opt_nlen, opt_nlen, opt);
return -EINVAL; return -EINVAL;
} while (opt = next_opt + 1, opt < end); } while (opt = next_opt + 1, opt < end);
} }
/* don't cache the result if we're caching an error saying there's no /* don't cache the result if we're caching an error saying there's no
* result */ * result */
if (key->type_data.x[0]) { if (prep->type_data[0]) {
kleave(" = 0 [h_error %ld]", key->type_data.x[0]); kleave(" = 0 [h_error %ld]", PTR_ERR(prep->type_data[0]));
return 0; return 0;
} }
kdebug("store result"); kdebug("store result");
ret = key_payload_reserve(key, result_len); prep->quotalen = result_len;
if (ret < 0)
return -EINVAL;
upayload = kmalloc(sizeof(*upayload) + result_len + 1, GFP_KERNEL); upayload = kmalloc(sizeof(*upayload) + result_len + 1, GFP_KERNEL);
if (!upayload) { if (!upayload) {
...@@ -159,12 +154,22 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) ...@@ -159,12 +154,22 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep)
upayload->datalen = result_len; upayload->datalen = result_len;
memcpy(upayload->data, data, result_len); memcpy(upayload->data, data, result_len);
upayload->data[result_len] = '\0'; upayload->data[result_len] = '\0';
rcu_assign_pointer(key->payload.data, upayload);
prep->payload[0] = upayload;
kleave(" = 0"); kleave(" = 0");
return 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 description is of the form "[<type>:]<domain_name>"
* *
...@@ -234,7 +239,9 @@ static long dns_resolver_read(const struct key *key, ...@@ -234,7 +239,9 @@ static long dns_resolver_read(const struct key *key,
struct key_type key_type_dns_resolver = { struct key_type key_type_dns_resolver = {
.name = "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, .match = dns_resolver_match,
.revoke = user_revoke, .revoke = user_revoke,
.destroy = user_destroy, .destroy = user_destroy,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment