[linux-cifs-client] [PATCH] cifs: clean up upcall handling for dns_resolver keys

Jeff Layton jlayton at redhat.com
Wed Aug 27 14:05:06 GMT 2008


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. Also,
declare a destroy routine to make sure that the kmalloc that's done in
the instantiate routine is cleaned up. Finally, add a sanity check of
the data in the downcall to make sure that it looks like a real IP
address.

This patch should replace the patch I sent yesterday to add the
destroy routine for dns_resolver upcall, and should apply cleanly
on top of the patch posted yesterday to get rid of the rcu assignments
in the cifs key instantiate routines.

Signed-off-by: Jeff Layton <jlayton at redhat.com>
Acked-by: David Howells <dhowells at redhat.com>
---
 fs/cifs/dns_resolve.c |   76 +++++++++++++++++++++++++++++--------------------
 1 files changed, 45 insertions(+), 31 deletions(-)

diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index 430c664..94ea9c8 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -29,38 +29,13 @@
 #include "cifsproto.h"
 #include "cifs_debug.h"
 
-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);
-	if (!ip)
-		return -ENOMEM;
-
-	memcpy(ip, data, datalen);
-	ip[datalen] = '\0';
-
-	key->payload.data = ip;
-
-	return rc;
-}
-
-struct key_type key_type_dns_resolver = {
-	.name        = "dns_resolver",
-	.def_datalen = sizeof(struct in_addr),
-	.describe    = user_describe,
-	.instantiate = dns_resolver_instantiate,
-	.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)
+static int
+is_ip(const char *name)
 {
 	int rc;
 	struct sockaddr_in sin_server;
@@ -82,6 +57,46 @@ static int is_ip(const char *name)
 	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);
+	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;
+	key->payload.data = ip;
+
+	return rc;
+}
+
+static void
+dns_resolver_destroy(struct key *key)
+{
+	kfree(key->payload.data);
+}
+
+struct key_type key_type_dns_resolver = {
+	.name        = "dns_resolver",
+	.def_datalen = sizeof(struct in_addr),
+	.describe    = user_describe,
+	.instantiate = dns_resolver_instantiate,
+	.destroy     = dns_resolver_destroy,
+	.match       = user_match,
+};
+
 /* Resolves server name to ip address.
  * input:
  * 	unc - server UNC
@@ -133,6 +148,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));
@@ -141,11 +157,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,
-- 
1.5.5.1



More information about the linux-cifs-client mailing list