Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d46d4942 authored by David Howells's avatar David Howells
Browse files

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
Loading
Loading
Loading
Loading
+25 −18
Original line number Diff line number Diff line
@@ -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,12 +154,22 @@ 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>"
 *
@@ -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,