Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/dns_resolver/dns_query.c
15109 views
1
/* Upcall routine, designed to work as a key type and working through
2
* /sbin/request-key to contact userspace when handling DNS queries.
3
*
4
* See Documentation/networking/dns_resolver.txt
5
*
6
* Copyright (c) 2007 Igor Mammedov
7
* Author(s): Igor Mammedov ([email protected])
8
* Steve French ([email protected])
9
* Wang Lei ([email protected])
10
* David Howells ([email protected])
11
*
12
* The upcall wrapper used to make an arbitrary DNS query.
13
*
14
* This function requires the appropriate userspace tool dns.upcall to be
15
* installed and something like the following lines should be added to the
16
* /etc/request-key.conf file:
17
*
18
* create dns_resolver * * /sbin/dns.upcall %k
19
*
20
* For example to use this module to query AFSDB RR:
21
*
22
* create dns_resolver afsdb:* * /sbin/dns.afsdb %k
23
*
24
* This library is free software; you can redistribute it and/or modify
25
* it under the terms of the GNU Lesser General Public License as published
26
* by the Free Software Foundation; either version 2.1 of the License, or
27
* (at your option) any later version.
28
*
29
* This library is distributed in the hope that it will be useful,
30
* but WITHOUT ANY WARRANTY; without even the implied warranty of
31
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
32
* the GNU Lesser General Public License for more details.
33
*
34
* You should have received a copy of the GNU Lesser General Public License
35
* along with this library; if not, write to the Free Software
36
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37
*/
38
39
#include <linux/module.h>
40
#include <linux/slab.h>
41
#include <linux/dns_resolver.h>
42
#include <linux/err.h>
43
#include <keys/dns_resolver-type.h>
44
#include <keys/user-type.h>
45
46
#include "internal.h"
47
48
/**
49
* dns_query - Query the DNS
50
* @type: Query type (or NULL for straight host->IP lookup)
51
* @name: Name to look up
52
* @namelen: Length of name
53
* @options: Request options (or NULL if no options)
54
* @_result: Where to place the returned data.
55
* @_expiry: Where to store the result expiry time (or NULL)
56
*
57
* The data will be returned in the pointer at *result, and the caller is
58
* responsible for freeing it.
59
*
60
* The description should be of the form "[<query_type>:]<domain_name>", and
61
* the options need to be appropriate for the query type requested. If no
62
* query_type is given, then the query is a straight hostname to IP address
63
* lookup.
64
*
65
* The DNS resolution lookup is performed by upcalling to userspace by way of
66
* requesting a key of type dns_resolver.
67
*
68
* Returns the size of the result on success, -ve error code otherwise.
69
*/
70
int dns_query(const char *type, const char *name, size_t namelen,
71
const char *options, char **_result, time_t *_expiry)
72
{
73
struct key *rkey;
74
struct user_key_payload *upayload;
75
const struct cred *saved_cred;
76
size_t typelen, desclen;
77
char *desc, *cp;
78
int ret, len;
79
80
kenter("%s,%*.*s,%zu,%s",
81
type, (int)namelen, (int)namelen, name, namelen, options);
82
83
if (!name || namelen == 0 || !_result)
84
return -EINVAL;
85
86
/* construct the query key description as "[<type>:]<name>" */
87
typelen = 0;
88
desclen = 0;
89
if (type) {
90
typelen = strlen(type);
91
if (typelen < 1)
92
return -EINVAL;
93
desclen += typelen + 1;
94
}
95
96
if (!namelen)
97
namelen = strlen(name);
98
if (namelen < 3)
99
return -EINVAL;
100
desclen += namelen + 1;
101
102
desc = kmalloc(desclen, GFP_KERNEL);
103
if (!desc)
104
return -ENOMEM;
105
106
cp = desc;
107
if (type) {
108
memcpy(cp, type, typelen);
109
cp += typelen;
110
*cp++ = ':';
111
}
112
memcpy(cp, name, namelen);
113
cp += namelen;
114
*cp = '\0';
115
116
if (!options)
117
options = "";
118
kdebug("call request_key(,%s,%s)", desc, options);
119
120
/* make the upcall, using special credentials to prevent the use of
121
* add_key() to preinstall malicious redirections
122
*/
123
saved_cred = override_creds(dns_resolver_cache);
124
rkey = request_key(&key_type_dns_resolver, desc, options);
125
revert_creds(saved_cred);
126
kfree(desc);
127
if (IS_ERR(rkey)) {
128
ret = PTR_ERR(rkey);
129
goto out;
130
}
131
132
down_read(&rkey->sem);
133
rkey->perm |= KEY_USR_VIEW;
134
135
ret = key_validate(rkey);
136
if (ret < 0)
137
goto put;
138
139
/* If the DNS server gave an error, return that to the caller */
140
ret = rkey->type_data.x[0];
141
if (ret)
142
goto put;
143
144
upayload = rcu_dereference_protected(rkey->payload.data,
145
lockdep_is_held(&rkey->sem));
146
len = upayload->datalen;
147
148
ret = -ENOMEM;
149
*_result = kmalloc(len + 1, GFP_KERNEL);
150
if (!*_result)
151
goto put;
152
153
memcpy(*_result, upayload->data, len + 1);
154
if (_expiry)
155
*_expiry = rkey->expiry;
156
157
ret = len;
158
put:
159
up_read(&rkey->sem);
160
key_put(rkey);
161
out:
162
kleave(" = %d", ret);
163
return ret;
164
}
165
EXPORT_SYMBOL(dns_query);
166
167