Linux NFS development
 help / color / mirror / Atom feed
* [PATCH] NFS: fix nfs_parse_ip_address() corner case
@ 2008-09-03 20:35 Chuck Lever
       [not found] ` <20080903203414.3322.97607.stgit-lQeC5l55kZ7wdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Chuck Lever @ 2008-09-03 20:35 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

Bruce observed that nfs_parse_ip_address() will successfully parse an
IPv6 address that looks like this:

  "::1%"

A scope delimiter is present, but there is no scope ID following it.
This is harmless, as it would simply set the scope ID to zero.  However,
in some cases we would like to flag this as an improperly formed
address.

We are now also careful to reject addresses where garbage follows the
address (up to the length of the string), instead of ignoring the
non-address characters; and where the scope ID is nonsense (not a valid
device name, but also not numeric).  Before, both of these cases would
result in a harmless zero scope ID.
    
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---

This has seen some local testing.  I'm not sure it gets every corner case
right, as the mount.nfs4 command passes the server name/address through DNS,
so it already doesn't allow patently bogus addresses like the above example.

But I thought I would post this for comments.

 fs/nfs/super.c |   37 ++++++++++++++++++++++++-------------
 1 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 5b2aa04..92de5e2 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -727,19 +727,22 @@ static void nfs_parse_ipv4_address(char *string, size_t str_len,
 #define IPV6_SCOPE_DELIMITER	'%'
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
-				    const char *delim,
-				    struct sockaddr_in6 *sin6)
+static int nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
+				   const char *delim,
+				   struct sockaddr_in6 *sin6)
 {
+	size_t len = (string + str_len) - delim - 1;
 	char *p;
-	size_t len;
 
-	if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
-		return ;
+	if (len == 0)
+		return 1;
+
 	if (*delim != IPV6_SCOPE_DELIMITER)
-		return;
+		return 0;
+
+	if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
+		return 0;
 
-	len = (string + str_len) - delim - 1;
 	p = kstrndup(delim + 1, len, GFP_KERNEL);
 	if (p) {
 		unsigned long scope_id = 0;
@@ -750,14 +753,20 @@ static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
 			scope_id = dev->ifindex;
 			dev_put(dev);
 		} else {
-			/* scope_id is set to zero on error */
-			strict_strtoul(p, 10, &scope_id);
+			if (strict_strtoul(p, 10, &scope_id) == 0) {
+				kfree(p);
+				return 0;
+			}
 		}
 
 		kfree(p);
+
 		sin6->sin6_scope_id = scope_id;
 		dfprintk(MOUNT, "NFS: IPv6 scope ID = %lu\n", scope_id);
+		return 1;
 	}
+
+	return 0;
 }
 
 static void nfs_parse_ipv6_address(char *string, size_t str_len,
@@ -773,9 +782,11 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len,
 
 		sin6->sin6_family = AF_INET6;
 		*addr_len = sizeof(*sin6);
-		if (in6_pton(string, str_len, addr, IPV6_SCOPE_DELIMITER, &delim)) {
-			nfs_parse_ipv6_scope_id(string, str_len, delim, sin6);
-			return;
+		if (in6_pton(string, str_len, addr,
+					IPV6_SCOPE_DELIMITER, &delim) != 0) {
+			if (nfs_parse_ipv6_scope_id(string, str_len,
+							delim, sin6) != 0)
+				return;
 		}
 	}
 


^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH] NFS: fix nfs_parse_ip_address() corner case
@ 2008-08-22 18:24 Chuck Lever
       [not found] ` <20080822182419.19572.34705.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Chuck Lever @ 2008-08-22 18:24 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs

Bruce observed that nfs_parse_ip_address() will successfully parse an IPv6
address that looks like this:

  "::1%"

A scope delimiter is present, but there is no scope ID following it.
This is harmless, as it would simply set the scope ID to zero.  However,
in some cases we would like to flag this as an improperly formed
address.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---

 fs/nfs/super.c |   24 +++++++++++++++---------
 1 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 5b2aa04..f73e068 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -727,19 +727,21 @@ static void nfs_parse_ipv4_address(char *string, size_t str_len,
 #define IPV6_SCOPE_DELIMITER	'%'
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
-				    const char *delim,
-				    struct sockaddr_in6 *sin6)
+static int nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
+				   const char *delim,
+				   struct sockaddr_in6 *sin6)
 {
 	char *p;
 	size_t len;
 
 	if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
-		return ;
+		return 0;
 	if (*delim != IPV6_SCOPE_DELIMITER)
-		return;
-
+		return 0;
 	len = (string + str_len) - delim - 1;
+	if (len == 0)
+		return 0;
+
 	p = kstrndup(delim + 1, len, GFP_KERNEL);
 	if (p) {
 		unsigned long scope_id = 0;
@@ -758,6 +760,8 @@ static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
 		sin6->sin6_scope_id = scope_id;
 		dfprintk(MOUNT, "NFS: IPv6 scope ID = %lu\n", scope_id);
 	}
+
+	return 1;
 }
 
 static void nfs_parse_ipv6_address(char *string, size_t str_len,
@@ -773,9 +777,11 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len,
 
 		sin6->sin6_family = AF_INET6;
 		*addr_len = sizeof(*sin6);
-		if (in6_pton(string, str_len, addr, IPV6_SCOPE_DELIMITER, &delim)) {
-			nfs_parse_ipv6_scope_id(string, str_len, delim, sin6);
-			return;
+		if (in6_pton(string, str_len, addr,
+					IPV6_SCOPE_DELIMITER, &delim)) {
+			if (nfs_parse_ipv6_scope_id(string,
+							str_len, delim, sin6))
+				return;
 		}
 	}
 


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2008-09-05 21:58 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-03 20:35 [PATCH] NFS: fix nfs_parse_ip_address() corner case Chuck Lever
     [not found] ` <20080903203414.3322.97607.stgit-lQeC5l55kZ7wdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-09-04 20:23   ` J. Bruce Fields
2008-09-04 21:36     ` Chuck Lever
     [not found]       ` <76bd70e30809041436y4a8fc1d2hb8230cb7aba17f26-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-09-05 21:58         ` J. Bruce Fields
  -- strict thread matches above, loose matches on Subject: below --
2008-08-22 18:24 Chuck Lever
     [not found] ` <20080822182419.19572.34705.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-08-26 18:39   ` J. Bruce Fields
2008-08-26 20:24     ` Chuck Lever
2008-08-26 20:28       ` J. Bruce Fields
2008-08-26 20:36         ` Chuck Lever
2008-08-26 20:45           ` J. Bruce Fields

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox