LCOV - code coverage report
Current view: top level - net/dns_resolver - dns_query.c (source / functions) Hit Total Coverage
Test: Real Lines: 0 44 0.0 %
Date: 2020-10-17 15:46:16 Functions: 0 1 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       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 (niallain@gmail.com)
       8                 :            :  *              Steve French (sfrench@us.ibm.com)
       9                 :            :  *              Wang Lei (wang840925@gmail.com)
      10                 :            :  *              David Howells (dhowells@redhat.com)
      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, see <http://www.gnu.org/licenses/>.
      36                 :            :  */
      37                 :            : 
      38                 :            : #include <linux/module.h>
      39                 :            : #include <linux/slab.h>
      40                 :            : #include <linux/cred.h>
      41                 :            : #include <linux/dns_resolver.h>
      42                 :            : #include <linux/err.h>
      43                 :            : #include <net/net_namespace.h>
      44                 :            : 
      45                 :            : #include <keys/dns_resolver-type.h>
      46                 :            : #include <keys/user-type.h>
      47                 :            : 
      48                 :            : #include "internal.h"
      49                 :            : 
      50                 :            : /**
      51                 :            :  * dns_query - Query the DNS
      52                 :            :  * @net: The network namespace to operate in.
      53                 :            :  * @type: Query type (or NULL for straight host->IP lookup)
      54                 :            :  * @name: Name to look up
      55                 :            :  * @namelen: Length of name
      56                 :            :  * @options: Request options (or NULL if no options)
      57                 :            :  * @_result: Where to place the returned data (or NULL)
      58                 :            :  * @_expiry: Where to store the result expiry time (or NULL)
      59                 :            :  * @invalidate: Always invalidate the key after use
      60                 :            :  *
      61                 :            :  * The data will be returned in the pointer at *result, if provided, and the
      62                 :            :  * caller is responsible for freeing it.
      63                 :            :  *
      64                 :            :  * The description should be of the form "[<query_type>:]<domain_name>", and
      65                 :            :  * the options need to be appropriate for the query type requested.  If no
      66                 :            :  * query_type is given, then the query is a straight hostname to IP address
      67                 :            :  * lookup.
      68                 :            :  *
      69                 :            :  * The DNS resolution lookup is performed by upcalling to userspace by way of
      70                 :            :  * requesting a key of type dns_resolver.
      71                 :            :  *
      72                 :            :  * Returns the size of the result on success, -ve error code otherwise.
      73                 :            :  */
      74                 :          0 : int dns_query(struct net *net,
      75                 :            :               const char *type, const char *name, size_t namelen,
      76                 :            :               const char *options, char **_result, time64_t *_expiry,
      77                 :            :               bool invalidate)
      78                 :            : {
      79                 :            :         struct key *rkey;
      80                 :            :         struct user_key_payload *upayload;
      81                 :            :         const struct cred *saved_cred;
      82                 :            :         size_t typelen, desclen;
      83                 :            :         char *desc, *cp;
      84                 :            :         int ret, len;
      85                 :            : 
      86                 :          0 :         kenter("%s,%*.*s,%zu,%s",
      87                 :            :                type, (int)namelen, (int)namelen, name, namelen, options);
      88                 :            : 
      89                 :          0 :         if (!name || namelen == 0)
      90                 :            :                 return -EINVAL;
      91                 :            : 
      92                 :            :         /* construct the query key description as "[<type>:]<name>" */
      93                 :            :         typelen = 0;
      94                 :            :         desclen = 0;
      95                 :          0 :         if (type) {
      96                 :          0 :                 typelen = strlen(type);
      97                 :          0 :                 if (typelen < 1)
      98                 :            :                         return -EINVAL;
      99                 :          0 :                 desclen += typelen + 1;
     100                 :            :         }
     101                 :            : 
     102                 :          0 :         if (namelen < 3 || namelen > 255)
     103                 :            :                 return -EINVAL;
     104                 :          0 :         desclen += namelen + 1;
     105                 :            : 
     106                 :            :         desc = kmalloc(desclen, GFP_KERNEL);
     107                 :          0 :         if (!desc)
     108                 :            :                 return -ENOMEM;
     109                 :            : 
     110                 :            :         cp = desc;
     111                 :          0 :         if (type) {
     112                 :          0 :                 memcpy(cp, type, typelen);
     113                 :          0 :                 cp += typelen;
     114                 :          0 :                 *cp++ = ':';
     115                 :            :         }
     116                 :          0 :         memcpy(cp, name, namelen);
     117                 :          0 :         cp += namelen;
     118                 :          0 :         *cp = '\0';
     119                 :            : 
     120                 :          0 :         if (!options)
     121                 :            :                 options = "";
     122                 :          0 :         kdebug("call request_key(,%s,%s)", desc, options);
     123                 :            : 
     124                 :            :         /* make the upcall, using special credentials to prevent the use of
     125                 :            :          * add_key() to preinstall malicious redirections
     126                 :            :          */
     127                 :          0 :         saved_cred = override_creds(dns_resolver_cache);
     128                 :          0 :         rkey = request_key_net(&key_type_dns_resolver, desc, net, options);
     129                 :          0 :         revert_creds(saved_cred);
     130                 :          0 :         kfree(desc);
     131                 :          0 :         if (IS_ERR(rkey)) {
     132                 :            :                 ret = PTR_ERR(rkey);
     133                 :          0 :                 goto out;
     134                 :            :         }
     135                 :            : 
     136                 :          0 :         down_read(&rkey->sem);
     137                 :          0 :         set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags);
     138                 :          0 :         rkey->perm |= KEY_USR_VIEW;
     139                 :            : 
     140                 :          0 :         ret = key_validate(rkey);
     141                 :          0 :         if (ret < 0)
     142                 :            :                 goto put;
     143                 :            : 
     144                 :            :         /* If the DNS server gave an error, return that to the caller */
     145                 :          0 :         ret = PTR_ERR(rkey->payload.data[dns_key_error]);
     146                 :          0 :         if (ret)
     147                 :            :                 goto put;
     148                 :            : 
     149                 :            :         upayload = user_key_payload_locked(rkey);
     150                 :          0 :         len = upayload->datalen;
     151                 :            : 
     152                 :          0 :         if (_result) {
     153                 :            :                 ret = -ENOMEM;
     154                 :          0 :                 *_result = kmemdup_nul(upayload->data, len, GFP_KERNEL);
     155                 :          0 :                 if (!*_result)
     156                 :            :                         goto put;
     157                 :            :         }
     158                 :            : 
     159                 :          0 :         if (_expiry)
     160                 :          0 :                 *_expiry = rkey->expiry;
     161                 :            : 
     162                 :            :         ret = len;
     163                 :            : put:
     164                 :          0 :         up_read(&rkey->sem);
     165                 :          0 :         if (invalidate)
     166                 :          0 :                 key_invalidate(rkey);
     167                 :          0 :         key_put(rkey);
     168                 :            : out:
     169                 :          0 :         kleave(" = %d", ret);
     170                 :          0 :         return ret;
     171                 :            : }
     172                 :            : EXPORT_SYMBOL(dns_query);
    

Generated by: LCOV version 1.14