From patchwork Wed Nov 7 04:12:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 10671779 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 68DF615E9 for ; Wed, 7 Nov 2018 04:14:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5A14D29E60 for ; Wed, 7 Nov 2018 04:14:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4D9712B7BA; Wed, 7 Nov 2018 04:14:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.2 required=2.0 tests=BAYES_00,FUZZY_CREDIT, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A06C92B7AF for ; Wed, 7 Nov 2018 04:14:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388302AbeKGNmk (ORCPT ); Wed, 7 Nov 2018 08:42:40 -0500 Received: from mx2.suse.de ([195.135.220.15]:56514 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2388530AbeKGNmk (ORCPT ); Wed, 7 Nov 2018 08:42:40 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 95156B11C; Wed, 7 Nov 2018 04:14:01 +0000 (UTC) From: NeilBrown To: "J. Bruce Fields" , Chuck Lever , Jeff Layton , Trond Myklebust , Anna Schumaker Date: Wed, 07 Nov 2018 15:12:30 +1100 Subject: [PATCH 05/23] SUNRPC: add 'struct cred *' to auth_cred and rpc_cred Cc: Linux NFS Mailing List , linux-kernel@vger.kernel.org Message-ID: <154156395089.24086.6277617015828499248.stgit@noble> In-Reply-To: <154156285766.24086.14262073575778354276.stgit@noble> References: <154156285766.24086.14262073575778354276.stgit@noble> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The SUNRPC credential framework was put together before Linux has 'struct cred'. Now that we have it, it makes sense to use it. This first step just includes a suitable 'struct cred *' pointer in every 'struct auth_cred' and almost every 'struct rpc_cred'. The rpc_cred used for auth_null has a NULL 'struct cred *' as nothing else really makes sense. For rpc_cred, the pointer is reference counted. For auth_cred it isn't. struct auth_cred are either allocated on the stack, in which case the thread owns a reference to the auth, or are part of 'struct generic_cred' in which case gc_base owns the reference, and "acred" shares it. Signed-off-by: NeilBrown --- fs/nfs/flexfilelayout/flexfilelayout.c | 17 +++++++++++++++++ fs/nfsd/nfs4callback.c | 13 ++++++++++++- include/linux/sunrpc/auth.h | 2 ++ net/sunrpc/auth.c | 8 +++++++- net/sunrpc/auth_generic.c | 8 +++++++- net/sunrpc/auth_gss/auth_gss.c | 2 ++ net/sunrpc/auth_unix.c | 1 + 7 files changed, 48 insertions(+), 3 deletions(-) diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 86bcba40ca61..9df686561f95 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -415,6 +416,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, struct nfs4_ff_layout_mirror *mirror; struct auth_cred acred = { .group_info = ff_zero_group }; struct rpc_cred __rcu *cred; + struct cred *kcred; u32 ds_count, fh_count, id; int j; @@ -491,8 +493,23 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, acred.gid = make_kgid(&init_user_ns, id); + if (gfp_flags & __GFP_FS) + kcred = prepare_kernel_cred(NULL); + else { + unsigned int nofs_flags = memalloc_nofs_save(); + kcred = prepare_kernel_cred(NULL); + memalloc_nofs_restore(nofs_flags); + } + rc = -ENOMEM; + if (!kcred) + goto out_err_free; + kcred->fsuid = acred.uid; + kcred->fsgid = acred.gid; + acred.cred = kcred; + /* find the cred for it */ rcu_assign_pointer(cred, rpc_lookup_generic_cred(&acred, 0, gfp_flags)); + put_cred(kcred); if (IS_ERR(cred)) { rc = PTR_ERR(cred); goto out_err_free; diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 25987bcdf96f..7c7e3510599d 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -858,10 +858,21 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc } else { struct rpc_auth *auth = client->cl_auth; struct auth_cred acred = {}; + struct cred *kcred; + struct rpc_cred *ret; + + kcred = prepare_kernel_cred(NULL); + if (!kcred) + return NULL; acred.uid = ses->se_cb_sec.uid; acred.gid = ses->se_cb_sec.gid; - return auth->au_ops->lookup_cred(client->cl_auth, &acred, 0); + kcred->uid = acred.uid; + kcred->gid = acred.gid; + acred.cred = kcred; + ret = auth->au_ops->lookup_cred(client->cl_auth, &acred, 0); + put_cred(kcred); + return ret; } } diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index c4db9424b63b..1f95bd612053 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h @@ -46,6 +46,7 @@ enum { /* Work around the lack of a VFS credential */ struct auth_cred { + const struct cred *cred; kuid_t uid; kgid_t gid; struct group_info *group_info; @@ -68,6 +69,7 @@ struct rpc_cred { unsigned long cr_expire; /* when to gc */ unsigned long cr_flags; /* various flags */ refcount_t cr_count; /* ref count */ + const struct cred *cr_cred; kuid_t cr_uid; diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index ad8ead738981..a7e08e44f92b 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -659,6 +659,7 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags) acred.uid = cred->fsuid; acred.gid = cred->fsgid; acred.group_info = cred->group_info; + acred.cred = cred; ret = auth->au_ops->lookup_cred(auth, &acred, flags); return ret; } @@ -674,6 +675,7 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, cred->cr_auth = auth; cred->cr_ops = ops; cred->cr_expire = jiffies; + cred->cr_cred = get_cred(acred->cred); cred->cr_uid = acred->uid; } EXPORT_SYMBOL_GPL(rpcauth_init_cred); @@ -694,11 +696,15 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) struct auth_cred acred = { .uid = GLOBAL_ROOT_UID, .gid = GLOBAL_ROOT_GID, + .cred = get_task_cred(&init_task), }; + struct rpc_cred *ret; dprintk("RPC: %5u looking up %s cred\n", task->tk_pid, task->tk_client->cl_auth->au_ops->au_name); - return auth->au_ops->lookup_cred(auth, &acred, lookupflags); + ret = auth->au_ops->lookup_cred(auth, &acred, lookupflags); + put_cred(acred.cred); + return ret; } static struct rpc_cred * diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index d8831b988b1e..ec28f7edb615 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c @@ -61,11 +61,15 @@ struct rpc_cred *rpc_lookup_machine_cred(const char *service_name) .gid = RPC_MACHINE_CRED_GROUPID, .principal = service_name, .machine_cred = 1, + .cred = get_task_cred(&init_task), }; + struct rpc_cred *ret; dprintk("RPC: looking up machine cred for service %s\n", service_name); - return generic_auth.au_ops->lookup_cred(&generic_auth, &acred, 0); + ret = generic_auth.au_ops->lookup_cred(&generic_auth, &acred, 0); + put_cred(acred.cred); + return ret; } EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred); @@ -110,6 +114,7 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags, g gcred->acred.uid = acred->uid; gcred->acred.gid = acred->gid; gcred->acred.group_info = acred->group_info; + gcred->acred.cred = gcred->gc_base.cr_cred; gcred->acred.ac_flags = 0; if (gcred->acred.group_info != NULL) get_group_info(gcred->acred.group_info); @@ -132,6 +137,7 @@ generic_free_cred(struct rpc_cred *cred) dprintk("RPC: generic_free_cred %p\n", gcred); if (gcred->acred.group_info != NULL) put_group_info(gcred->acred.group_info); + put_cred(cred->cr_cred); kfree(gcred); } diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 30f970cdc7f6..092452b9f05c 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -1320,6 +1320,7 @@ gss_destroy_nullcred(struct rpc_cred *cred) struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1); RCU_INIT_POINTER(gss_cred->gc_ctx, NULL); + put_cred(cred->cr_cred); call_rcu(&cred->cr_rcu, gss_free_cred_callback); if (ctx) gss_put_ctx(ctx); @@ -1585,6 +1586,7 @@ static int gss_renew_cred(struct rpc_task *task) struct rpc_auth *auth = oldcred->cr_auth; struct auth_cred acred = { .uid = oldcred->cr_uid, + .cred = oldcred->cr_cred, .principal = gss_cred->gc_principal, .machine_cred = (gss_cred->gc_principal != NULL ? 1 : 0), }; diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 4c1c7e56288f..36e01384f082 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -97,6 +97,7 @@ static void unx_free_cred(struct unx_cred *unx_cred) { dprintk("RPC: unx_free_cred %p\n", unx_cred); + put_cred(unx_cred->uc_base.cr_cred); kfree(unx_cred); }