On Wed, 2024-08-28 at 21:04 -0400, Mike Snitzer wrote: > From: Weston Andros Adamson <dros@xxxxxxxxxxxxxxx> > > Add new funtion svcauth_map_clnt_to_svc_cred_local which maps a > generic cred to a svc_cred suitable for use in nfsd. > > This is needed by the localio code to map nfs client creds to nfs > server credentials. > > Following from net/sunrpc/auth_unix.c:unx_marshal() it is clear that > ->fsuid and ->fsgid must be used (rather than ->uid and ->gid). In > addition, these uid and gid must be translated with from_kuid_munged() > so local client uses correct uid and gid when acting as local server. > > Suggested-by: NeilBrown <neilb@xxxxxxx> # to approximate unx_marshal() > Signed-off-by: Weston Andros Adamson <dros@xxxxxxxxxxxxxxx> > Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> > Co-developed-by: Mike Snitzer <snitzer@xxxxxxxxxx> > Signed-off-by: Mike Snitzer <snitzer@xxxxxxxxxx> > --- > include/linux/sunrpc/svcauth.h | 5 +++++ > net/sunrpc/svcauth.c | 28 ++++++++++++++++++++++++++++ > 2 files changed, 33 insertions(+) > > diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h > index 63cf6fb26dcc..2e111153f7cd 100644 > --- a/include/linux/sunrpc/svcauth.h > +++ b/include/linux/sunrpc/svcauth.h > @@ -14,6 +14,7 @@ > #include <linux/sunrpc/msg_prot.h> > #include <linux/sunrpc/cache.h> > #include <linux/sunrpc/gss_api.h> > +#include <linux/sunrpc/clnt.h> > #include <linux/hash.h> > #include <linux/stringhash.h> > #include <linux/cred.h> > @@ -157,6 +158,10 @@ extern enum svc_auth_status svc_set_client(struct svc_rqst *rqstp); > extern int svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops); > extern void svc_auth_unregister(rpc_authflavor_t flavor); > > +extern void svcauth_map_clnt_to_svc_cred_local(struct rpc_clnt *clnt, > + const struct cred *, > + struct svc_cred *); > + > extern struct auth_domain *unix_domain_find(char *name); > extern void auth_domain_put(struct auth_domain *item); > extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new); > diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c > index 93d9e949e265..55b4d2874188 100644 > --- a/net/sunrpc/svcauth.c > +++ b/net/sunrpc/svcauth.c > @@ -18,6 +18,7 @@ > #include <linux/sunrpc/svcauth.h> > #include <linux/err.h> > #include <linux/hash.h> > +#include <linux/user_namespace.h> > > #include <trace/events/sunrpc.h> > > @@ -175,6 +176,33 @@ rpc_authflavor_t svc_auth_flavor(struct svc_rqst *rqstp) > } > EXPORT_SYMBOL_GPL(svc_auth_flavor); > > +/** > + * svcauth_map_clnt_to_svc_cred_local - maps a generic cred > + * to a svc_cred suitable for use in nfsd. > + * @clnt: rpc_clnt associated with nfs client > + * @cred: generic cred associated with nfs client > + * @svc: returned svc_cred that is suitable for use in nfsd > + */ > +void svcauth_map_clnt_to_svc_cred_local(struct rpc_clnt *clnt, > + const struct cred *cred, > + struct svc_cred *svc) > +{ > + struct user_namespace *userns = clnt->cl_cred ? > + clnt->cl_cred->user_ns : &init_user_ns; > + > + memset(svc, 0, sizeof(struct svc_cred)); > + > + svc->cr_uid = KUIDT_INIT(from_kuid_munged(userns, cred->fsuid)); > + svc->cr_gid = KGIDT_INIT(from_kgid_munged(userns, cred->fsgid)); > + svc->cr_flavor = clnt->cl_auth->au_flavor; > + if (cred->group_info) > + svc->cr_group_info = get_group_info(cred->group_info); > + /* These aren't relevant for local (network is bypassed) */ > + svc->cr_principal = NULL; > + svc->cr_gss_mech = NULL; > +} > +EXPORT_SYMBOL_GPL(svcauth_map_clnt_to_svc_cred_local); > + > /************************************************** > * 'auth_domains' are stored in a hash table indexed by name. > * When the last reference to an 'auth_domain' is dropped, This is where the magic happens. Took me a bit to understand, but since we're working in kuid_t/kgid_t, we don't need to worry about further idmapping. Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>