diff options
Diffstat (limited to 'net/dns_resolver/dns_key.c')
| -rw-r--r-- | net/dns_resolver/dns_key.c | 92 |
1 files changed, 87 insertions, 5 deletions
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index 400a04d5c9a1..739435a6af39 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
| 30 | #include <linux/keyctl.h> | 30 | #include <linux/keyctl.h> |
| 31 | #include <linux/err.h> | 31 | #include <linux/err.h> |
| 32 | #include <linux/seq_file.h> | ||
| 32 | #include <keys/dns_resolver-type.h> | 33 | #include <keys/dns_resolver-type.h> |
| 33 | #include <keys/user-type.h> | 34 | #include <keys/user-type.h> |
| 34 | #include "internal.h" | 35 | #include "internal.h" |
| @@ -43,6 +44,8 @@ MODULE_PARM_DESC(debug, "DNS Resolver debugging mask"); | |||
| 43 | 44 | ||
| 44 | const struct cred *dns_resolver_cache; | 45 | const struct cred *dns_resolver_cache; |
| 45 | 46 | ||
| 47 | #define DNS_ERRORNO_OPTION "dnserror" | ||
| 48 | |||
| 46 | /* | 49 | /* |
| 47 | * Instantiate a user defined key for dns_resolver. | 50 | * Instantiate a user defined key for dns_resolver. |
| 48 | * | 51 | * |
| @@ -59,9 +62,10 @@ static int | |||
| 59 | dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) | 62 | dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) |
| 60 | { | 63 | { |
| 61 | struct user_key_payload *upayload; | 64 | struct user_key_payload *upayload; |
| 65 | unsigned long derrno; | ||
| 62 | int ret; | 66 | int ret; |
| 63 | size_t result_len = 0; | 67 | size_t result_len = 0; |
| 64 | const char *data = _data, *opt; | 68 | const char *data = _data, *end, *opt; |
| 65 | 69 | ||
| 66 | kenter("%%%d,%s,'%s',%zu", | 70 | kenter("%%%d,%s,'%s',%zu", |
| 67 | key->serial, key->description, data, datalen); | 71 | key->serial, key->description, data, datalen); |
| @@ -71,13 +75,77 @@ dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) | |||
| 71 | datalen--; | 75 | datalen--; |
| 72 | 76 | ||
| 73 | /* deal with any options embedded in the data */ | 77 | /* deal with any options embedded in the data */ |
| 78 | end = data + datalen; | ||
| 74 | opt = memchr(data, '#', datalen); | 79 | opt = memchr(data, '#', datalen); |
| 75 | if (!opt) { | 80 | if (!opt) { |
| 76 | kdebug("no options currently supported"); | 81 | /* no options: the entire data is the result */ |
| 77 | return -EINVAL; | 82 | kdebug("no options"); |
| 83 | result_len = datalen; | ||
| 84 | } else { | ||
| 85 | const char *next_opt; | ||
| 86 | |||
| 87 | result_len = opt - data; | ||
| 88 | opt++; | ||
| 89 | kdebug("options: '%s'", opt); | ||
| 90 | do { | ||
| 91 | const char *eq; | ||
| 92 | int opt_len, opt_nlen, opt_vlen, tmp; | ||
| 93 | |||
| 94 | next_opt = memchr(opt, '#', end - opt) ?: end; | ||
| 95 | opt_len = next_opt - opt; | ||
| 96 | if (!opt_len) { | ||
| 97 | printk(KERN_WARNING | ||
| 98 | "Empty option to dns_resolver key %d\n", | ||
| 99 | key->serial); | ||
| 100 | return -EINVAL; | ||
| 101 | } | ||
| 102 | |||
| 103 | eq = memchr(opt, '=', opt_len) ?: end; | ||
| 104 | opt_nlen = eq - opt; | ||
| 105 | eq++; | ||
| 106 | opt_vlen = next_opt - eq; /* will be -1 if no value */ | ||
| 107 | |||
| 108 | tmp = opt_vlen >= 0 ? opt_vlen : 0; | ||
| 109 | kdebug("option '%*.*s' val '%*.*s'", | ||
| 110 | opt_nlen, opt_nlen, opt, tmp, tmp, eq); | ||
| 111 | |||
| 112 | /* see if it's an error number representing a DNS error | ||
| 113 | * that's to be recorded as the result in this key */ | ||
| 114 | if (opt_nlen == sizeof(DNS_ERRORNO_OPTION) - 1 && | ||
| 115 | memcmp(opt, DNS_ERRORNO_OPTION, opt_nlen) == 0) { | ||
| 116 | kdebug("dns error number option"); | ||
| 117 | if (opt_vlen <= 0) | ||
| 118 | goto bad_option_value; | ||
| 119 | |||
| 120 | ret = strict_strtoul(eq, 10, &derrno); | ||
| 121 | if (ret < 0) | ||
| 122 | goto bad_option_value; | ||
| 123 | |||
| 124 | if (derrno < 1 || derrno > 511) | ||
| 125 | goto bad_option_value; | ||
| 126 | |||
| 127 | kdebug("dns error no. = %lu", derrno); | ||
| 128 | key->type_data.x[0] = -derrno; | ||
| 129 | continue; | ||
| 130 | } | ||
| 131 | |||
| 132 | bad_option_value: | ||
| 133 | printk(KERN_WARNING | ||
| 134 | "Option '%*.*s' to dns_resolver key %d:" | ||
| 135 | " bad/missing value\n", | ||
| 136 | opt_nlen, opt_nlen, opt, key->serial); | ||
| 137 | return -EINVAL; | ||
| 138 | } while (opt = next_opt + 1, opt < end); | ||
| 139 | } | ||
| 140 | |||
| 141 | /* don't cache the result if we're caching an error saying there's no | ||
| 142 | * result */ | ||
| 143 | if (key->type_data.x[0]) { | ||
| 144 | kleave(" = 0 [h_error %ld]", key->type_data.x[0]); | ||
| 145 | return 0; | ||
| 78 | } | 146 | } |
| 79 | 147 | ||
| 80 | result_len = datalen; | 148 | kdebug("store result"); |
| 81 | ret = key_payload_reserve(key, result_len); | 149 | ret = key_payload_reserve(key, result_len); |
| 82 | if (ret < 0) | 150 | if (ret < 0) |
| 83 | return -EINVAL; | 151 | return -EINVAL; |
| @@ -135,13 +203,27 @@ no_match: | |||
| 135 | return ret; | 203 | return ret; |
| 136 | } | 204 | } |
| 137 | 205 | ||
| 206 | /* | ||
| 207 | * Describe a DNS key | ||
| 208 | */ | ||
| 209 | static void dns_resolver_describe(const struct key *key, struct seq_file *m) | ||
| 210 | { | ||
| 211 | int err = key->type_data.x[0]; | ||
| 212 | |||
| 213 | seq_puts(m, key->description); | ||
| 214 | if (err) | ||
| 215 | seq_printf(m, ": %d", err); | ||
| 216 | else | ||
| 217 | seq_printf(m, ": %u", key->datalen); | ||
| 218 | } | ||
| 219 | |||
| 138 | struct key_type key_type_dns_resolver = { | 220 | struct key_type key_type_dns_resolver = { |
| 139 | .name = "dns_resolver", | 221 | .name = "dns_resolver", |
| 140 | .instantiate = dns_resolver_instantiate, | 222 | .instantiate = dns_resolver_instantiate, |
| 141 | .match = dns_resolver_match, | 223 | .match = dns_resolver_match, |
| 142 | .revoke = user_revoke, | 224 | .revoke = user_revoke, |
| 143 | .destroy = user_destroy, | 225 | .destroy = user_destroy, |
| 144 | .describe = user_describe, | 226 | .describe = dns_resolver_describe, |
| 145 | .read = user_read, | 227 | .read = user_read, |
| 146 | }; | 228 | }; |
| 147 | 229 | ||
