Re: [PATCH Version 5 08/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Andy,

On 02/24/2017 05:19 PM, andros@xxxxxxxxxx wrote:
> From: Andy Adamson <andros@xxxxxxxxxx>
> 
> Signed-off-by: Andy Adamson <andros@xxxxxxxxxx>
> ---
>  net/sunrpc/auth_gss/auth_gss.c | 140 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 138 insertions(+), 2 deletions(-)
> 
> diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
> index 6ffb16d..98971cf 100644
> --- a/net/sunrpc/auth_gss/auth_gss.c
> +++ b/net/sunrpc/auth_gss/auth_gss.c
> @@ -52,9 +52,12 @@
>  #include <linux/sunrpc/gss_api.h>
>  #include <linux/uaccess.h>
>  #include <linux/hashtable.h>
> +#include <linux/security.h>
>  
>  #include "../netns.h"
>  
> +static int gss3_create_label(struct rpc_cred *cred, int gss_vers);
> +
>  static const struct rpc_authops authgss_ops;
>  
>  static const struct rpc_credops gss_credops;
> @@ -128,6 +131,20 @@ gss_put_ctx(struct gss_cl_ctx *ctx)
>  		gss_free_ctx(ctx);
>  }
>  
> +/* gss3_label_enabled:
> + * Called to determine if Full Mode Mandatory Access Control (MAC)
> + * over a GSS connection is desired.
> + *
> + * Note:
> + * Currently Full Mode MAC is assuemed if SeLinux is enabled and
> + * RPCSEC_GSS version 3 is in use.
> + */
> +static inline bool
> +gss3_label_assertion_is_enabled(u32 rpcsec_version)
> +{
> +	return (rpcsec_version == RPC_GSS3_VERSION && selinux_is_enabled());
> +}
> +
>  /* gss_cred_set_ctx:
>   * called by gss_upcall_callback and gss_create_upcall in order
>   * to set the gss context. The actual exchange of an old context
> @@ -145,6 +162,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
>  	set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
>  	smp_mb__before_atomic();
>  	clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
> +	gss3_create_label(cred, ctx->gc_v);
>  }
>  
>  static const void *
> @@ -1602,6 +1620,75 @@ static int gss_cred_is_negative_entry(struct rpc_cred *cred)
>  #define GSS3_createres_maxsz   (1 /* cr_hlen */ + \
>  				XDR_QUADLEN(1024) /* cr_handle*/ + \
>  				GSS3_createargs_maxsz)
> +#define GSS3_labelargs_maxsz	(1 /* la_lfs */ + \
> +				 1 /* la_pi */ + \
> +				 1 /* la_label.len */ + \
> +				 XDR_QUADLEN(1024) /* la_label.data */)
> +#define GSS3_labelres_maxsz	GSS3_labelargs_maxsz
> +
> +static void
> +gss3_enc_label(struct rpc_rqst *req, struct xdr_stream *xdr,
> +	       const struct gss3_create_args *g3ca)
> +{
> +	struct gss3_label *gl;
> +	__be32 *p;
> +
> +	gl = &g3ca->ca_assertions[0].u.au_label;
> +
> +	dprintk("RPC: %5u encoding GSSv3 label %s:%d\n", req->rq_task->tk_pid,
> +		(char *)gl->la_label.data, gl->la_label.len);
> +
> +	p = xdr_reserve_space(xdr, GSS3_labelargs_maxsz << 2);
> +	*p++ = cpu_to_be32(0); /* la_lfs */
> +	*p++ = cpu_to_be32(0); /* la_pi */
> +	p = xdr_encode_netobj(p, &gl->la_label);
> +}
> +
> +static int
> +gss3_dec_label(struct rpc_rqst *req, struct xdr_stream *xdr,
> +	       struct gss3_create_res *g3cr)
> +{
> +	struct gss3_label *gl;
> +	struct gss3_assertion_u *g3a;
> +	__be32 *p;
> +
> +	/* Used to store assertion in parent gss_cl_ctx */
> +	g3a = kzalloc(sizeof(*g3a), GFP_KERNEL);
> +	if (!g3a)
> +		goto out_err;
> +
> +	g3a->au_type = GSS3_LABEL;
> +	gl = &g3a->u.au_label;
> +
> +	p = xdr_inline_decode(xdr, 12);
> +	if (unlikely(!p))
> +		goto out_overflow;
> +
> +	gl->la_lfs = be32_to_cpup(p++);
> +	gl->la_pi = be32_to_cpup(p++);
> +	gl->la_label.len = be32_to_cpup(p++);
> +
> +	p = xdr_inline_decode(xdr, gl->la_label.len);
> +	if (unlikely(!p))
> +		goto out_overflow;
> +
> +	gl->la_label.data = kmemdup(p, gl->la_label.len, GFP_KERNEL);
> +	if (!gl->la_label.data)
> +		goto out_free_assert;
> +
> +	g3cr->cr_assertions = g3a;
> +
> +	return 0;
> +
> +out_free_assert:
> +	kfree(g3a);
> +out_err:
> +	return -EIO;
> +out_overflow:
> +	pr_warn("RPC    %s End of receive buffer. Remaining len: %tu words.\n",
> +		__func__, xdr->end - xdr->p);
> +	goto out_free_assert;
> +}
>  
>  static void
>  gss3_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr,
> @@ -1618,6 +1705,8 @@ gss3_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr,
>  	*p++ = type;
>  	switch (type) {
>  	case GSS3_LABEL:
> +		gss3_enc_label(req, xdr, g3ca);
> +		break;
>  	case GSS3_PRIVS:
>  	default:
>  		/* drop through to return */
> @@ -1673,6 +1762,9 @@ gss3_dec_create(struct rpc_rqst *req, struct xdr_stream *xdr,
>  	type = be32_to_cpup(p++);
>  	switch (type) {
>  	case GSS3_LABEL:
> +		if (gss3_dec_label(req, xdr, g3cr) != 0)
> +			goto out_free_handle;
> +		break;
>  	case GSS3_PRIVS:
>  	default:
>  		pr_warn("RPC    Unsupported gss3 create assertion %d\n", type);
> @@ -1692,13 +1784,16 @@ gss3_dec_create(struct rpc_rqst *req, struct xdr_stream *xdr,
>  
>  #define RPC_PROC_NULL 0
>  
> +#define GSS3_create_args_max	(GSS3_createargs_maxsz + GSS3_labelargs_maxsz)
> +#define GSS3_create_res_max	(GSS3_createres_maxsz + GSS3_labelres_maxsz)
> +
>  struct rpc_procinfo gss3_label_assertion[] = {
>  	[RPC_GSS_PROC_CREATE] = {
>  		.p_proc		= RPC_PROC_NULL,
>  		.p_encode	= (kxdreproc_t)gss3_enc_create,
>  		.p_decode	= (kxdrdproc_t)gss3_dec_create,
> -		.p_arglen	= GSS3_createargs_maxsz,
> -		.p_replen	= GSS3_createres_maxsz,
> +		.p_arglen	= GSS3_create_args_max,
> +		.p_replen	= GSS3_create_res_max,
>  		.p_statidx	= RPC_GSS_PROC_CREATE,
>  		.p_timer	= 0,
>  		.p_name		= "GSS_PROC_CREATE",
> @@ -1773,6 +1868,47 @@ gss3_proc_create(struct rpc_cred *cred, struct gss3_assertion_u *asserts,
>  	return ret;
>  }
>  
> +/**
> + * GSS3 Label Assertion
> + *
> + * Support one label assertion
> + *
> + * XXX Return not checked. Should we fail nfs requests if
> + * a label fails to be created? I think the server enforcing
> + * Full Mode MAC will reject an NFS request that does not use
> + * a GSS3 (child) context with the correct label.
> + */
> +static int
> +gss3_create_label(struct rpc_cred *cred, int gss_vers)
> +{
> +	struct gss3_assertion_u *asserts;
> +	struct gss3_label *gl;
> +	int ret;
> +
> +	if (!gss3_label_assertion_is_enabled(gss_vers))
> +		return -EINVAL;
> +
> +	asserts = kzalloc(sizeof(*asserts), GFP_NOFS);
> +	if (!asserts)
> +		return -ENOMEM;
> +
> +	/* NOTE: not setting la_lfs, la_pi. Do we even need them? */
> +	asserts->au_type = GSS3_LABEL;
> +	gl = &asserts->u.au_label;
> +
> +	ret = -EINVAL;
> +	ret = security_current_sid_to_context((char **)&gl->la_label.data,
> +					      &gl->la_label.len);

I think you only need to assign "ret" once here

Thanks,
Anna

> +	if (ret)
> +		goto out_free_asserts;
> +
> +	return gss3_proc_create(cred, asserts, 1);
> +
> +out_free_asserts:
> +	kfree(asserts);
> +	return ret;
> +}
> +
>  /*
>  * Refresh credentials. XXX - finish
>  */
> 
--
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



[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux