diff mbox series

[v14,12/25] SUNRPC: add svcauth_map_clnt_to_svc_cred_local

Message ID 20240829010424.83693-13-snitzer@kernel.org (mailing list archive)
State New
Headers show
Series nfs/nfsd: add support for LOCALIO | expand

Commit Message

Mike Snitzer Aug. 29, 2024, 1:04 a.m. UTC
From: Weston Andros Adamson <dros@primarydata.com>

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@suse.de> # to approximate unx_marshal()
Signed-off-by: Weston Andros Adamson <dros@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Co-developed-by: Mike Snitzer <snitzer@kernel.org>
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
---
 include/linux/sunrpc/svcauth.h |  5 +++++
 net/sunrpc/svcauth.c           | 28 ++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

Comments

Chuck Lever III Aug. 29, 2024, 3:50 p.m. UTC | #1
On Wed, Aug 28, 2024 at 09:04:07PM -0400, Mike Snitzer wrote:
> From: Weston Andros Adamson <dros@primarydata.com>
> 
> 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@suse.de> # to approximate unx_marshal()
> Signed-off-by: Weston Andros Adamson <dros@primarydata.com>
> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
> Co-developed-by: Mike Snitzer <snitzer@kernel.org>
> Signed-off-by: Mike Snitzer <snitzer@kernel.org>
> ---
>  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,
> -- 
> 2.44.0
> 

Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Jeff Layton Aug. 29, 2024, 4:01 p.m. UTC | #2
On Wed, 2024-08-28 at 21:04 -0400, Mike Snitzer wrote:
> From: Weston Andros Adamson <dros@primarydata.com>
> 
> 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@suse.de> # to approximate unx_marshal()
> Signed-off-by: Weston Andros Adamson <dros@primarydata.com>
> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
> Co-developed-by: Mike Snitzer <snitzer@kernel.org>
> Signed-off-by: Mike Snitzer <snitzer@kernel.org>
> ---
>  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@kernel.org>
diff mbox series

Patch

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,