aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@netapp.com>2013-09-04 12:13:19 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-09-07 18:39:25 -0400
commitb1b3e136948a2bf4915326acb0d825d7d180753f (patch)
treebba218c0ba86f3030f8f91e3c3d19dd445812d81 /fs/nfs/nfs4proc.c
parent0aea92bf67321fc600b6c61627e0fd46e8889a49 (diff)
NFSv4: use mach cred for SECINFO_NO_NAME w/ integrity
Commit 97431204ea005ec8070ac94bc3251e836daa7ca7 introduced a regression that causes SECINFO_NO_NAME to fail without sending an RPC if: 1) the nfs_client's rpc_client is using krb5i/p (now tried by default) 2) the current user doesn't have valid kerberos credentials This situation is quite common - as of now a sec=sys mount would use krb5i for the nfs_client's rpc_client and a user would hardly be faulted for not having run kinit. The solution is to use the machine cred when trying to use an integrity protected auth flavor for SECINFO_NO_NAME. Older servers may not support using the machine cred or an integrity protected auth flavor for SECINFO_NO_NAME in every circumstance, so we fall back to using the user's cred and the filesystem's auth flavor in this case. We run into another problem when running against linux nfs servers - they return NFS4ERR_WRONGSEC when using integrity auth flavor (unless the mount is also that flavor) even though that is not a valid error for SECINFO*. Even though it's against spec, handle WRONGSEC errors on SECINFO_NO_NAME by falling back to using the user cred and the filesystem's auth flavor. Signed-off-by: Weston Andros Adamson <dros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 122b9340e6ef..e1212914bc03 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -7483,7 +7483,8 @@ out:
7483 */ 7483 */
7484static int 7484static int
7485_nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, 7485_nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
7486 struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors) 7486 struct nfs_fsinfo *info,
7487 struct nfs4_secinfo_flavors *flavors, bool use_integrity)
7487{ 7488{
7488 struct nfs41_secinfo_no_name_args args = { 7489 struct nfs41_secinfo_no_name_args args = {
7489 .style = SECINFO_STYLE_CURRENT_FH, 7490 .style = SECINFO_STYLE_CURRENT_FH,
@@ -7496,8 +7497,23 @@ _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
7496 .rpc_argp = &args, 7497 .rpc_argp = &args,
7497 .rpc_resp = &res, 7498 .rpc_resp = &res,
7498 }; 7499 };
7499 return nfs4_call_sync(server->nfs_client->cl_rpcclient, server, &msg, 7500 struct rpc_clnt *clnt = server->client;
7500 &args.seq_args, &res.seq_res, 0); 7501 int status;
7502
7503 if (use_integrity) {
7504 clnt = server->nfs_client->cl_rpcclient;
7505 msg.rpc_cred = nfs4_get_clid_cred(server->nfs_client);
7506 }
7507
7508 dprintk("--> %s\n", __func__);
7509 status = nfs4_call_sync(clnt, server, &msg, &args.seq_args,
7510 &res.seq_res, 0);
7511 dprintk("<-- %s status=%d\n", __func__, status);
7512
7513 if (msg.rpc_cred)
7514 put_rpccred(msg.rpc_cred);
7515
7516 return status;
7501} 7517}
7502 7518
7503static int 7519static int
@@ -7507,7 +7523,24 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
7507 struct nfs4_exception exception = { }; 7523 struct nfs4_exception exception = { };
7508 int err; 7524 int err;
7509 do { 7525 do {
7510 err = _nfs41_proc_secinfo_no_name(server, fhandle, info, flavors); 7526 /* first try using integrity protection */
7527 err = -NFS4ERR_WRONGSEC;
7528
7529 /* try to use integrity protection with machine cred */
7530 if (_nfs4_is_integrity_protected(server->nfs_client))
7531 err = _nfs41_proc_secinfo_no_name(server, fhandle, info,
7532 flavors, true);
7533
7534 /*
7535 * if unable to use integrity protection, or SECINFO with
7536 * integrity protection returns NFS4ERR_WRONGSEC (which is
7537 * disallowed by spec, but exists in deployed servers) use
7538 * the current filesystem's rpc_client and the user cred.
7539 */
7540 if (err == -NFS4ERR_WRONGSEC)
7541 err = _nfs41_proc_secinfo_no_name(server, fhandle, info,
7542 flavors, false);
7543
7511 switch (err) { 7544 switch (err) {
7512 case 0: 7545 case 0:
7513 case -NFS4ERR_WRONGSEC: 7546 case -NFS4ERR_WRONGSEC: