diff options
Diffstat (limited to 'net/dns_resolver/dns_query.c')
| -rw-r--r-- | net/dns_resolver/dns_query.c | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c index c32be292c7e3..53da62984447 100644 --- a/net/dns_resolver/dns_query.c +++ b/net/dns_resolver/dns_query.c @@ -1,7 +1,7 @@ /* Upcall routine, designed to work as a key type and working through * /sbin/request-key to contact userspace when handling DNS queries. * - * See Documentation/networking/dns_resolver.txt + * See Documentation/networking/dns_resolver.rst * * Copyright (c) 2007 Igor Mammedov * Author(s): Igor Mammedov (niallain@gmail.com) @@ -32,14 +32,16 @@ * the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include <linux/module.h> #include <linux/slab.h> +#include <linux/cred.h> #include <linux/dns_resolver.h> #include <linux/err.h> +#include <net/net_namespace.h> + #include <keys/dns_resolver-type.h> #include <keys/user-type.h> @@ -47,15 +49,17 @@ /** * dns_query - Query the DNS + * @net: The network namespace to operate in. * @type: Query type (or NULL for straight host->IP lookup) * @name: Name to look up * @namelen: Length of name * @options: Request options (or NULL if no options) - * @_result: Where to place the returned data. + * @_result: Where to place the returned data (or NULL) * @_expiry: Where to store the result expiry time (or NULL) + * @invalidate: Always invalidate the key after use * - * The data will be returned in the pointer at *result, and the caller is - * responsible for freeing it. + * The data will be returned in the pointer at *result, if provided, and the + * caller is responsible for freeing it. * * The description should be of the form "[<query_type>:]<domain_name>", and * the options need to be appropriate for the query type requested. If no @@ -67,12 +71,13 @@ * * Returns the size of the result on success, -ve error code otherwise. */ -int dns_query(const char *type, const char *name, size_t namelen, - const char *options, char **_result, time_t *_expiry) +int dns_query(struct net *net, + const char *type, const char *name, size_t namelen, + const char *options, char **_result, time64_t *_expiry, + bool invalidate) { struct key *rkey; struct user_key_payload *upayload; - const struct cred *saved_cred; size_t typelen, desclen; char *desc, *cp; int ret, len; @@ -80,7 +85,7 @@ int dns_query(const char *type, const char *name, size_t namelen, kenter("%s,%*.*s,%zu,%s", type, (int)namelen, (int)namelen, name, namelen, options); - if (!name || namelen == 0 || !_result) + if (!name || namelen == 0) return -EINVAL; /* construct the query key description as "[<type>:]<name>" */ @@ -93,9 +98,7 @@ int dns_query(const char *type, const char *name, size_t namelen, desclen += typelen + 1; } - if (!namelen) - namelen = strlen(name); - if (namelen < 3) + if (namelen < 3 || namelen > 255) return -EINVAL; desclen += namelen + 1; @@ -120,9 +123,8 @@ int dns_query(const char *type, const char *name, size_t namelen, /* make the upcall, using special credentials to prevent the use of * add_key() to preinstall malicious redirections */ - saved_cred = override_creds(dns_resolver_cache); - rkey = request_key(&key_type_dns_resolver, desc, options); - revert_creds(saved_cred); + scoped_with_creds(dns_resolver_cache) + rkey = request_key_net(&key_type_dns_resolver, desc, net, options); kfree(desc); if (IS_ERR(rkey)) { ret = PTR_ERR(rkey); @@ -130,6 +132,7 @@ int dns_query(const char *type, const char *name, size_t namelen, } down_read(&rkey->sem); + set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags); rkey->perm |= KEY_USR_VIEW; ret = key_validate(rkey); @@ -137,26 +140,28 @@ int dns_query(const char *type, const char *name, size_t namelen, goto put; /* If the DNS server gave an error, return that to the caller */ - ret = rkey->type_data.x[0]; + ret = PTR_ERR(rkey->payload.data[dns_key_error]); if (ret) goto put; - upayload = rcu_dereference_protected(rkey->payload.data, - lockdep_is_held(&rkey->sem)); + upayload = user_key_payload_locked(rkey); len = upayload->datalen; - ret = -ENOMEM; - *_result = kmalloc(len + 1, GFP_KERNEL); - if (!*_result) - goto put; + if (_result) { + ret = -ENOMEM; + *_result = kmemdup_nul(upayload->data, len, GFP_KERNEL); + if (!*_result) + goto put; + } - memcpy(*_result, upayload->data, len + 1); if (_expiry) *_expiry = rkey->expiry; ret = len; put: up_read(&rkey->sem); + if (invalidate) + key_invalidate(rkey); key_put(rkey); out: kleave(" = %d", ret); |
