0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #include <linux/module.h>
0039 #include <linux/slab.h>
0040 #include <linux/cred.h>
0041 #include <linux/dns_resolver.h>
0042 #include <linux/err.h>
0043 #include <net/net_namespace.h>
0044
0045 #include <keys/dns_resolver-type.h>
0046 #include <keys/user-type.h>
0047
0048 #include "internal.h"
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 int dns_query(struct net *net,
0075 const char *type, const char *name, size_t namelen,
0076 const char *options, char **_result, time64_t *_expiry,
0077 bool invalidate)
0078 {
0079 struct key *rkey;
0080 struct user_key_payload *upayload;
0081 const struct cred *saved_cred;
0082 size_t typelen, desclen;
0083 char *desc, *cp;
0084 int ret, len;
0085
0086 kenter("%s,%*.*s,%zu,%s",
0087 type, (int)namelen, (int)namelen, name, namelen, options);
0088
0089 if (!name || namelen == 0)
0090 return -EINVAL;
0091
0092
0093 typelen = 0;
0094 desclen = 0;
0095 if (type) {
0096 typelen = strlen(type);
0097 if (typelen < 1)
0098 return -EINVAL;
0099 desclen += typelen + 1;
0100 }
0101
0102 if (namelen < 3 || namelen > 255)
0103 return -EINVAL;
0104 desclen += namelen + 1;
0105
0106 desc = kmalloc(desclen, GFP_KERNEL);
0107 if (!desc)
0108 return -ENOMEM;
0109
0110 cp = desc;
0111 if (type) {
0112 memcpy(cp, type, typelen);
0113 cp += typelen;
0114 *cp++ = ':';
0115 }
0116 memcpy(cp, name, namelen);
0117 cp += namelen;
0118 *cp = '\0';
0119
0120 if (!options)
0121 options = "";
0122 kdebug("call request_key(,%s,%s)", desc, options);
0123
0124
0125
0126
0127 saved_cred = override_creds(dns_resolver_cache);
0128 rkey = request_key_net(&key_type_dns_resolver, desc, net, options);
0129 revert_creds(saved_cred);
0130 kfree(desc);
0131 if (IS_ERR(rkey)) {
0132 ret = PTR_ERR(rkey);
0133 goto out;
0134 }
0135
0136 down_read(&rkey->sem);
0137 set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags);
0138 rkey->perm |= KEY_USR_VIEW;
0139
0140 ret = key_validate(rkey);
0141 if (ret < 0)
0142 goto put;
0143
0144
0145 ret = PTR_ERR(rkey->payload.data[dns_key_error]);
0146 if (ret)
0147 goto put;
0148
0149 upayload = user_key_payload_locked(rkey);
0150 len = upayload->datalen;
0151
0152 if (_result) {
0153 ret = -ENOMEM;
0154 *_result = kmemdup_nul(upayload->data, len, GFP_KERNEL);
0155 if (!*_result)
0156 goto put;
0157 }
0158
0159 if (_expiry)
0160 *_expiry = rkey->expiry;
0161
0162 ret = len;
0163 put:
0164 up_read(&rkey->sem);
0165 if (invalidate)
0166 key_invalidate(rkey);
0167 key_put(rkey);
0168 out:
0169 kleave(" = %d", ret);
0170 return ret;
0171 }
0172 EXPORT_SYMBOL(dns_query);