[CIFS] clean up upcall handling for dns_resolver keys
Steve French [Tue, 23 Sep 2008 18:46:07 +0000 (18:46 +0000)]
We're given the datalen in the downcall, so there's no need to do any
calls to strlen(). Just keep track of the datalen in the key. Finally,
add a sanity check of the data in the downcall to make sure that it
looks like a real IP address.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>

fs/cifs/dns_resolve.c

index a2e0673..1e0c1bd 100644 (file)
 #include "cifsproto.h"
 #include "cifs_debug.h"
 
-static int dns_resolver_instantiate(struct key *key, const void *data,
+/* Checks if supplied name is IP address
+ * returns:
+ *             1 - name is IP
+ *             0 - name is not IP
+ */
+static int
+is_ip(const char *name)
+{
+       int rc;
+       struct sockaddr_in sin_server;
+       struct sockaddr_in6 sin_server6;
+
+       rc = cifs_inet_pton(AF_INET, name,
+                       &sin_server.sin_addr.s_addr);
+
+       if (rc <= 0) {
+               /* not ipv4 address, try ipv6 */
+               rc = cifs_inet_pton(AF_INET6, name,
+                               &sin_server6.sin6_addr.in6_u);
+               if (rc > 0)
+                       return 1;
+       } else {
+               return 1;
+       }
+       /* we failed translating address */
+       return 0;
+}
+
+static int
+dns_resolver_instantiate(struct key *key, const void *data,
                size_t datalen)
 {
        int rc = 0;
        char *ip;
 
-       ip = kmalloc(datalen+1, GFP_KERNEL);
+       ip = kmalloc(datalen + 1, GFP_KERNEL);
        if (!ip)
                return -ENOMEM;
 
        memcpy(ip, data, datalen);
        ip[datalen] = '\0';
 
+       /* make sure this looks like an address */
+       if (!is_ip((const char *) ip)) {
+               kfree(ip);
+               return -EINVAL;
+       }
+
+       key->type_data.x[0] = datalen;
        rcu_assign_pointer(key->payload.data, ip);
 
        return rc;
@@ -62,33 +98,6 @@ struct key_type key_type_dns_resolver = {
        .match       = user_match,
 };
 
-/* Checks if supplied name is IP address
- * returns:
- *             1 - name is IP
- *             0 - name is not IP
- */
-static int is_ip(const char *name)
-{
-       int rc;
-       struct sockaddr_in sin_server;
-       struct sockaddr_in6 sin_server6;
-
-       rc = cifs_inet_pton(AF_INET, name,
-                       &sin_server.sin_addr.s_addr);
-
-       if (rc <= 0) {
-               /* not ipv4 address, try ipv6 */
-               rc = cifs_inet_pton(AF_INET6, name,
-                               &sin_server6.sin6_addr.in6_u);
-               if (rc > 0)
-                       return 1;
-       } else {
-               return 1;
-       }
-       /* we failed translating address */
-       return 0;
-}
-
 /* Resolves server name to ip address.
  * input:
  *     unc - server UNC
@@ -140,6 +149,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
 
        rkey = request_key(&key_type_dns_resolver, name, "");
        if (!IS_ERR(rkey)) {
+               len = rkey->type_data.x[0];
                data = rkey->payload.data;
        } else {
                cERROR(1, ("%s: unable to resolve: %s", __func__, name));
@@ -148,11 +158,9 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
 
 skip_upcall:
        if (data) {
-               len = strlen(data);
-               *ip_addr = kmalloc(len+1, GFP_KERNEL);
+               *ip_addr = kmalloc(len + 1, GFP_KERNEL);
                if (*ip_addr) {
-                       memcpy(*ip_addr, data, len);
-                       (*ip_addr)[len] = '\0';
+                       memcpy(*ip_addr, data, len + 1);
                        if (!IS_ERR(rkey))
                                cFYI(1, ("%s: resolved: %s to %s", __func__,
                                                        name,