Re: [PATCH] Fix NFS mount from IPv6 addresses

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On  8:23 12/01, Ian Kent wrote:
> On Fri, 2019-01-11 at 12:18 -0600, Goldwyn Rodrigues wrote:
> > When an NFS server is specified by an IPv6 address and no mount
> > options, the mount fails because check_address_proto()
> > receives vers with TCP_REQUESTED set but the host.addr_len is
> > INET6_ADDRSTRLEN. Removing the check for INET_ADDRSTRLEN
> > fixes this issue.
> 
> Thanks for the patch Goldwyn.
> 
> Shouldn't that be "Removing the check for INET6_ADDRSTRLEN fixes
> this issue".

Correct.

> 
> > 
> > However, this would allow mount from "proto=tcp" for an IPv6
> > addressed server.
> 
> This statement is a bit confusing, Isn't this the point of the
> change?
> 

Yes, I was mentioning the side-effects of the patch :)
The other way would be not to set TCP_REQUESTED at all, and
set it later by returning version from check_address_proto.

I  have another bigger patch [attached] but decided against
it. It kinda looked too ugly for resolving this. Take your pick ;)

> I need to try and find the reason I added this check in the
> first place to work out if removing the check could introduce
> a problem ...
> 
> > 
> > Fixes: 9053214 ("autofs-5.1.3 - fix ipv6 proto option handling")
> 
> Can I have a look at the bug, couldn't find it by searching for
> it?

Add this entry in relevant auto file.

local-dir	-fstype=nfs		[IP:v6:address]:/export-dir/on/server

and try to access it.

> 
> > Signed-off-by: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx>
> > ---
> >  modules/replicated.c | 3 ---
> >  1 file changed, 3 deletions(-)
> > 
> > diff --git a/modules/replicated.c b/modules/replicated.c
> > index 740270e..e99e32a 100644
> > --- a/modules/replicated.c
> > +++ b/modules/replicated.c
> > @@ -497,9 +497,6 @@ static int check_address_proto(unsigned logopt,
> >  	if (ipv6_requested) {
> >  		if (host->addr_len == INET_ADDRSTRLEN)
> >  			ret = 0;
> > -	} else {
> > -		if (host->addr_len == INET6_ADDRSTRLEN)
> > -			ret = 0;
> >  	}
> >  
> >  	if (!ret)
> 

-- 
Goldwyn
commit 4e05949c3e140b0d66ccd78fe74d9974eeff9cf2
Author: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx>
Date:   Fri Jan 11 06:36:13 2019 -0600

    Fix NFS mounts with IPv6 address and no options
    
    When a NFS server is specified by an IPv6 address and no mount
    options, the mount fails because check_address_proto() receives
    vers with TCP_REQUESTED set but the host.add_len is set to
    INET6_ADDRSTRLEN. Fix it by not setting TCP_SUPPORTED before
    options are parsed. This is eventually set at
    check_address_proto(), if not set.
    
    Also check for UDP6_REQUESTED when denying NFSv4 over UDP.
    
    Fixes: 9053214 ("autofs-5.1.3 - fix ipv6 proto option handling")
    Signed-off-by: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx>

diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c
index 426c27b..90668e4 100644
--- a/modules/mount_nfs.c
+++ b/modules/mount_nfs.c
@@ -88,7 +88,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 	mount_default_proto = defaults_get_mount_nfs_default_proto();
 	vers = NFS_VERS_DEFAULT | NFS_PROTO_DEFAULT;
 	if (strcmp(fstype, "nfs4") == 0)
-		vers = NFS4_VERS_DEFAULT | TCP_SUPPORTED;
+		vers = NFS4_VERS_DEFAULT;
 	else if (mount_default_proto == 4)
 		vers = vers | NFS4_VERS_DEFAULT;
 
@@ -154,7 +154,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 				/* Is any version of NFSv4 in the options */
 				if (_strncmp("vers=4", cp, 6) == 0 ||
 				    _strncmp("nfsvers=4", cp, 9) == 0)
-					vers = NFS4_VERS_MASK | TCP_SUPPORTED;
+					vers = NFS4_VERS_MASK;
 				else if (_strncmp("vers=3", cp, o_len) == 0 ||
 					 _strncmp("nfsvers=3", cp, o_len) == 0) {
 					vers &= ~(NFS4_VERS_MASK | NFS_VERS_MASK);
@@ -174,17 +174,15 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 						port = 0;
 				} else if (_strncmp("proto=udp", cp, o_len) == 0 ||
 					   _strncmp("udp", cp, o_len) == 0) {
-					vers &= ~TCP_SUPPORTED;
+					vers |= UDP_REQUESTED;
 				} else if (_strncmp("proto=udp6", cp, o_len) == 0 ||
 					   _strncmp("udp6", cp, o_len) == 0) {
-					vers &= ~TCP_SUPPORTED;
 					vers |= UDP6_REQUESTED;
 				} else if (_strncmp("proto=tcp", cp, o_len) == 0 ||
 					   _strncmp("tcp", cp, o_len) == 0) {
-					vers &= ~UDP_SUPPORTED;
+					vers |= TCP_REQUESTED;
 				} else if (_strncmp("proto=tcp6", cp, o_len) == 0 ||
 					   _strncmp("tcp6", cp, o_len) == 0) {
-					vers &= ~UDP_SUPPORTED;
 					vers |= TCP6_REQUESTED;
 				}
 				/* Check for options that also make sense
@@ -199,10 +197,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 			}
 		}
 
-		/* In case both tcp and udp options were given */
-		if ((vers & NFS_PROTO_MASK) == 0)
-			vers |= NFS_PROTO_MASK;
-
 		debug(ap->logopt, MODPREFIX
 		      "nfs options=\"%s\", nobind=%d, nosymlink=%d, ro=%d",
 		      nfsoptions, nobind, nosymlink, ro);
@@ -234,7 +228,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 	    mount_default_proto == 4 &&
 	    (vers & NFS_VERS_MASK) != 0 &&
 	    (vers & NFS4_VERS_MASK) != 0 &&
-	    !(vers & UDP6_REQUESTED)) {
+	    !(vers & (UDP6_REQUESTED | UDP_REQUESTED))) {
 		unsigned int v4_probe_ok = 0;
 		struct host *tmp = new_host(hosts->name, 0,
 					    hosts->addr, hosts->addr_len,
diff --git a/modules/replicated.c b/modules/replicated.c
index 740270e..9819c22 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -486,22 +486,32 @@ done_ver:
 }
 
 static int check_address_proto(unsigned logopt,
-			       struct host *host, unsigned int version)
+			       struct host *host, unsigned int *version)
 {
-	int ipv6_requested = version & (TCP6_REQUESTED | UDP6_REQUESTED);
+	unsigned int ver = *version;
 	int ret = 1;
 
 	/* If a protocol has been explicitly requested then don't
 	 * consider addresses that don't match the requested protocol.
 	 */
-	if (ipv6_requested) {
-		if (host->addr_len == INET_ADDRSTRLEN)
-			ret = 0;
-	} else {
-		if (host->addr_len == INET6_ADDRSTRLEN)
-			ret = 0;
+	if (host->addr_len == INET6_ADDRSTRLEN) {
+		if (ver & (TCP_REQUESTED | UDP_REQUESTED)) {
+			ret = 1;
+			goto out;
+		}
+		if (!(ver & (TCP6_REQUESTED | UDP6_REQUESTED)))
+			*version |= TCP6_REQUESTED;
+
+	} else if (host->addr_len == INET_ADDRSTRLEN) {
+		if (ver & (TCP6_REQUESTED | UDP6_REQUESTED)) {
+			ret = 1;
+			goto out;
+		}
+		if (!(ver & (TCP_REQUESTED | UDP_REQUESTED)))
+			*version |= TCP_REQUESTED;
 	}
 
+out:
 	if (!ret)
 		debug(logopt, "requested protocol does not match address");
 
@@ -516,7 +526,7 @@ static int get_vers_and_cost(unsigned logopt, struct host *host,
 	unsigned int supported, vers = (NFS_VERS_MASK | NFS4_VERS_MASK);
 	int ret = 0;
 
-	if (!check_address_proto(logopt, host, version))
+	if (!check_address_proto(logopt, host, &version))
 		return 0;
 
 	memset(&pm_info, 0, sizeof(struct conn_info));
@@ -588,7 +598,7 @@ static int get_supported_ver_and_cost(unsigned logopt, struct host *host,
 		debug(logopt, "called with host %s version 0x%x",
 			host->name, version);
 
-	if (!check_address_proto(logopt, host, version))
+	if (!check_address_proto(logopt, host, &version))
 		return 0;
 
 	memset(&pm_info, 0, sizeof(struct conn_info));

[Index of Archives]     [Linux Filesystem Development]     [Linux Ext4]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux