linux-nfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Negotiate NFSv3 mount security flavor
@ 2013-03-19 19:01 Chuck Lever
  2013-03-19 19:01 ` [PATCH 1/3] SUNRPC: Remove extra xprt_put() Chuck Lever
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Chuck Lever @ 2013-03-19 19:01 UTC (permalink / raw)
  To: linux-nfs

For review, here is an implementation of NFSv3 security flavor
negotiation.

---

Chuck Lever (3):
      NFS: Use server-recommended security flavor by default (NFSv3)
      SUNRPC: Don't recognize RPC_AUTH_MAXFLAVOR
      SUNRPC: Remove extra xprt_put()


 fs/nfs/nfs4super.c |    2 +
 fs/nfs/super.c     |   80 +++++++++++++++++++++++++++-------------------------
 net/sunrpc/auth.c  |    5 +++
 net/sunrpc/clnt.c  |    4 +--
 4 files changed, 49 insertions(+), 42 deletions(-)

-- 
Chuck Lever

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

* [PATCH 1/3] SUNRPC: Remove extra xprt_put()
  2013-03-19 19:01 [PATCH 0/3] Negotiate NFSv3 mount security flavor Chuck Lever
@ 2013-03-19 19:01 ` Chuck Lever
  2013-03-19 19:01 ` [PATCH 2/3] SUNRPC: Don't recognize RPC_AUTH_MAXFLAVOR Chuck Lever
  2013-03-19 19:01 ` [PATCH 3/3] NFS: Use server-recommended security flavor by default (NFSv3) Chuck Lever
  2 siblings, 0 replies; 4+ messages in thread
From: Chuck Lever @ 2013-03-19 19:01 UTC (permalink / raw)
  To: linux-nfs

While testing error cases where rpc_new_client() fails, I saw
some oopses.

If rpc_new_client() fails, it already invokes xprt_put().  Thus
__rpc_clone_client() does not need to invoke it again.

Introduced by commit 1b63a751 "SUNRPC: Refactor rpc_clone_client()"
Fri Sep 14, 2012.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: stable@kernel.org
---

 net/sunrpc/clnt.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index dcc446e..9df26b7 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -512,7 +512,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
 	new = rpc_new_client(args, xprt);
 	if (IS_ERR(new)) {
 		err = PTR_ERR(new);
-		goto out_put;
+		goto out_err;
 	}
 
 	atomic_inc(&clnt->cl_count);
@@ -525,8 +525,6 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
 	new->cl_chatty = clnt->cl_chatty;
 	return new;
 
-out_put:
-	xprt_put(xprt);
 out_err:
 	dprintk("RPC:       %s: returned error %d\n", __func__, err);
 	return ERR_PTR(err);


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

* [PATCH 2/3] SUNRPC: Don't recognize RPC_AUTH_MAXFLAVOR
  2013-03-19 19:01 [PATCH 0/3] Negotiate NFSv3 mount security flavor Chuck Lever
  2013-03-19 19:01 ` [PATCH 1/3] SUNRPC: Remove extra xprt_put() Chuck Lever
@ 2013-03-19 19:01 ` Chuck Lever
  2013-03-19 19:01 ` [PATCH 3/3] NFS: Use server-recommended security flavor by default (NFSv3) Chuck Lever
  2 siblings, 0 replies; 4+ messages in thread
From: Chuck Lever @ 2013-03-19 19:01 UTC (permalink / raw)
  To: linux-nfs

RPC_AUTH_MAXFLAVOR is an invalid flavor, on purpose.  Don't allow
any processing whatsoever if a caller passes it to rpcauth_create()
or rpcauth_get_gssinfo().

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

 net/sunrpc/auth.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 2bc0cc2..ed2fdd2 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -82,7 +82,7 @@ MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size");
 
 static u32
 pseudoflavor_to_flavor(u32 flavor) {
-	if (flavor >= RPC_AUTH_MAXFLAVOR)
+	if (flavor > RPC_AUTH_MAXFLAVOR)
 		return RPC_AUTH_GSS;
 	return flavor;
 }
@@ -173,6 +173,9 @@ rpcauth_get_gssinfo(rpc_authflavor_t pseudoflavor, struct rpcsec_gss_info *info)
 	const struct rpc_authops *ops;
 	int result;
 
+	if (flavor >= RPC_AUTH_MAXFLAVOR)
+		return -EINVAL;
+
 	ops = auth_flavors[flavor];
 	if (ops == NULL)
 		request_module("rpc-auth-%u", flavor);


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

* [PATCH 3/3] NFS: Use server-recommended security flavor by default (NFSv3)
  2013-03-19 19:01 [PATCH 0/3] Negotiate NFSv3 mount security flavor Chuck Lever
  2013-03-19 19:01 ` [PATCH 1/3] SUNRPC: Remove extra xprt_put() Chuck Lever
  2013-03-19 19:01 ` [PATCH 2/3] SUNRPC: Don't recognize RPC_AUTH_MAXFLAVOR Chuck Lever
@ 2013-03-19 19:01 ` Chuck Lever
  2 siblings, 0 replies; 4+ messages in thread
From: Chuck Lever @ 2013-03-19 19:01 UTC (permalink / raw)
  To: linux-nfs

Since commit ec88f28d in 2009, checking if the user-specified flavor
is in the server's flavor list has been the source of a few
noticeable regressions (now fixed), but there is one that is still
vexing.

An NFS server can list AUTH_NULL in its flavor list, which suggests
a client should try to mount the server with the flavor of the
client's choice, but the server will squash all accesses.  In some
cases, our client fails to mount a server because of this check,
when the mount could have proceeded successfully.

Skip this check if the user has specified "sec=" on the mount
command line.  But do consult the server-provided flavor list to
choose a security flavor if no sec= option is specified on the mount
command.

If a server lists Kerberos pseudoflavors before "sys" in its export
options, our client now chooses Kerberos over AUTH_UNIX for mount
points, when no security flavor is specified by the mount command.
This could be surprising to some administrators or users, who would
need to have Kerberos credentials to access the export.

Or, a client administrator may not have enabled
"nfs-secure.service".  In this case, auth_rpcgss.ko might be
loadable, which is enough for the new logic to choose Kerberos over
AUTH_UNIX.  But the mount would fail since no GSS context can be
created without rpc.gssd running.

To retain the use of AUTH_UNIX by default:

  o  The server administrator can ensure that "sys" is listed before
     Kerberos flavors in its export security options (see
     exports(5)),

  o  The client administrator can explicitly specify "sec=sys" on
     its mount command line (see nfs(5)),

  o  The client administrator can use "Sec=sys" in an appropriate
     section of /etc/nfsmount.conf (see nfsmount.conf(5)), or

  o  The client administrator can blacklist auth_rpcgss.ko.

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

 fs/nfs/nfs4super.c |    2 +
 fs/nfs/super.c     |   80 +++++++++++++++++++++++++++-------------------------
 2 files changed, 44 insertions(+), 38 deletions(-)

diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 569b166..3df6c03 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -252,6 +252,8 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
 
 	dfprintk(MOUNT, "--> nfs4_try_mount()\n");
 
+	if (data->args_flavors[0] == RPC_AUTH_MAXFLAVOR)
+		data->args_flavors[0] = RPC_AUTH_UNIX;
 	export_path = data->nfs_server.export_path;
 	data->nfs_server.export_path = "/";
 	root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 95cdcb2..cc858f6 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -919,7 +919,7 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void)
 		data->mount_server.port	= NFS_UNSPEC_PORT;
 		data->nfs_server.port	= NFS_UNSPEC_PORT;
 		data->nfs_server.protocol = XPRT_TRANSPORT_TCP;
-		data->auth_flavors[0]	= RPC_AUTH_UNIX;
+		data->auth_flavors[0]	= RPC_AUTH_MAXFLAVOR;
 		data->auth_flavor_len	= 1;
 		data->minorversion	= 0;
 		data->need_mount	= true;
@@ -1607,49 +1607,57 @@ out_security_failure:
 }
 
 /*
- * Match the requested auth flavors with the list returned by
- * the server.  Returns zero and sets the mount's authentication
- * flavor on success; returns -EACCES if server does not support
- * the requested flavor.
+ * Select a security flavor for this mount.  The selected flavor
+ * is planted in args->auth_flavors[0].
  */
-static int nfs_walk_authlist(struct nfs_parsed_mount_data *args,
-			     struct nfs_mount_request *request)
+static void nfs_select_flavor(struct nfs_parsed_mount_data *args,
+			      struct nfs_mount_request *request)
 {
-	unsigned int i, j, server_authlist_len = *(request->auth_flav_len);
+	unsigned int i, count = *(request->auth_flav_len);
+	rpc_authflavor_t flavor;
+
+	if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR)
+		goto out;
+
+	/*
+	 * The NFSv2 MNT operation does not return a flavor list.
+	 */
+	if (args->mount_server.version != NFS_MNT3_VERSION)
+		goto out_default;
 
 	/*
 	 * Certain releases of Linux's mountd return an empty
-	 * flavor list.  To prevent behavioral regression with
-	 * these servers (ie. rejecting mounts that used to
-	 * succeed), revert to pre-2.6.32 behavior (no checking)
-	 * if the returned flavor list is empty.
+	 * flavor list in some cases.
 	 */
-	if (server_authlist_len == 0)
-		return 0;
+	if (count == 0)
+		goto out_default;
 
 	/*
-	 * We avoid sophisticated negotiating here, as there are
-	 * plenty of cases where we can get it wrong, providing
-	 * either too little or too much security.
-	 *
 	 * RFC 2623, section 2.7 suggests we SHOULD prefer the
 	 * flavor listed first.  However, some servers list
-	 * AUTH_NULL first.  Our caller plants AUTH_SYS, the
-	 * preferred default, in args->auth_flavors[0] if user
-	 * didn't specify sec= mount option.
+	 * AUTH_NULL first.  Avoid ever choosing AUTH_NULL.
 	 */
-	for (i = 0; i < args->auth_flavor_len; i++)
-		for (j = 0; j < server_authlist_len; j++)
-			if (args->auth_flavors[i] == request->auth_flavs[j]) {
-				dfprintk(MOUNT, "NFS: using auth flavor %d\n",
-					request->auth_flavs[j]);
-				args->auth_flavors[0] = request->auth_flavs[j];
-				return 0;
-			}
+	for (i = 0; i < count; i++) {
+		struct rpcsec_gss_info info;
+
+		flavor = request->auth_flavs[i];
+		switch (flavor) {
+		case RPC_AUTH_UNIX:
+			goto out_set;
+		case RPC_AUTH_NULL:
+			continue;
+		default:
+			if (rpcauth_get_gssinfo(flavor, &info) == 0)
+				goto out_set;
+		}
+	}
 
-	dfprintk(MOUNT, "NFS: server does not support requested auth flavor\n");
-	nfs_umount(request);
-	return -EACCES;
+out_default:
+	flavor = RPC_AUTH_UNIX;
+out_set:
+	args->auth_flavors[0] = flavor;
+out:
+	dfprintk(MOUNT, "NFS: using auth flavor %d\n", args->auth_flavors[0]);
 }
 
 /*
@@ -1712,12 +1720,8 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args,
 		return status;
 	}
 
-	/*
-	 * MNTv1 (NFSv2) does not support auth flavor negotiation.
-	 */
-	if (args->mount_server.version != NFS_MNT3_VERSION)
-		return 0;
-	return nfs_walk_authlist(args, &request);
+	nfs_select_flavor(args, &request);
+	return 0;
 }
 
 struct dentry *nfs_try_mount(int flags, const char *dev_name,


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

end of thread, other threads:[~2013-03-19 19:02 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-19 19:01 [PATCH 0/3] Negotiate NFSv3 mount security flavor Chuck Lever
2013-03-19 19:01 ` [PATCH 1/3] SUNRPC: Remove extra xprt_put() Chuck Lever
2013-03-19 19:01 ` [PATCH 2/3] SUNRPC: Don't recognize RPC_AUTH_MAXFLAVOR Chuck Lever
2013-03-19 19:01 ` [PATCH 3/3] NFS: Use server-recommended security flavor by default (NFSv3) Chuck Lever

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).