On Fri, 2013-06-07 at 15:45 -0400, Chuck Lever wrote: > Commit 05f4c350 "NFS: Discover NFSv4 server trunking when mounting" > Fri Sep 14 17:24:32 2012 introduced Uniform Client String support, > which forces our NFS client to establish a client ID immediately > during a mount operation rather than waiting until a user wants to > open a file. > > Normally machine credentials (eg. from a keytab) are used to perform > a mount operation that is protected by Kerberos. Before 05fc350, > SETCLIENTID used a machine credential, or fell back to a regular > user's credential if no keytab is available. > > On clients that don't have a keytab, performing SETCLIENTID early > means there's no user credential to fall back on, since no regular > user has kinit'd yet. 05f4c350 seems to have broken the ability > to mount with sec=krb5 on clients that don't have a keytab in > kernels 3.7 - 3.9. > > To address this regression, commit 4edaa308 (NFS: Use "krb5i" to > establish NFSv4 state whenever possible), Sat Mar 16 15:56:20 2013, > was merged in 3.10. This commit forces the NFS client to fall back > to AUTH_SYS for lease management operations if no keytab is > available. > > Neil Brown noticed that, since root is required to kinit to do a > sec=krb5 mount when a client doesn't have a keytab, we can try to > use root's Kerberos credential before AUTH_SYS. > > Now, when determining a principal and flavor to use for lease > management, the NFS client tries in this order: > > 1. Flavor: AUTH_GSS, krb5i > Principal: service principal (via keytab) > > 2. Flavor: AUTH_GSS, krb5i > Principal: user principal established for UID 0 (via kinit) > > 3. Flavor: AUTH_SYS > Principal: UID 0 / GID 0 > > Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> > --- > fs/nfs/nfs4proc.c | 21 ++++++++++++++------- > fs/nfs/nfs4state.c | 16 ++++++++-------- > 2 files changed, 22 insertions(+), 15 deletions(-) > > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c > index 5ba38b3..4d76fae 100644 > --- a/fs/nfs/nfs4proc.c > +++ b/fs/nfs/nfs4proc.c > @@ -4356,7 +4356,8 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, > dprintk("NFS call setclientid auth=%s, '%.*s'\n", > clp->cl_rpcclient->cl_auth->au_ops->au_name, > setclientid.sc_name_len, setclientid.sc_name); > - status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); > + status = rpc_call_sync(clp->cl_rpcclient, &msg, > + RPC_TASK_TIMEOUT|RPC_TASK_ROOTCREDS); We are certainly _not_ resurrecting the RPC_TASK_ROOTCREDS abomination. For one thing is overrides the machine creds that are what we really want to use when available. NACK... > dprintk("NFS reply setclientid: %d\n", status); > return status; > } > @@ -4383,7 +4384,8 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, > dprintk("NFS call setclientid_confirm auth=%s, (client ID %llx)\n", > clp->cl_rpcclient->cl_auth->au_ops->au_name, > clp->cl_clientid); > - status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); > + status = rpc_call_sync(clp->cl_rpcclient, &msg, > + RPC_TASK_TIMEOUT|RPC_TASK_ROOTCREDS); > dprintk("NFS reply setclientid_confirm: %d\n", status); > return status; > } > @@ -5461,7 +5463,8 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred > goto out; > } > > - status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); > + status = rpc_call_sync(clp->cl_rpcclient, &msg, > + RPC_TASK_TIMEOUT|RPC_TASK_ROOTCREDS); > if (status == 0) { > if (memcmp(res.session->sess_id.data, > clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { > @@ -5545,7 +5548,8 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) > goto out_server_scope; > } > > - status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); > + status = rpc_call_sync(clp->cl_rpcclient, &msg, > + RPC_TASK_TIMEOUT|RPC_TASK_ROOTCREDS); > if (status == 0) > status = nfs4_check_cl_exchange_flags(res.flags); > > @@ -5605,7 +5609,8 @@ static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, > }; > int status; > > - status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); > + status = rpc_call_sync(clp->cl_rpcclient, &msg, > + RPC_TASK_TIMEOUT|RPC_TASK_ROOTCREDS); > if (status) > dprintk("NFS: Got error %d from the server %s on " > "DESTROY_CLIENTID.", status, clp->cl_hostname); > @@ -5871,7 +5876,8 @@ static int _nfs4_proc_create_session(struct nfs_client *clp, > nfs4_init_channel_attrs(&args); > args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); > > - status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); > + status = rpc_call_sync(session->clp->cl_rpcclient, &msg, > + RPC_TASK_TIMEOUT|RPC_TASK_ROOTCREDS); > > if (!status) { > /* Verify the session's negotiated channel_attrs values */ > @@ -5934,7 +5940,8 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, > if (session->clp->cl_cons_state != NFS_CS_READY) > return status; > > - status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); > + status = rpc_call_sync(session->clp->cl_rpcclient, &msg, > + RPC_TASK_TIMEOUT|RPC_TASK_ROOTCREDS); > > if (status) > dprintk("NFS: Got error %d from the server on DESTROY_SESSION. " > diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c > index 4949ce5..d8068ab 100644 > --- a/fs/nfs/nfs4state.c > +++ b/fs/nfs/nfs4state.c > @@ -1811,10 +1811,9 @@ static int nfs4_establish_lease(struct nfs_client *clp) > int status; > > cred = ops->get_clid_cred(clp); > - if (cred == NULL) > - return -ENOENT; > status = ops->establish_clid(clp, cred); > - put_rpccred(cred); > + if (cred) > + put_rpccred(cred); > if (status != 0) > return status; > pnfs_destroy_all_layouts(clp); > @@ -1885,11 +1884,9 @@ int nfs4_discover_server_trunking(struct nfs_client *clp, > again: > status = -ENOENT; > cred = ops->get_clid_cred(clp); > - if (cred == NULL) > - goto out_unlock; > - > status = ops->detect_trunking(clp, result, cred); > - put_rpccred(cred); > + if (cred) > + put_rpccred(cred); > switch (status) { > case 0: > break; > @@ -1902,6 +1899,10 @@ again: > __func__, status); > goto again; > case -EACCES: > + if (clp->cl_machine_cred != NULL) { > + nfs4_clear_machine_cred(clp); > + goto again; > + } > if (i++) > break; > case -NFS4ERR_CLID_INUSE: > @@ -1935,7 +1936,6 @@ again: > status = -EIO; > } > > -out_unlock: > mutex_unlock(&nfs_clid_init_mutex); > dprintk("NFS: %s: status = %d\n", __func__, status); > return status; > > -- > To unsubscribe from this list: send the line "unsubscribe linux-nfs" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Trond Myklebust Linux NFS client maintainer NetApp Trond.Myklebust@xxxxxxxxxx www.netapp.com -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html