All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set
@ 2017-02-24 22:19 andros
  2017-02-24 22:19 ` [PATCH Version 5 01/17] SUNRPC handle unsupported RPCSEC_GSS security service andros
                   ` (17 more replies)
  0 siblings, 18 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

This patchset implements RFC 7861  RPCSEC_GSS Version 3 RPCSEC_GSS_CREATE
operation with rgs3_label payloads to provide  full mode Mandatory Access
Control (MAC) when run with NFSv4.2 Labeled NFS using SeLinux.

A lot more testing is needed - and planned :)

Client was built on Trond's testing branch, 4.10.0 kernel.
Server was  built on Bruce's nfsd-next branch, 4.10.0-rc7 kernel

nfsd-next branch has these server required patches missing from Tronds
testing branch:

1) svcrpc: free contexts immediately on PROC_DESTROY
2) nfsd: opt in to labeled nfs per export

Version-5.
---------
- responded to comments from Anna Schumaker
- refactored code to split generice RPCSEC_GSS_CREATE from label payload
- nfsd check for NFSEXP_SECURITY_LABEL export flag

Requires on Client:
-------------------
gssd patches:  "RFC: GSSD changes for RPCSEC_GSS version 3"
libtirpc patches "RFC: Libtirpc changes for RPCSEC_GSS version 3"

Implementation Features:
------------------------

GSSv3
- Negotiate GSS version - starts with GSSv3 then falls back to GSSv1 if
  GSSv3 is not supported.
- New GSSv3 reply verifier
- RPCSEC_GSS_CREATE operation generic code is separated from the payload code.
- rgss3_label assertion payload carries each client SeLinux thread label
- Supports one label assertion payload per RPCSEC_GSS_CREATE
- Kerberos pseudoflavor support (krb5, krb5i, krb5p)

TODO:
----
- Send all RPCSEC_GSS_CREATE calls with integrity or privacy
- Ensure SeLinux function exported in patch "SELINUX export
  security_current_sid_to_context" is OK with SeLinux experts.
- Perhaps add administrative ability on the client to indicate Full Mode
  MAC is desired and that NFSv4.2 Labeled NFS (LNFS) is used.

Prototype description:
---------------------
Parent GSS context: the normal GSS context
 - "Normal" GSSv3 context is the same as a "normal" GSSv1 context except
   for the new GSS Version and new reply verifier. For GSSv3 this "normal"
   context is called the parent context.

Child GSS3 context: Is returned by a successful RPCSEC_GSS_CREATE operation
 - Child context is associated with the parent context on both the client
   and the server.

If SeLinux is enabled and GSSv3 is in use, assume LNFS and GSSv3 full mode MAC.

When Full Mode MAC is used:
- Each new GSS3 context (parent) kicks off an RPCSEC_GSS_CREATE with the
client thread's SeLinux label as a payload.
  - Upon success, the RPCSEC_GSS_CREATE call creates a GSSv3 child context
    handle that asserts the thread label, and uses the parent context for
    encrytion services.
  - CLIENT: Child context and assertion is stored in an assertion list
    off the struct gss_cl_ctx.
  - SERVER: Child context has it's own rsc cache entry, and the child
    handle is stored in a list of children handles off the parent rsc entry.
  - CLIENT and SERVER: child contexts are destroyed when parent context is
    destroyed.
  - CLIENT: child context associated with the client NFS request thread
    is used for the NFS request.
  - SERVER: Using the child context handle looks up the child rsc entry.
    Using the parent context handle stored in the child rsc entry looks up
    the parent rsc entry to use for MIC creation/verification, integrity
    (krb5i)  and/or privacy (krb5p).
  - SERVER: the label asserted by the NFS request child handle is imposed
    upon the NFSD thread servicing the request just like the UID/GIDs in
    the rpc credential.

Each time a call is made, the client makes a check in gss_match to see if
the curren thread's SeLinux label has an associated GSS3 child context handle
to use. If not, an RPCSEC_GSS_CREATE call is kicked off to establish the
child context prior to the NFS request being sent. The NFS request then
uses the child context that asserts the client NFS request thread label
when sending the NFS request to the server.

Smoke Test;
----------
Setup:
- Ensure SeLinux is enabled on both client and server
- Turn on NFSv4.2 in client and server
  - SERVER: in /etc/sysconfig/nfs: RPCNFSDARGS="-V 4.2" (not needed in
    Fedora 25 as NFSv4.2 is turned on)
  - Fedora 25 SERVER export option "security_label" must be set:
    /export *(sec=krb5:sys,rw,no_subtree_check,no_root_squash,security_label)
  - CLIENT: mount -o v4.2 <server>:<export> <mntpoint>
  - Note: LNFS sends the file label in the OPEN compound GETATTR.
  - GSS3 sends the client thread label in the RPCSEC_GSS_CREATE call.
- Useful SeLinux commands
  - getenforce (setenforce) will let you know if Selinux is enforced
  - ls -Z  (shows label and fetches it via GETATTR usin LNFS)
  - ls -scontext  (shows just the label)

Note: Server should be Fedora 25 as the nfs-utils-2.1.1.2.rc1.fc25 and
kernel 5.9.10-200.fc25 supports the new "security_label" export option
which needs to be set on an exported file system that wants to support
LNFS and GSS3 labels.

Test: (run with wireshark capture)
Note: labels and conext values are from my setup. I restart gssd each test run.
Note: my server /etc/export is "/export *(sec=krb5:sys,rw,no_root_squash)"

- # mount -o v4.2,sec=krb5 <server>:<export>  <mntpoint>
  # ls <mntpoint>
  - This will create a parent GSS context for kb5i (010000000000000 say 01),
    and a GSS3 child context for krb5i parent with the client thread
    label "system_u:system_r:kernel_t:s0" with handle 02.
   - The child handle 02 is used for the EXCHANGE_ID, CREATE_SESSION, and
     RECLAIM_COMPLETE calls.
  - Then a parent GSS handle is created for krb5 (03) and a GSS3 child
    context for the krb5 parent with hanel (04) for the client thread label
    "unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023"
   - The child handle 04 is used for the PUTROOT_FH, all the mount GETATTRs
     and the LOOKUP of "/export"
   - A new GSS3 child context (05) is created for krb5 parent with label
     "system_u:system_r:kernel_t:s0"
     The child handle 05 is used for LOOKUP, ACCESS, READDIR, etc.


- # umount <mntpoint>
   - This will create a new GSS3 child context (06) for krb5i parent with the
     client thread label
     "unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023"
    - The child handle 06 is used for DESTROY_SESSION and DESTROY_CLIENTID.
  - RPCSEC_GSS_DESTROY messages are sent for the two parent contexts 01 and 03.
  - CHILD: the parent contexts and associated child contexts are destroyed.
  - SERVER: the parent context and associated child contexts are destroyed.

-->Andy


Andy Adamson (17):
  SUNRPC handle unsupported RPCSEC_GSS security service
  SUNRPC: RPCNULL call with payload for GSSv3
  SELINUX export security_current_sid_to_context
  SUNRPC GSSv3: base definitions
  SUNRPC AUTH_GSS get RPCSEC_GSS version from gssd downcall
  SUNRPC AUTH_GSS gss3 reply verifier
  SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with no payload
  SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload
  SUNRPC AUTH_GSS store GSS3 assertions in parent gss_cl_ctx
  SUNRPC AUTH_GSS store and use gss3 label assertion
  SUNRPC AUTH_GSS free assertions
  SUNRPC: AUTH_GSS add RPC_GSS_PROC_CREATE case for wrap and unwrap
  SUNRPC SVCAUTH_GSS allow RPCSEC_GSS version 1 or 3
  SUNRPC SVCAUTH_GSS gss3 reply verifier
  SUNRPC SVCAUTH_GSS gss3 create label
  SUNRPC SVCAUTH_GSS set gss3 label on nfsd thread
  SUNRPC SVCAUTH_gss store gss3 child handles in parent rsc

 fs/nfsd/auth.c                     |  11 +-
 include/linux/selinux.h            |   7 +
 include/linux/sunrpc/auth_gss.h    |  76 ++++-
 include/linux/sunrpc/clnt.h        |   3 +
 include/linux/sunrpc/gss_api.h     |  11 +
 include/linux/sunrpc/svcauth.h     |   1 +
 include/linux/sunrpc/svcauth_gss.h |   1 +
 net/sunrpc/auth_gss/auth_gss.c     | 564 ++++++++++++++++++++++++++++++++++++-
 net/sunrpc/auth_gss/svcauth_gss.c  | 549 ++++++++++++++++++++++++++++++++++--
 net/sunrpc/clnt.c                  |  20 ++
 security/selinux/hooks.c           |  14 +
 11 files changed, 1217 insertions(+), 40 deletions(-)

-- 
2.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH Version 5 01/17] SUNRPC handle unsupported RPCSEC_GSS security service
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
@ 2017-02-24 22:19 ` andros
  2017-03-09 21:54   ` J. Bruce Fields
  2017-02-24 22:19 ` [PATCH Version 5 02/17] SUNRPC: RPCNULL call with payload for GSSv3 andros
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 net/sunrpc/auth_gss/auth_gss.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index cdeb1d8..d8395ce 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1869,6 +1869,11 @@ gss_wrap_req(struct rpc_task *task,
 	case RPC_GSS_SVC_PRIVACY:
 		status = gss_wrap_req_priv(cred, ctx, encode, rqstp, p, obj);
 		break;
+	default:
+		status = -EIO;
+		pr_warn("RPC    Unsupported service level %d\n",
+			gss_cred->gc_service);
+		break;
 	}
 out:
 	gss_put_ctx(ctx);
@@ -1979,6 +1984,11 @@ gss_unwrap_resp(struct rpc_task *task,
 		if (status)
 			goto out;
 		break;
+	default:
+		status = -EIO;
+		pr_warn("RPC    Unsupported service level %d\n",
+			gss_cred->gc_service);
+		goto out;
 	}
 	/* take into account extra slack for integrity and privacy cases: */
 	cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp)
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 02/17] SUNRPC: RPCNULL call with payload for GSSv3
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
  2017-02-24 22:19 ` [PATCH Version 5 01/17] SUNRPC handle unsupported RPCSEC_GSS security service andros
@ 2017-02-24 22:19 ` andros
  2017-03-09 22:11   ` J. Bruce Fields
  2017-02-24 22:19 ` [PATCH Version 5 03/17] SELINUX export security_current_sid_to_context andros
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

RPCSEC_GSS_CREATE and RPCSEC_GSS_LIST are RPCNULL calls with a payload

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 include/linux/sunrpc/clnt.h |  3 +++
 net/sunrpc/clnt.c           | 20 ++++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 333ad11..6d9e4ac 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -175,6 +175,9 @@ int		rpc_call_sync(struct rpc_clnt *clnt,
 			      const struct rpc_message *msg, int flags);
 struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
 			       int flags);
+struct rpc_task *rpc_call_null_payload(struct rpc_clnt *clnt,
+				struct rpc_cred *cred, int flags, void *argp,
+				void *resp, struct rpc_procinfo *pinfo);
 int		rpc_restart_call_prepare(struct rpc_task *);
 int		rpc_restart_call(struct rpc_task *);
 void		rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 1dc9f3b..c6f1d04 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -2508,6 +2508,26 @@ static int rpcproc_decode_null(void *rqstp, struct xdr_stream *xdr, void *obj)
 	return 0;
 }
 
+struct rpc_task *
+rpc_call_null_payload(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags,
+		      void *argp, void *resp, struct rpc_procinfo *pinfo)
+{
+	struct rpc_message msg = {
+		.rpc_proc = pinfo,
+		.rpc_argp = argp,
+		.rpc_resp = resp,
+		.rpc_cred = cred,
+	};
+	struct rpc_task_setup task_setup_data = {
+		.rpc_client = clnt,
+		.rpc_message = &msg,
+		.callback_ops = &rpc_default_ops,
+		.flags = flags,
+	};
+	return rpc_run_task(&task_setup_data);
+}
+EXPORT_SYMBOL_GPL(rpc_call_null_payload);
+
 static struct rpc_procinfo rpcproc_null = {
 	.p_encode = rpcproc_encode_null,
 	.p_decode = rpcproc_decode_null,
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 03/17] SELINUX export security_current_sid_to_context
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
  2017-02-24 22:19 ` [PATCH Version 5 01/17] SUNRPC handle unsupported RPCSEC_GSS security service andros
  2017-02-24 22:19 ` [PATCH Version 5 02/17] SUNRPC: RPCNULL call with payload for GSSv3 andros
@ 2017-02-24 22:19 ` andros
  2017-02-24 22:19 ` [PATCH Version 5 04/17] SUNRPC GSSv3: base definitions andros
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

RPCSEC_GSS Version 3 label assertions require the client thread
sid in string context form

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 include/linux/selinux.h  |  7 +++++++
 security/selinux/hooks.c | 14 ++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/include/linux/selinux.h b/include/linux/selinux.h
index 44f4596..e82a4ba 100644
--- a/include/linux/selinux.h
+++ b/include/linux/selinux.h
@@ -24,12 +24,19 @@ struct kern_ipc_perm;
  * selinux_is_enabled - is SELinux enabled?
  */
 bool selinux_is_enabled(void);
+int security_current_sid_to_context(char **scontext, u32 *scontext_len);
 #else
 
 static inline bool selinux_is_enabled(void)
 {
 	return false;
 }
+
+static inline int
+security_current_sid_to_context(char **scontext, u32 *scontext_len)
+{
+	return -EINVAL;
+}
 #endif	/* CONFIG_SECURITY_SELINUX */
 
 #endif /* _LINUX_SELINUX_H */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c7c6619..a65f6dc 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6492,3 +6492,17 @@ int selinux_disable(void)
 	return 0;
 }
 #endif
+
+/**
+ * RPCSEC_GSS Version 3 Full Mode labeling needs this interface
+ * or one like it.
+ */
+int security_current_sid_to_context(char **scontext, u32 *scontext_len)
+{
+	const struct task_security_struct *ts = current_security();
+
+	if (!selinux_enabled)
+		return -EINVAL;
+	return security_sid_to_context(ts->sid, scontext, scontext_len);
+}
+EXPORT_SYMBOL_GPL(security_current_sid_to_context);
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 04/17] SUNRPC GSSv3: base definitions
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (2 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 03/17] SELINUX export security_current_sid_to_context andros
@ 2017-02-24 22:19 ` andros
  2017-02-24 22:19 ` [PATCH Version 5 05/17] SUNRPC AUTH_GSS get RPCSEC_GSS version from gssd downcall andros
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 include/linux/sunrpc/auth_gss.h | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 36eebc4..8939db4 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -18,6 +18,7 @@
 #include <linux/sunrpc/gss_api.h>
 
 #define RPC_GSS_VERSION		1
+#define RPC_GSS3_VERSION	3
 
 #define MAXSEQ 0x80000000 /* maximum legal sequence number, from rfc 2203 */
 
@@ -25,13 +26,17 @@ enum rpc_gss_proc {
 	RPC_GSS_PROC_DATA = 0,
 	RPC_GSS_PROC_INIT = 1,
 	RPC_GSS_PROC_CONTINUE_INIT = 2,
-	RPC_GSS_PROC_DESTROY = 3
+	RPC_GSS_PROC_DESTROY = 3,
+	RPC_GSS_PROC_BIND_CHANNEL = 4,	/* GSS2, not used */
+	RPC_GSS_PROC_CREATE = 5,	/* GSS3 */
+	RPC_GSS_PROC_LIST = 6		/* GSS3 */
 };
 
 enum rpc_gss_svc {
 	RPC_GSS_SVC_NONE = 1,
 	RPC_GSS_SVC_INTEGRITY = 2,
-	RPC_GSS_SVC_PRIVACY = 3
+	RPC_GSS_SVC_PRIVACY = 3,
+	RPC_GSS_SVC_CHANNEL_PROT = 4	/* GSS2, not used */
 };
 
 /* on-the-wire gss cred: */
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 05/17] SUNRPC AUTH_GSS get RPCSEC_GSS version from gssd downcall
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (3 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 04/17] SUNRPC GSSv3: base definitions andros
@ 2017-02-24 22:19 ` andros
  2017-03-10 16:18   ` J. Bruce Fields
  2017-02-24 22:19 ` [PATCH Version 5 06/17] SUNRPC AUTH_GSS gss3 reply verifier andros
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 include/linux/sunrpc/auth_gss.h |  1 +
 net/sunrpc/auth_gss/auth_gss.c  | 16 ++++++++++++----
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 8939db4..4ab63a9 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -71,6 +71,7 @@ struct rpc_gss_init_res {
 
 struct gss_cl_ctx {
 	atomic_t		count;
+	u32			gc_v;
 	enum rpc_gss_proc	gc_proc;
 	u32			gc_seq;
 	spinlock_t		gc_seq_lock;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index d8395ce..216a78e 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -213,6 +213,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
 	unsigned int seclen;
 	unsigned int timeout;
 	unsigned long now = jiffies;
+	unsigned int gss_v;
 	u32 window_size;
 	int ret;
 
@@ -226,6 +227,13 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
 	if (timeout == 0)
 		timeout = GSSD_MIN_TIMEOUT;
 	ctx->gc_expiry = now + ((unsigned long)timeout * HZ);
+
+	/* RPCSEC_GSS version used to obtain context */
+	p = simple_get_bytes(p, end, &gss_v, sizeof(gss_v));
+	if (IS_ERR(p))
+		goto err;
+	ctx->gc_v = gss_v;
+
 	/* Sequence number window. Determines the maximum number of
 	 * simultaneous requests
 	 */
@@ -1511,10 +1519,10 @@ gss_marshal(struct rpc_task *task, __be32 *p)
 	req->rq_seqno = ctx->gc_seq++;
 	spin_unlock(&ctx->gc_seq_lock);
 
-	*p++ = htonl((u32) RPC_GSS_VERSION);
-	*p++ = htonl((u32) ctx->gc_proc);
-	*p++ = htonl((u32) req->rq_seqno);
-	*p++ = htonl((u32) gss_cred->gc_service);
+	*p++ = htonl((u32)ctx->gc_v);
+	*p++ = htonl((u32)ctx->gc_proc);
+	*p++ = htonl((u32)req->rq_seqno);
+	*p++ = htonl((u32)gss_cred->gc_service);
 	p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);
 	*cred_len = htonl((p - (cred_len + 1)) << 2);
 
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 06/17] SUNRPC AUTH_GSS gss3 reply verifier
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (4 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 05/17] SUNRPC AUTH_GSS get RPCSEC_GSS version from gssd downcall andros
@ 2017-02-24 22:19 ` andros
  2017-03-10 16:51   ` J. Bruce Fields
  2017-02-24 22:19 ` [PATCH Version 5 07/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with no payload andros
                   ` (11 subsequent siblings)
  17 siblings, 1 reply; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

The new GSS Version 3 reply  verifier is taken over the same data as
the call verifier, caveat REPLY direction

Verifier Data

   xid          tk_rqstp->rq_xid
   direction    REPLY (always a 1) RPC_REPLY
   rpcvers      RPC_VERSION
   prog         clnt->cl_prog
   vers         clnt->cl_vers
   proc         tk_msg.rpc_proc->p_proc
   credential
         flavor       RPC_AUTH_GSS
         length       cred_len is in gss_marshal (new gv_crlen)
         gss version  ctx->gc_v
         gss proc     ctx->gv_proc
         gss seq      tk_rqstp->rq_seqno
         gss svc      gss_cred->gc_service
         gss ctx len  ctx->gc_wire_ctx
         gss ctx data ctx->gc_wire_ctx

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 net/sunrpc/auth_gss/auth_gss.c | 59 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)

diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 216a78e..499cf99 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1624,6 +1624,53 @@ gss_refresh_null(struct rpc_task *task)
 	return 0;
 }
 
+/**
+ * gss3_reply_verifier: The new gssv3 verifier uses same data as call
+ * caveat REPLY direction - see rpc_encode_header
+ */
+static  void *
+gss3_reply_verifier(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
+		    struct rpc_task *task, __be32 *seq, struct kvec *iov)
+{
+	struct gss_cred *g_cred = container_of(cred, struct gss_cred, gc_base);
+	void	*gss3_buf = NULL;
+	__be32 *crlen, *ptr = NULL;
+	int len;
+
+	/* freed in gss_validate */
+	len = (13 * 4) + ctx->gc_wire_ctx.len;
+	gss3_buf = kmalloc(len, GFP_NOFS);
+	if (!gss3_buf) {
+		gss3_buf = ERR_PTR(-EIO);
+		goto out;
+	}
+	ptr = (__be32 *)gss3_buf;
+
+	*ptr++ = htonl(task->tk_rqstp->rq_xid);
+	*ptr++ = htonl(RPC_REPLY);
+	*ptr++ = htonl(RPC_VERSION);
+	*ptr++ = htonl(task->tk_client->cl_prog);
+	*ptr++ = htonl(task->tk_client->cl_vers);
+	*ptr++ = htonl(task->tk_msg.rpc_proc->p_proc);
+	*ptr++ = htonl(RPC_AUTH_GSS);
+
+	/* credential */
+	crlen = ptr++;
+	*ptr++ = htonl(ctx->gc_v);
+	*ptr++ = htonl(ctx->gc_proc);
+	*ptr++ = *seq;
+	*ptr++ = htonl(g_cred->gc_service);
+	ptr = xdr_encode_netobj(ptr, &ctx->gc_wire_ctx);
+
+	/* backfill cred length */
+	*crlen = htonl((ptr - (crlen + 1)) << 2);
+
+	iov->iov_base = gss3_buf;
+	iov->iov_len = (ptr - (__be32 *)gss3_buf) << 2;
+out:
+	return gss3_buf;
+}
+
 static __be32 *
 gss_validate(struct rpc_task *task, __be32 *p)
 {
@@ -1633,6 +1680,7 @@ gss_validate(struct rpc_task *task, __be32 *p)
 	struct kvec	iov;
 	struct xdr_buf	verf_buf;
 	struct xdr_netobj mic;
+	void	*g3_buf = NULL;
 	u32		flav,len;
 	u32		maj_stat;
 	__be32		*ret = ERR_PTR(-EIO);
@@ -1648,14 +1696,21 @@ gss_validate(struct rpc_task *task, __be32 *p)
 	if (!seq)
 		goto out_bad;
 	*seq = htonl(task->tk_rqstp->rq_seqno);
-	iov.iov_base = seq;
-	iov.iov_len = 4;
+	if (ctx->gc_v == RPC_GSS_VERSION) {
+		iov.iov_base = seq;
+		iov.iov_len = 4;
+	} else if (ctx->gc_v == RPC_GSS3_VERSION) {
+		g3_buf = gss3_reply_verifier(cred, ctx, task, seq, &iov);
+		if (IS_ERR(g3_buf))
+			goto out_bad;
+	}
 	xdr_buf_from_iov(&iov, &verf_buf);
 	mic.data = (u8 *)p;
 	mic.len = len;
 
 	ret = ERR_PTR(-EACCES);
 	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
+	kfree(g3_buf);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
 		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
 	if (maj_stat) {
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 07/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with no payload
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (5 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 06/17] SUNRPC AUTH_GSS gss3 reply verifier andros
@ 2017-02-24 22:19 ` andros
  2017-03-10 17:25   ` J. Bruce Fields
  2017-02-24 22:19 ` [PATCH Version 5 08/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload andros
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 include/linux/sunrpc/auth_gss.h |  54 ++++++++++++
 net/sunrpc/auth_gss/auth_gss.c  | 182 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 236 insertions(+)

diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 4ab63a9..b2a5a61 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -93,6 +93,60 @@ struct gss_cred {
 	unsigned long		gc_upcall_timestamp;
 };
 
+/** GSS3 */
+enum gss3_type {
+	GSS3_LABEL = 0,
+	GSS3_PRIVS = 1,
+};
+
+struct gss3_chan_binding {
+	u32	cb_len;
+	void	*cb_binding;
+};
+
+struct gss3_mp_auth {
+	u32	mp_handle_len;
+	void	*mp_handle;
+	u32	*mp_mic_len;
+	void	*mp_mic;	/* header mic */
+};
+
+struct gss3_label {
+	u32			la_lfs;
+	u32			la_pi;
+	struct xdr_netobj	la_label;
+};
+
+struct gss3_privs {
+	char	*pr_name;
+	u32	pr_num;
+	void	*pr_data;
+};
+
+struct gss3_assertion_u {
+	u32	au_type;
+	union {
+		struct gss3_label	au_label;
+		struct gss3_privs	au_privs;
+	} u;
+};
+
+struct gss3_create_args {
+	struct gss3_mp_auth		*ca_mp_auth;
+	struct gss3_chan_binding	*ca_chan_bind;
+	u32			ca_num;
+	struct gss3_assertion_u	*ca_assertions;
+};
+
+struct gss3_create_res {
+	u32		cr_hlen;
+	void		*cr_handle;
+	struct gss3_mp_auth		*cr_mp_auth;
+	struct gss3_chan_binding	*cr_chan_bind;
+	u32			cr_num;
+	struct gss3_assertion_u	*cr_assertions;
+};
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_AUTH_GSS_H */
 
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 499cf99..6ffb16d 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1591,6 +1591,188 @@ static int gss_cred_is_negative_entry(struct rpc_cred *cred)
 	return 0;
 }
 
+/**
+ * GSS3_createargs_maxsz and GSS3_createres_maxsz
+ * include no rgss3_assertion_u payload.
+ */
+#define GSS3_createargs_maxsz  (1 /* empty ca_mp_auth */ + \
+				1 /* empty ca_chan_bind */ + \
+				1 /* ca_num */ + \
+				1 /* au_type */)
+#define GSS3_createres_maxsz   (1 /* cr_hlen */ + \
+				XDR_QUADLEN(1024) /* cr_handle*/ + \
+				GSS3_createargs_maxsz)
+
+static void
+gss3_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr,
+		const struct gss3_create_args *g3ca)
+{
+	u32 type;
+	__be32 *p;
+
+	p = xdr_reserve_space(xdr, GSS3_createargs_maxsz << 2);
+	*p++ = cpu_to_be32(0); /* NULL ca_mp_auth */
+	*p++ = cpu_to_be32(0); /* NULL ca_chan_bind */
+	*p++ = cpu_to_be32(g3ca->ca_num);
+	type = cpu_to_be32(g3ca->ca_assertions->au_type);
+	*p++ = type;
+	switch (type) {
+	case GSS3_LABEL:
+	case GSS3_PRIVS:
+	default:
+		/* drop through to return */
+		pr_warn("RPC    Unsupported gss3 create assertion %d\n", type);
+	}
+}
+
+static int
+gss3_dec_create(struct rpc_rqst *req, struct xdr_stream *xdr,
+		struct gss3_create_res *g3cr)
+{
+	u32 dummy, type;
+	__be32 *p;
+
+	p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	g3cr->cr_hlen = be32_to_cpup(p++);
+
+	p = xdr_inline_decode(xdr, g3cr->cr_hlen + 16);
+	if (unlikely(!p))
+		goto out_overflow;
+
+	g3cr->cr_handle = kmemdup(p, g3cr->cr_hlen, GFP_KERNEL);
+	if (!g3cr->cr_handle)
+		goto out_err;
+
+	p += XDR_QUADLEN(g3cr->cr_hlen);
+
+	/* cr_mp_auth: not supported */
+	dummy = be32_to_cpup(p++);
+	if (dummy != 0) {
+		pr_warn("RPC    gss3 create cr_mp_auth not supported\n");
+		goto out_free_handle;
+	}
+
+	/* cr_chan_bind: not supported */
+	dummy = be32_to_cpup(p++);
+	if (dummy != 0) {
+		pr_warn("RPC    gss3 create cr_chan_bind not supported\n");
+		goto out_free_handle;
+	}
+
+	/* XXX Support one assertion */
+	g3cr->cr_num = be32_to_cpup(p++);
+	if (g3cr->cr_num != 1) {
+		pr_warn("RPC    gss3 multiple assertions %d unspported\n",
+			g3cr->cr_num);
+		goto out_free_handle;
+	}
+
+	/* au_type */
+	type = be32_to_cpup(p++);
+	switch (type) {
+	case GSS3_LABEL:
+	case GSS3_PRIVS:
+	default:
+		pr_warn("RPC    Unsupported gss3 create assertion %d\n", type);
+		goto out_free_handle;
+	}
+	return 0;
+
+out_free_handle:
+	kfree(g3cr->cr_handle);
+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_err;
+}
+
+#define RPC_PROC_NULL 0
+
+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_statidx	= RPC_GSS_PROC_CREATE,
+		.p_timer	= 0,
+		.p_name		= "GSS_PROC_CREATE",
+	},
+};
+
+/**
+ * RPC_GSS_PROC_CREATE operation
+ *
+ * Notes:
+ *    1) Spec says we MUST use integrity or privacy security service.
+ *    First pass; use rpc_gss_svc_none.
+ *    2) asserts are allocated by caller, and freed here.
+ */
+static int
+gss3_proc_create(struct rpc_cred *cred, struct gss3_assertion_u *asserts,
+		 int numasserts)
+{
+	struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth,
+						 rpc_auth);
+	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
+	struct rpc_task *task;
+	struct gss3_create_res cres = {
+		.cr_mp_auth = 0,
+	};
+	struct gss3_create_args *cargs = NULL;
+	int ret = -EINVAL;
+
+	if (!ctx || !asserts)
+		goto out;
+	/**
+	 * Take a reference to ensure the cred sticks around as we create
+	 * a child context
+	 * XXX does grabbing a reference to the context (gss_cred_get_ctx)
+	 * also keep the cred from being removed?
+	 * XXX do we need to keep this cred reference until the child context
+	 * handle and associated assertion is removed?
+	 */
+	get_rpccred(cred);
+
+	ret = -ENOMEM;
+	cargs = kzalloc(sizeof(*cargs), GFP_NOFS);
+	if (!cargs)
+		goto out_err;
+
+	cargs->ca_assertions = asserts;
+	cargs->ca_num = numasserts;
+	ctx->gc_proc = RPC_GSS_PROC_CREATE;
+	cred->cr_ops = &gss_credops;
+
+	/* Want a sync rpc call */
+	task = rpc_call_null_payload(gss_auth->client, cred, 0, cargs, &cres,
+				    &gss3_label_assertion[RPC_GSS_PROC_CREATE]);
+	if (IS_ERR(task)) {
+		ret = PTR_ERR(task);
+		goto out_free_assert;
+	}
+	if (task->tk_status != 0) {
+		ret = task->tk_status;
+		goto out_free_assert;
+	}
+	rpc_put_task(task);
+
+out_free_assert:
+	kfree(cargs->ca_assertions);
+	kfree(cargs);
+out_err:
+	ctx->gc_proc = RPC_GSS_PROC_DATA;
+	gss_put_ctx(ctx);
+	put_rpccred(cred);
+out:
+	return ret;
+}
+
 /*
 * Refresh credentials. XXX - finish
 */
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 08/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (6 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 07/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with no payload andros
@ 2017-02-24 22:19 ` andros
  2017-02-27 21:47   ` Anna Schumaker
  2017-03-10 17:31   ` J. Bruce Fields
  2017-02-24 22:19 ` [PATCH Version 5 09/17] SUNRPC AUTH_GSS store GSS3 assertions in parent gss_cl_ctx andros
                   ` (9 subsequent siblings)
  17 siblings, 2 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 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);
+	if (ret)
+		goto out_free_asserts;
+
+	return gss3_proc_create(cred, asserts, 1);
+
+out_free_asserts:
+	kfree(asserts);
+	return ret;
+}
+
 /*
 * Refresh credentials. XXX - finish
 */
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 09/17] SUNRPC AUTH_GSS store GSS3 assertions in parent gss_cl_ctx
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (7 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 08/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload andros
@ 2017-02-24 22:19 ` andros
  2017-02-24 22:19 ` [PATCH Version 5 10/17] SUNRPC AUTH_GSS store and use gss3 label assertion andros
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 include/linux/sunrpc/auth_gss.h |  6 ++++++
 include/linux/sunrpc/gss_api.h  | 10 ++++++++++
 net/sunrpc/auth_gss/auth_gss.c  | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 55 insertions(+)

diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index b2a5a61..7f7b378 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -63,6 +63,11 @@ struct rpc_gss_init_res {
 	struct xdr_netobj	gr_token;	/* token */
 };
 
+struct gss3_assert_list {
+	struct list_head	assert_list;
+	spinlock_t		assert_lock;
+};
+
 /* The gss_cl_ctx struct holds all the information the rpcsec_gss client
  * code needs to know about a single security context.  In particular,
  * gc_gss_ctx is the context handle that is used to do gss-api calls, while
@@ -80,6 +85,7 @@ struct gss_cl_ctx {
 	struct xdr_netobj	gc_acceptor;
 	u32			gc_win;
 	unsigned long		gc_expiry;
+	struct gss3_assert_list	gc_alist;
 	struct rcu_head		gc_rcu;
 };
 
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index 68ec78c..c2c6354 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -17,6 +17,16 @@
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/uio.h>
 
+/* one gss3 assertion plus associated child context handle
+ * XXX more than one assertion per child context?
+ */
+struct gss3_assert {
+	struct list_head	gss3_list;  /* per context list of assertions */
+	struct xdr_netobj	gss3_handle; /* child handle */
+	u32			gss3_num;  /* always one for now */
+	struct gss3_assertion_u	*gss3_assertion;
+};
+
 /* The mechanism-independent gss-api context: */
 struct gss_ctx {
 	struct gss_api_mech	*mech_type;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 98971cf..18b97a7 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -219,6 +219,8 @@ gss_alloc_context(void)
 		ctx->gc_seq = 1;	/* NetApp 6.4R1 doesn't accept seq. no. 0 */
 		spin_lock_init(&ctx->gc_seq_lock);
 		atomic_set(&ctx->count,1);
+		INIT_LIST_HEAD(&ctx->gc_alist.assert_list);
+		spin_lock_init(&ctx->gc_alist.assert_lock);
 	}
 	return ctx;
 }
@@ -1610,6 +1612,35 @@ static int gss_cred_is_negative_entry(struct rpc_cred *cred)
 }
 
 /**
+ * The gss3_handle and gss3_assertions are allocated in gss3_dec_label
+ */
+static struct gss3_assert *
+gss3_alloc_init_assertion(struct gss3_create_res *cres)
+{
+	struct gss3_assert *ret;
+
+	ret = kzalloc(sizeof(*ret), GFP_NOFS);
+	if (!ret)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&ret->gss3_list);
+	ret->gss3_handle.len = cres->cr_hlen;
+	ret->gss3_handle.data = cres->cr_handle;
+	ret->gss3_num = cres->cr_num;
+	ret->gss3_assertion = cres->cr_assertions;
+	return ret;
+}
+
+void
+gss3_insert_assertion(struct gss3_assert_list *alist, struct gss3_assert *g3a)
+{
+	spin_lock(&alist->assert_lock);
+	/* list_add_tail_rcu(new,head) inserts new before head */
+	list_add_tail_rcu(&g3a->gss3_list, &alist->assert_list);
+	spin_unlock(&alist->assert_lock);
+}
+
+/**
  * GSS3_createargs_maxsz and GSS3_createres_maxsz
  * include no rgss3_assertion_u payload.
  */
@@ -1820,6 +1851,7 @@ gss3_proc_create(struct rpc_cred *cred, struct gss3_assertion_u *asserts,
 		.cr_mp_auth = 0,
 	};
 	struct gss3_create_args *cargs = NULL;
+	struct gss3_assert *g3a = NULL;
 	int ret = -EINVAL;
 
 	if (!ctx || !asserts)
@@ -1857,6 +1889,13 @@ gss3_proc_create(struct rpc_cred *cred, struct gss3_assertion_u *asserts,
 	}
 	rpc_put_task(task);
 
+	g3a = gss3_alloc_init_assertion(&cres);
+	if (IS_ERR(g3a)) {
+		ret = PTR_ERR(task);
+		goto out_free_assert;
+	}
+	gss3_insert_assertion(&ctx->gc_alist, g3a);
+
 out_free_assert:
 	kfree(cargs->ca_assertions);
 	kfree(cargs);
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 10/17] SUNRPC AUTH_GSS store and use gss3 label assertion
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (8 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 09/17] SUNRPC AUTH_GSS store GSS3 assertions in parent gss_cl_ctx andros
@ 2017-02-24 22:19 ` andros
  2017-02-24 22:19 ` [PATCH Version 5 11/17] SUNRPC AUTH_GSS free assertions andros
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Store gss3 assertions in the parent gss_cl_ctx. Choose to use a child
or parent context handle in gss_marshal and in gss3_reply_verifier.

Note: Need to add a test for full mode labeling. Current code only tests
for the GSS version == 3 and selinx enabled.

Perhaps an auth_rpcgss module parameter?

In gss_cred_set_ctx() after assigning a new gss context to a credential,
call gss3_create_label which will kick off an RPCSED_GSS_CREATE for the
thread's label if selinux is enabled.

In gss_match(), check if the current threads SeLinux label (sid)  has
a matching label assertion. If not, kick off an RPCSEC_GSS_CREATE for
the thread's label.

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 include/linux/sunrpc/svcauth_gss.h |  1 +
 net/sunrpc/auth_gss/auth_gss.c     | 69 ++++++++++++++++++++++++++++++++++++--
 net/sunrpc/auth_gss/svcauth_gss.c  |  2 +-
 3 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/include/linux/sunrpc/svcauth_gss.h b/include/linux/sunrpc/svcauth_gss.h
index 726aff1..af45bff 100644
--- a/include/linux/sunrpc/svcauth_gss.h
+++ b/include/linux/sunrpc/svcauth_gss.h
@@ -22,6 +22,7 @@ int gss_svc_init_net(struct net *net);
 void gss_svc_shutdown_net(struct net *net);
 int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
 u32 svcauth_gss_flavor(struct auth_domain *dom);
+int netobj_equal(struct xdr_netobj *a, struct xdr_netobj *b);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 18b97a7..0b925fb 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -57,6 +57,8 @@
 #include "../netns.h"
 
 static int gss3_create_label(struct rpc_cred *cred, int gss_vers);
+static struct gss3_assert *gss3_use_child_handle(struct gss_cl_ctx *ctx);
+static struct gss3_assert *gss3_match_label(struct gss3_assert_list *in);
 
 static const struct rpc_authops authgss_ops;
 
@@ -1472,13 +1474,16 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
 {
 	struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
 	struct gss_cl_ctx *ctx;
+	struct gss3_assert *g3a;
 	int ret;
+	bool gss3_label_enabled = false;
 
 	if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
 		goto out;
 	/* Don't match with creds that have expired. */
 	rcu_read_lock();
 	ctx = rcu_dereference(gss_cred->gc_ctx);
+	gss3_label_enabled = gss3_label_assertion_is_enabled(ctx->gc_v);
 	if (!ctx || time_after(jiffies, ctx->gc_expiry)) {
 		rcu_read_unlock();
 		return 0;
@@ -1509,6 +1514,13 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
 		/* tell NFS layer that key will expire soon */
 		set_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags);
 	}
+	if (ret && gss3_label_enabled) {
+		ctx = gss_cred_get_ctx(rc);
+		g3a = gss3_match_label(&ctx->gc_alist);
+		if (!g3a)
+			gss3_create_label(rc, ctx->gc_v);
+		gss_put_ctx(ctx);
+	}
 	return ret;
 }
 
@@ -1529,6 +1541,7 @@ gss_marshal(struct rpc_task *task, __be32 *p)
 	struct xdr_netobj mic;
 	struct kvec	iov;
 	struct xdr_buf	verf_buf;
+	struct gss3_assert *g3a;
 
 	dprintk("RPC: %5u %s\n", task->tk_pid, __func__);
 
@@ -1543,7 +1556,11 @@ gss_marshal(struct rpc_task *task, __be32 *p)
 	*p++ = htonl((u32)ctx->gc_proc);
 	*p++ = htonl((u32)req->rq_seqno);
 	*p++ = htonl((u32)gss_cred->gc_service);
-	p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);
+	g3a = gss3_use_child_handle(ctx);
+	if (g3a)
+		p = xdr_encode_netobj(p, &g3a->gss3_handle);
+	else
+		p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);
 	*cred_len = htonl((p - (cred_len + 1)) << 2);
 
 	/* We compute the checksum for the verifier over the xdr-encoded bytes
@@ -1640,6 +1657,49 @@ gss3_insert_assertion(struct gss3_assert_list *alist, struct gss3_assert *g3a)
 	spin_unlock(&alist->assert_lock);
 }
 
+static struct gss3_assert *
+gss3_match_label(struct gss3_assert_list *in)
+{
+	struct gss3_assert *found;
+	struct xdr_netobj label;
+	int ret;
+
+	/* Need a Full Mode stanza in /etc/selinux/config to check */
+	if (!gss3_label_assertion_is_enabled(RPC_GSS3_VERSION))
+		return NULL;
+
+	/* grab the current threads subject label */
+	ret = security_current_sid_to_context((char **)&label.data, &label.len);
+	if (ret)
+		return NULL;
+	rcu_read_lock();
+	list_for_each_entry_rcu(found, &in->assert_list, gss3_list) {
+		struct gss3_label *gl;
+
+		if (found->gss3_assertion->au_type != GSS3_LABEL)
+			continue;
+		gl = &found->gss3_assertion->u.au_label;
+		if (netobj_equal(&gl->la_label, &label))
+			goto out;
+	}
+	found = NULL;
+out:
+	rcu_read_lock();
+	kfree(label.data);
+	return found;
+}
+
+static struct gss3_assert *
+gss3_use_child_handle(struct gss_cl_ctx *ctx)
+{
+	struct gss3_assert *g3a = NULL;
+
+	if (gss3_label_assertion_is_enabled(ctx->gc_v) &&
+	    ctx->gc_proc == RPC_GSS_PROC_DATA)
+		g3a = gss3_match_label(&ctx->gc_alist);
+	return g3a;
+}
+
 /**
  * GSS3_createargs_maxsz and GSS3_createres_maxsz
  * include no rgss3_assertion_u payload.
@@ -1991,6 +2051,7 @@ gss3_reply_verifier(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
 {
 	struct gss_cred *g_cred = container_of(cred, struct gss_cred, gc_base);
 	void	*gss3_buf = NULL;
+	struct gss3_assert *g3a;
 	__be32 *crlen, *ptr = NULL;
 	int len;
 
@@ -2017,7 +2078,11 @@ gss3_reply_verifier(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
 	*ptr++ = htonl(ctx->gc_proc);
 	*ptr++ = *seq;
 	*ptr++ = htonl(g_cred->gc_service);
-	ptr = xdr_encode_netobj(ptr, &ctx->gc_wire_ctx);
+	g3a = gss3_use_child_handle(ctx);
+	if (g3a)
+		ptr = xdr_encode_netobj(ptr, &g3a->gss3_handle);
+	else
+		ptr = xdr_encode_netobj(ptr, &ctx->gc_wire_ctx);
 
 	/* backfill cred length */
 	*crlen = htonl((ptr - (crlen + 1)) << 2);
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index a54a7a3..aa7cb3b 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -63,7 +63,7 @@
  *
  */
 
-static int netobj_equal(struct xdr_netobj *a, struct xdr_netobj *b)
+int netobj_equal(struct xdr_netobj *a, struct xdr_netobj *b)
 {
 	return a->len == b->len && 0 == memcmp(a->data, b->data, a->len);
 }
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 11/17] SUNRPC AUTH_GSS free assertions
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (9 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 10/17] SUNRPC AUTH_GSS store and use gss3 label assertion andros
@ 2017-02-24 22:19 ` andros
  2017-02-24 22:19 ` [PATCH Version 5 12/17] SUNRPC: AUTH_GSS add RPC_GSS_PROC_CREATE case for wrap and unwrap andros
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 net/sunrpc/auth_gss/auth_gss.c | 49 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 0b925fb..5daab12 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -59,6 +59,7 @@
 static int gss3_create_label(struct rpc_cred *cred, int gss_vers);
 static struct gss3_assert *gss3_use_child_handle(struct gss_cl_ctx *ctx);
 static struct gss3_assert *gss3_match_label(struct gss3_assert_list *in);
+static void gss3_free_assertions(struct gss3_assert_list *in);
 
 static const struct rpc_authops authgss_ops;
 
@@ -1275,11 +1276,10 @@ gss_destroying_context(struct rpc_cred *cred)
 static void
 gss_do_free_ctx(struct gss_cl_ctx *ctx)
 {
-	dprintk("RPC:       %s\n", __func__);
-
 	gss_delete_sec_context(&ctx->gc_gss_ctx);
 	kfree(ctx->gc_wire_ctx.data);
 	kfree(ctx->gc_acceptor.data);
+	gss3_free_assertions(&ctx->gc_alist);
 	kfree(ctx);
 }
 
@@ -1657,6 +1657,50 @@ gss3_insert_assertion(struct gss3_assert_list *alist, struct gss3_assert *g3a)
 	spin_unlock(&alist->assert_lock);
 }
 
+static void gss3_free_label(struct gss3_label *gl)
+{
+	kfree(gl->la_label.data);
+}
+
+/**
+ * Note: Currently, only support for one assertion so gss3_num always = 1
+ */
+static void gss3_free_assertions(struct gss3_assert_list *in)
+{
+	struct gss3_assert *found, *tmp;
+	LIST_HEAD(freelist);
+
+	rcu_read_lock();
+	spin_lock(&in->assert_lock);
+	list_for_each_entry_rcu(found, &in->assert_list, gss3_list) {
+		list_del_rcu(&found->gss3_list);
+		list_add(&found->gss3_list, &freelist);
+	}
+	rcu_read_unlock();
+	spin_unlock(&in->assert_lock);
+	synchronize_rcu();
+
+	list_for_each_entry_safe(found, tmp, &freelist, gss3_list) {
+		list_del(&found->gss3_list);
+
+		/* allocated in gss3_dec_label */
+		kfree(found->gss3_handle.data);
+
+		/* gss3_num is always one for now */
+		switch (found->gss3_assertion->au_type) {
+		case GSS3_LABEL:
+			gss3_free_label(&found->gss3_assertion->u.au_label);
+			break;
+		case GSS3_PRIVS:
+		default:
+			pr_warn("RPC  %s Can't free unsupported au_type %d\n",
+				__func__, found->gss3_assertion->au_type);
+			return;
+		}
+		kfree(found);
+	}
+}
+
 static struct gss3_assert *
 gss3_match_label(struct gss3_assert_list *in)
 {
@@ -1821,6 +1865,7 @@ gss3_dec_create(struct rpc_rqst *req, struct xdr_stream *xdr,
 	if (unlikely(!p))
 		goto out_overflow;
 
+	/* freed in gss3_free_assertions */
 	g3cr->cr_handle = kmemdup(p, g3cr->cr_hlen, GFP_KERNEL);
 	if (!g3cr->cr_handle)
 		goto out_err;
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 12/17] SUNRPC: AUTH_GSS add RPC_GSS_PROC_CREATE case for wrap and unwrap
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (10 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 11/17] SUNRPC AUTH_GSS free assertions andros
@ 2017-02-24 22:19 ` andros
  2017-02-24 22:19 ` [PATCH Version 5 13/17] SUNRPC SVCAUTH_GSS allow RPCSEC_GSS version 1 or 3 andros
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 net/sunrpc/auth_gss/auth_gss.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 5daab12..73e3204 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -2380,7 +2380,8 @@ gss_wrap_req(struct rpc_task *task,
 	int             status = -EIO;
 
 	dprintk("RPC: %5u %s\n", task->tk_pid, __func__);
-	if (ctx->gc_proc != RPC_GSS_PROC_DATA) {
+	if (!(ctx->gc_proc == RPC_GSS_PROC_DATA  ||
+	      ctx->gc_proc == RPC_GSS_PROC_CREATE)) {
 		/* The spec seems a little ambiguous here, but I think that not
 		 * wrapping context destruction requests makes the most sense.
 		 */
@@ -2499,7 +2500,8 @@ gss_unwrap_resp(struct rpc_task *task,
 	int		savedlen = head->iov_len;
 	int             status = -EIO;
 
-	if (ctx->gc_proc != RPC_GSS_PROC_DATA)
+	if (!(ctx->gc_proc == RPC_GSS_PROC_DATA  ||
+	      ctx->gc_proc == RPC_GSS_PROC_CREATE))
 		goto out_decode;
 	switch (gss_cred->gc_service) {
 	case RPC_GSS_SVC_NONE:
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 13/17] SUNRPC SVCAUTH_GSS allow RPCSEC_GSS version 1 or 3
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (11 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 12/17] SUNRPC: AUTH_GSS add RPC_GSS_PROC_CREATE case for wrap and unwrap andros
@ 2017-02-24 22:19 ` andros
  2017-02-24 22:19 ` [PATCH Version 5 14/17] SUNRPC SVCAUTH_GSS gss3 reply verifier andros
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Store the version used in the context INIT phase with the context.
Check the incoming rpcsec gss version against the stored context version.

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 include/linux/sunrpc/gss_api.h    |  1 +
 net/sunrpc/auth_gss/svcauth_gss.c | 20 ++++++++++++++------
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index c2c6354..c0e5058 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -30,6 +30,7 @@ struct gss3_assert {
 /* The mechanism-independent gss-api context: */
 struct gss_ctx {
 	struct gss_api_mech	*mech_type;
+	u32			 gss_version;
 	void			*internal_ctx_id;
 };
 
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index aa7cb3b..f7aa8c4 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -976,8 +976,8 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
 }
 
 static inline int
-gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
-		struct xdr_netobj *out_handle, int *major_status)
+gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, u32 gssv,
+		    struct xdr_netobj *out_handle, int *major_status)
 {
 	struct rsc *rsci;
 	int        rc;
@@ -989,6 +989,8 @@ gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
 		*major_status = GSS_S_NO_CONTEXT;
 		return gss_write_null_verf(rqstp);
 	}
+	/* set the RPCSEC_GSS version in the context */
+	rsci->mechctx->gss_version = gssv;
 	rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
 	cache_put(&rsci->h, cd);
 	return rc;
@@ -1130,7 +1132,7 @@ static int svcauth_gss_legacy_init(struct svc_rqst *rqstp,
 
 	ret = SVC_CLOSE;
 	/* Got an answer to the upcall; use it: */
-	if (gss_write_init_verf(sn->rsc_cache, rqstp,
+	if (gss_write_init_verf(sn->rsc_cache, rqstp, gc->gc_v,
 				&rsip->out_handle, &rsip->major_status))
 		goto out;
 	if (gss_write_resv(resv, PAGE_SIZE,
@@ -1259,7 +1261,7 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
 	}
 
 	/* Got an answer to the upcall; use it: */
-	if (gss_write_init_verf(sn->rsc_cache, rqstp,
+	if (gss_write_init_verf(sn->rsc_cache, rqstp, gc->gc_v,
 				&cli_handle, &ud.major_status))
 		goto out;
 	if (gss_write_resv(resv, PAGE_SIZE,
@@ -1435,14 +1437,15 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 	rpcstart -= 7;
 
 	/* credential is:
-	 *   version(==1), proc(0,1,2,3), seq, service (1,2,3), handle
+	 *   version(==1 or 3), proc(0,1,2,3), seq, service (1,2,3), handle
 	 * at least 5 u32s, and is preceded by length, so that makes 6.
 	 */
 
 	if (argv->iov_len < 5 * 4)
 		goto auth_err;
 	crlen = svc_getnl(argv);
-	if (svc_getnl(argv) != RPC_GSS_VERSION)
+	gc->gc_v = svc_getnl(argv);
+	if ((gc->gc_v != RPC_GSS_VERSION) && (gc->gc_v != RPC_GSS3_VERSION))
 		goto auth_err;
 	gc->gc_proc = svc_getnl(argv);
 	gc->gc_seq = svc_getnl(argv);
@@ -1470,6 +1473,11 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 		rsci = gss_svc_searchbyctx(sn->rsc_cache, &gc->gc_ctx);
 		if (!rsci)
 			goto auth_err;
+		if (rsci->mechctx->gss_version != gc->gc_v) {
+			pr_warn("NFSD:  RPCSEC_GSS version mismatch (%u:%u)\n",
+				rsci->mechctx->gss_version, gc->gc_v);
+			goto auth_err;
+		}
 		switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) {
 		case SVC_OK:
 			break;
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 14/17] SUNRPC SVCAUTH_GSS gss3 reply verifier
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (12 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 13/17] SUNRPC SVCAUTH_GSS allow RPCSEC_GSS version 1 or 3 andros
@ 2017-02-24 22:19 ` andros
  2017-02-24 22:19 ` [PATCH Version 5 15/17] SUNRPC SVCAUTH_GSS gss3 create label andros
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

The new GSS Version 3 reply  verifier is taken over the same data as
the call verifier, caveat REPLY direction

verifier data

 rpc_header (6 u32s)
   XID (put32) rqstp->rq_xid
   type REPLY (putnl) always a 1.
   rpcvers u32
   prog (getnl) rqstp->rq_prog
   vers (getnl) rqstp->rq_vers
   proc (getnl) rqstp->rq_proc

 credential (7 u32s plus data)
     flavor (getnl) (new rq_flav)
     length (getnl) (new gc_crlen)
     gss version  gc_v u32 (svcauth_gss_accept)
     gss proceedure u32 gc_proc
     gss seq num    u32 gc_seq
     gss service    u32 gc_svc
     gss context length u32 gc_ctx->len

      gss context gc_ctx->data

size is 13 + gc_ctx->len.

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 include/linux/sunrpc/auth_gss.h   |  1 +
 net/sunrpc/auth_gss/svcauth_gss.c | 77 ++++++++++++++++++++++++++++++++-------
 2 files changed, 65 insertions(+), 13 deletions(-)

diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 7f7b378..59469fc 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -41,6 +41,7 @@ enum rpc_gss_svc {
 
 /* on-the-wire gss cred: */
 struct rpc_gss_wire_cred {
+	u32			gc_crlen;
 	u32			gc_v;		/* version */
 	u32			gc_proc;	/* control procedure */
 	u32			gc_seq;		/* sequence number */
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index f7aa8c4..3a42133 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -715,8 +715,50 @@ gss_write_null_verf(struct svc_rqst *rqstp)
 	return 0;
 }
 
+/**
+ * The new GSS Version 3 reply  verifier is taken over the same data as
+ * the call verifier, caveat REPLY direction
+ */
+static void *
+gss3_svc_reply_verifier(struct svc_rqst *rqstp, struct rpc_gss_wire_cred *gc,
+			struct kvec *iov, u32 seq)
+{
+	void	*gss3_buf = NULL;
+	__be32	*ptr = NULL;
+	int	len;
+
+	/* freed in gss_write_verf */
+	len = (13 * 4) + gc->gc_ctx.len;
+	gss3_buf = kmalloc(len, GFP_KERNEL);
+	if (!gss3_buf)
+		return NULL;
+
+	iov->iov_len = 0;
+	iov->iov_base = gss3_buf;
+	/* 12  __be32's plus iov_len = 13 */
+	svc_putnl(iov, rqstp->rq_xid);
+	svc_putnl(iov, RPC_REPLY);
+	svc_putnl(iov, 2);
+	svc_putnl(iov, rqstp->rq_prog);
+	svc_putnl(iov, rqstp->rq_vers);
+	svc_putnl(iov, rqstp->rq_proc);
+	svc_putnl(iov, RPC_AUTH_GSS);
+	svc_putnl(iov, gc->gc_crlen);
+	svc_putnl(iov, gc->gc_v);
+	svc_putnl(iov, gc->gc_proc);
+	svc_putnl(iov, seq);
+	svc_putnl(iov, gc->gc_svc);
+	ptr = iov->iov_base + iov->iov_len;
+
+	ptr = xdr_encode_netobj(ptr, &gc->gc_ctx);
+	iov->iov_len += sizeof(__be32); /* for ctx length */
+	iov->iov_len += gc->gc_ctx.len;
+	return gss3_buf;
+}
+
 static int
-gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
+gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id,
+	       struct rpc_gss_wire_cred *gc, u32 seq)
 {
 	__be32			*xdr_seq;
 	u32			maj_stat;
@@ -724,6 +766,7 @@ gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
 	struct xdr_netobj	mic;
 	__be32			*p;
 	struct kvec		iov;
+	void			*g3_buf = NULL;
 	int err = -1;
 
 	svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS);
@@ -732,12 +775,20 @@ gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
 		return -1;
 	*xdr_seq = htonl(seq);
 
-	iov.iov_base = xdr_seq;
-	iov.iov_len = 4;
+	if (gc->gc_v == 1) {
+		iov.iov_base = &xdr_seq;
+		iov.iov_len = 4;
+	}
+	if (gc->gc_v == 3) {
+		g3_buf = gss3_svc_reply_verifier(rqstp, gc, &iov, seq);
+		if (!g3_buf)
+			return -1;
+	}
 	xdr_buf_from_iov(&iov, &verf_data);
 	p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
 	mic.data = (u8 *)(p + 1);
 	maj_stat = gss_get_mic(ctx_id, &verf_data, &mic);
+	kfree(g3_buf);
 	if (maj_stat != GSS_S_COMPLETE)
 		goto out;
 	*p++ = htonl(mic.len);
@@ -976,7 +1027,8 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
 }
 
 static inline int
-gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, u32 gssv,
+gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
+		    struct rpc_gss_wire_cred *gc,
 		    struct xdr_netobj *out_handle, int *major_status)
 {
 	struct rsc *rsci;
@@ -990,8 +1042,8 @@ gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, u32 gssv,
 		return gss_write_null_verf(rqstp);
 	}
 	/* set the RPCSEC_GSS version in the context */
-	rsci->mechctx->gss_version = gssv;
-	rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
+	rsci->mechctx->gss_version = gc->gc_v;
+	rc = gss_write_verf(rqstp, rsci->mechctx, gc, GSS_SEQ_WIN);
 	cache_put(&rsci->h, cd);
 	return rc;
 }
@@ -1132,7 +1184,7 @@ static int svcauth_gss_legacy_init(struct svc_rqst *rqstp,
 
 	ret = SVC_CLOSE;
 	/* Got an answer to the upcall; use it: */
-	if (gss_write_init_verf(sn->rsc_cache, rqstp, gc->gc_v,
+	if (gss_write_init_verf(sn->rsc_cache, rqstp, gc,
 				&rsip->out_handle, &rsip->major_status))
 		goto out;
 	if (gss_write_resv(resv, PAGE_SIZE,
@@ -1261,7 +1313,7 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
 	}
 
 	/* Got an answer to the upcall; use it: */
-	if (gss_write_init_verf(sn->rsc_cache, rqstp, gc->gc_v,
+	if (gss_write_init_verf(sn->rsc_cache, rqstp, gc,
 				&cli_handle, &ud.major_status))
 		goto out;
 	if (gss_write_resv(resv, PAGE_SIZE,
@@ -1408,7 +1460,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 {
 	struct kvec	*argv = &rqstp->rq_arg.head[0];
 	struct kvec	*resv = &rqstp->rq_res.head[0];
-	u32		crlen;
 	struct gss_svc_data *svcdata = rqstp->rq_auth_data;
 	struct rpc_gss_wire_cred *gc;
 	struct rsc	*rsci = NULL;
@@ -1443,7 +1494,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 
 	if (argv->iov_len < 5 * 4)
 		goto auth_err;
-	crlen = svc_getnl(argv);
+	gc->gc_crlen = svc_getnl(argv);
 	gc->gc_v = svc_getnl(argv);
 	if ((gc->gc_v != RPC_GSS_VERSION) && (gc->gc_v != RPC_GSS3_VERSION))
 		goto auth_err;
@@ -1452,7 +1503,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 	gc->gc_svc = svc_getnl(argv);
 	if (svc_safe_getnetobj(argv, &gc->gc_ctx))
 		goto auth_err;
-	if (crlen != round_up_to_quad(gc->gc_ctx.len) + 5 * 4)
+	if (gc->gc_crlen != round_up_to_quad(gc->gc_ctx.len) + 5 * 4)
 		goto auth_err;
 
 	if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0))
@@ -1495,7 +1546,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 	/* now act upon the command: */
 	switch (gc->gc_proc) {
 	case RPC_GSS_PROC_DESTROY:
-		if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
+		if (gss_write_verf(rqstp, rsci->mechctx, gc, gc->gc_seq))
 			goto auth_err;
 		/* Delete the entry from the cache_list and call cache_put */
 		sunrpc_cache_unhash(sn->rsc_cache, &rsci->h);
@@ -1506,7 +1557,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 	case RPC_GSS_PROC_DATA:
 		*authp = rpcsec_gsserr_ctxproblem;
 		svcdata->verf_start = resv->iov_base + resv->iov_len;
-		if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
+		if (gss_write_verf(rqstp, rsci->mechctx, gc, gc->gc_seq))
 			goto auth_err;
 		rqstp->rq_cred = rsci->cred;
 		get_group_info(rsci->cred.cr_group_info);
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 15/17] SUNRPC SVCAUTH_GSS gss3 create label
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (13 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 14/17] SUNRPC SVCAUTH_GSS gss3 reply verifier andros
@ 2017-02-24 22:19 ` andros
  2017-02-24 22:19 ` [PATCH Version 5 16/17] SUNRPC SVCAUTH_GSS set gss3 label on nfsd thread andros
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

GSSv3 uses the same rsc fields as GSSv1 to hold GSS context information.
For GSSv3 these 'normal' rsc cache entries are termed parent rsc cache
entries.

A successful RPCSEC_GSS_CREATE call results in a child rsc cache entry,
which piggy-backs off a parent rsc cache entry, using the parent negotiated
crypto for MIC and PRIV calculations.

A child rsc cache entry does not use the cred, seqdata, nor mechctx fields.

New fields for RPCSEC_GSS_CREATE
1) parent_handle: set on a child rsc cache entry to enable the lookup of
   the parent.
2) assertions: set on a child rsc cache entry to hold the
   RPCSEC_GSS_CREATE data to assert.

Use a common "act upon the command' switch case for RPC_GSS_PROC_DATA and
RPC_GSS_PROC_CREATE to enable wrap and unwrap.

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 include/linux/sunrpc/auth_gss.h   |   5 +
 net/sunrpc/auth_gss/svcauth_gss.c | 296 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 295 insertions(+), 6 deletions(-)

diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 59469fc..150e4b7 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -138,6 +138,11 @@ struct gss3_assertion_u {
 	} u;
 };
 
+struct gss3_svc_assert {
+	u32			sa_num;
+	struct gss3_assertion_u	sa_assert;
+};
+
 struct gss3_create_args {
 	struct gss3_mp_auth		*ca_mp_auth;
 	struct gss3_chan_binding	*ca_chan_bind;
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 3a42133..bd7ceab 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -55,6 +55,9 @@
 # define RPCDBG_FACILITY	RPCDBG_AUTH
 #endif
 
+/* Global counter for context handles */
+static atomic64_t ctxhctr;
+
 /* The rpcsec_init cache is used for mapping RPCSEC_GSS_{,CONT_}INIT requests
  * into replies.
  *
@@ -324,23 +327,49 @@ struct gss_svc_seq_data {
 	spinlock_t		sd_lock;
 };
 
+/**
+ * struct rsc:
+ *
+ * GSSv3 uses the same rsc fields as GSSv1 to hold GSS context information.
+ * For GSSv3 these 'normal' rsc cache entries are termed parent rsc cache
+ * entries.
+ *
+ * A successful RPCSEC_GSS_CREATE call results in a child rsc cache entry,
+ * which piggy-backs off a parent rsc cache entry, using the parent negotiated
+ * crypto for MIC and PRIV calculations.
+ *
+ * A child rsc cache entry does not use the cred, seqdata, nor mechctx fields.
+ *
+ * New fields for RPCSEC_GSS_CREATE
+ *     1) parent_handle: set on a child rsc cache entry to enable the lookup of
+ *     the parent.
+ *     2) assertions: set on a child rsc cache entry to hold the
+ *     RPCSEC_GSS_CREATE data to assert.
+ *
+ */
 struct rsc {
 	struct cache_head	h;
 	struct xdr_netobj	handle;
+	struct xdr_netobj	parent_handle;
 	struct svc_cred		cred;
 	struct gss_svc_seq_data	seqdata;
 	struct gss_ctx		*mechctx;
+	struct gss3_svc_assert  *assertions;
 };
 
 static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old);
 static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item);
+static void gss3_free_svc_assert(struct gss3_svc_assert *g3a);
 
 static void rsc_free(struct rsc *rsci)
 {
 	kfree(rsci->handle.data);
+	kfree(rsci->parent_handle.data);
 	if (rsci->mechctx)
 		gss_delete_sec_context(&rsci->mechctx);
 	free_svc_cred(&rsci->cred);
+	if (rsci->assertions)
+		gss3_free_svc_assert(rsci->assertions);
 }
 
 static void rsc_put(struct kref *ref)
@@ -376,8 +405,15 @@ rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
 	tmp->handle.len = 0;
 	new->handle.data = tmp->handle.data;
 	tmp->handle.data = NULL;
+
+	new->parent_handle.len = tmp->handle.len;
+	tmp->parent_handle.len = 0;
+	new->parent_handle.data = tmp->handle.data;
+	tmp->parent_handle.data = NULL;
+
 	new->mechctx = NULL;
 	init_svc_cred(&new->cred);
+	new->assertions = NULL;
 }
 
 static void
@@ -388,9 +424,15 @@ update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
 
 	new->mechctx = tmp->mechctx;
 	tmp->mechctx = NULL;
+	new->parent_handle.len = tmp->parent_handle.len;
+	new->parent_handle.data = tmp->parent_handle.data;
+	tmp->parent_handle.len = 0;
+	tmp->parent_handle.data = NULL;
 	memset(&new->seqdata, 0, sizeof(new->seqdata));
 	spin_lock_init(&new->seqdata.sd_lock);
 	new->cred = tmp->cred;
+	new->assertions = tmp->assertions;
+	tmp->assertions = NULL;
 	init_svc_cred(&tmp->cred);
 }
 
@@ -1203,7 +1245,6 @@ static int gss_proxy_save_rsc(struct cache_detail *cd,
 				uint64_t *handle)
 {
 	struct rsc rsci, *rscp = NULL;
-	static atomic64_t ctxhctr;
 	long long ctxh;
 	struct gss_api_mech *gm = NULL;
 	time_t expiry;
@@ -1447,13 +1488,224 @@ static void destroy_use_gss_proxy_proc_entry(struct net *net) {}
 
 #endif /* CONFIG_PROC_FS */
 
+/**
+ * for now, support a single au_label per RPCSEC_GSS_CREATE
+ * no checks here, as the checks are in gss3_save_child
+ */
+static void gss3_free_svc_assert(struct gss3_svc_assert *g3a)
+{
+	struct gss3_label *glp = &g3a->sa_assert.u.au_label;
+
+	switch (g3a->sa_assert.au_type) {
+	case GSS3_LABEL:
+		kfree(glp->la_label.data);
+		break;
+	case GSS3_PRIVS:
+	default:
+		pr_warn("RPC    %s au_type %d not supported\n",
+			__func__, g3a->sa_assert.au_type);
+	}
+
+	kfree(g3a);
+}
+
+/**
+ * gss3_save_child_rsc()
+ * Create a child handle, set the parent handle, assertions, and add to
+ * the rsc cache.
+ *
+ * @handle - output child handle data
+ * @phandle - input parent handle
+ * @expiry - input parent expiry
+ */
+static struct gss3_svc_assert *
+gss3_save_child_rsc(struct cache_detail *cd, uint64_t *handle,
+		    struct xdr_netobj *phandle, time_t expiry,
+		    struct kvec *argv)
+{
+	struct gss3_svc_assert *g3a, *ret = NULL;
+	struct gss3_label *glp;
+	struct rsc child, *rscp = NULL;
+	unsigned int len;
+	long dummy;
+	long long ctxh;
+
+	memset(&child, 0, sizeof(child));
+
+	/* context handle */
+	ctxh = atomic64_inc_return(&ctxhctr);
+
+	/* make a copy for the caller */
+	*handle = ctxh;
+
+	/* make a copy for the rsc cache */
+	if (dup_to_netobj(&child.handle, (char *)handle, sizeof(uint64_t)))
+		goto out;
+
+	rscp = rsc_lookup(cd, &child);
+	if (!rscp)
+		goto out;
+
+	if (dup_netobj(&child.parent_handle, phandle))
+		goto out;
+	child.h.expiry_time = expiry;
+
+	/* ca_mp_auth */
+	dummy = svc_getnl(argv);
+	if (dummy != 0)
+		goto out;
+
+	/* ca_chan_bind  */
+	dummy = svc_getnl(argv);
+	if (dummy != 0)
+		goto out;
+
+	g3a = kmalloc(sizeof(*g3a), GFP_KERNEL);
+	if (!g3a)
+		goto out;
+
+	/* for now support one assertion per RPCSEC_GSS_CREATE */
+	g3a->sa_num = svc_getnl(argv);
+	if (g3a->sa_num != 1) {
+		pr_warn("RPC    Number gss3 assertions %d not 1\n",
+			g3a->sa_num);
+		goto out;
+	}
+
+	g3a->sa_assert.au_type = svc_getnl(argv);
+	switch (g3a->sa_assert.au_type) {
+	case GSS3_LABEL:
+		glp = &g3a->sa_assert.u.au_label;
+
+		/* XXX need to verify? */
+		glp->la_lfs = svc_getnl(argv);
+		glp->la_pi = svc_getnl(argv);
+
+		/**
+		 * don't use svc_safe_getnetobj as this object needs to live
+		 * in the rsc cache past the nfsd thread request processing.
+		 */
+		glp->la_label.len = svc_getnl(argv);
+		len = round_up_to_quad(glp->la_label.len);
+		if (argv->iov_len < len)
+			goto out;
+
+		if (dup_to_netobj(&glp->la_label, (char *)argv->iov_base,
+				  glp->la_label.len))
+			goto out;
+		break;
+	case GSS3_PRIVS:
+	default:
+		pr_warn("RPC    %s au_type %d not supported\n",
+			__func__, g3a->sa_assert.au_type);
+		goto out;
+	}
+	argv->iov_base += len;
+	argv->iov_len -= len;
+
+	child.assertions = g3a;
+	rscp = rsc_update(cd, &child, rscp);
+
+out:
+	rsc_free(&child);
+	if (rscp) {
+		ret = rscp->assertions;
+		cache_put(&rscp->h, cd);
+	}
+	return ret;
+}
+
+/**
+ * gss3_handle_create_req.
+ *
+ * Create a child rsc record
+ *
+ * Encode the RPCSEC_GSS_CREATE reply as follows:
+ *  4 RPC_SUCCESS
+ *  4 gss3_handle len
+ *  4 rcr_mp_auth
+ *  4 rcr_chan_bind_mic
+ *  4 gss3_num
+ *  4 au_type
+ *
+ * total encode length: 24 + gss_handlelen + au_type assert len
+ */
+static int
+gss3_handle_create_req(struct kvec *resv, struct kvec *argv, struct rsc *rsci,
+		       struct rpc_gss_wire_cred *gc, struct sunrpc_net *sn)
+{
+	struct gss3_svc_assert *g3a;
+	struct gss3_label *glp;
+	u64 c_handle;
+	struct xdr_netobj child_handle;
+	int enc_len, assert_len, ret = 0;
+
+	g3a = gss3_save_child_rsc(sn->rsc_cache, &c_handle, &gc->gc_ctx,
+				  rsci->h.expiry_time, argv);
+	if (!g3a)
+		goto auth_err;
+
+	/* set child handle for encoding */
+	child_handle.data = (u8 *)&c_handle;
+	child_handle.len = sizeof(c_handle);
+
+	/* calculate the assert length. Support one assert per request */
+	switch (g3a->sa_assert.au_type) {
+	case GSS3_LABEL:
+		/* 4 la_lfs, 4 la_pi, 4 la_label len */
+		glp = &g3a->sa_assert.u.au_label;
+		assert_len = 12 + glp->la_label.len;
+		break;
+	case GSS3_PRIVS:
+	default:
+		pr_warn("RPC    Unsupported GSS3 assertion %d\n",
+			g3a->sa_assert.au_type);
+		goto drop;
+	}
+	enc_len = 24 + child_handle.len + assert_len;
+	if (resv->iov_len + enc_len > PAGE_SIZE)
+		goto drop;
+
+	svc_putnl(resv, RPC_SUCCESS);
+
+	/* Encode the RPCSEC_GSS_CREATE payload */
+
+	if (svc_safe_putnetobj(resv, &child_handle))
+		goto auth_err;
+	svc_putnl(resv, 0);  /* NULL rcr_mp_auth */
+	svc_putnl(resv, 0);  /* NULL rcr_chan_bind_mic */
+	svc_putnl(resv, g3a->sa_num); /* the # of assertions (<>) */
+	svc_putnl(resv, g3a->sa_assert.au_type);
+
+	/* sa_num checked to be = 1 in gss3_save_child_rsc */
+	switch (g3a->sa_assert.au_type) {
+	case GSS3_LABEL:
+		svc_putnl(resv, glp->la_lfs);
+		svc_putnl(resv, glp->la_pi);
+		if (svc_safe_putnetobj(resv, &glp->la_label))
+			goto auth_err;
+		break;
+	/* already checked GSS3_PRIVS and default cases above */
+	}
+out:
+	return ret;
+auth_err:
+	ret = SVC_DENIED;
+	goto out;
+drop:
+	ret = SVC_DROP;
+	goto out;
+}
+
 /*
  * Accept an rpcsec packet.
  * If context establishment, punt to user space
  * If data exchange, verify/decrypt
  * If context destruction, handle here
+ * If gssv3 RPCSEC_GSS_CREATE handle here
  * In the context establishment and destruction case we encode
  * response here and return SVC_COMPLETE.
+ * XXXX should punt to user space for RPCSEC_GSS_CREATE payloads.
  */
 static int
 svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
@@ -1462,7 +1714,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 	struct kvec	*resv = &rqstp->rq_res.head[0];
 	struct gss_svc_data *svcdata = rqstp->rq_auth_data;
 	struct rpc_gss_wire_cred *gc;
-	struct rsc	*rsci = NULL;
+	struct rsc	*rsci = NULL, *rsci_ch = NULL;
 	__be32		*rpcstart;
 	__be32		*reject_stat = resv->iov_base + resv->iov_len;
 	int		ret;
@@ -1519,11 +1771,25 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 			return svcauth_gss_legacy_init(rqstp, gc, authp);
 	case RPC_GSS_PROC_DATA:
 	case RPC_GSS_PROC_DESTROY:
+	case RPC_GSS_PROC_CREATE:
 		/* Look up the context, and check the verifier: */
 		*authp = rpcsec_gsserr_credproblem;
+
 		rsci = gss_svc_searchbyctx(sn->rsc_cache, &gc->gc_ctx);
-		if (!rsci)
+		if (!rsci) {
+			pr_warn("RPC   gc_ctx handle not found\n");
 			goto auth_err;
+		}
+		if (rsci->parent_handle.len != 0) { /* GSSv3 child handle */
+
+			rsci_ch = rsci;
+			rsci = gss_svc_searchbyctx(sn->rsc_cache,
+						   &rsci_ch->parent_handle);
+			if (!rsci) {
+				pr_warn("RPC    parent handle not found\n");
+				goto auth_err;
+			}
+		}
 		if (rsci->mechctx->gss_version != gc->gc_v) {
 			pr_warn("NFSD:  RPCSEC_GSS version mismatch (%u:%u)\n",
 				rsci->mechctx->gss_version, gc->gc_v);
@@ -1555,6 +1821,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 		svc_putnl(resv, RPC_SUCCESS);
 		goto complete;
 	case RPC_GSS_PROC_DATA:
+	case RPC_GSS_PROC_CREATE:
 		*authp = rpcsec_gsserr_ctxproblem;
 		svcdata->verf_start = resv->iov_base + resv->iov_len;
 		if (gss_write_verf(rqstp, rsci->mechctx, gc, gc->gc_seq))
@@ -1592,8 +1859,22 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 					rsci->mechctx->mech_type,
 					GSS_C_QOP_DEFAULT,
 					gc->gc_svc);
-		ret = SVC_OK;
-		goto out;
+		/* RPC_GSS_PROC_DATA */
+		if (gc->gc_proc == RPC_GSS_PROC_DATA) {
+			ret = SVC_OK;
+			goto out;
+		}
+
+		/* RPC_GSS_PROC_CREATE */
+		ret = gss3_handle_create_req(resv, argv, rsci, gc, sn);
+		switch (ret) {
+		case 0:
+			goto out;
+		case SVC_DENIED:
+			goto auth_err;
+		case SVC_DROP:
+			goto drop;
+		}
 	}
 garbage_args:
 	ret = SVC_GARBAGE;
@@ -1611,6 +1892,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 out:
 	if (rsci)
 		cache_put(&rsci->h, sn->rsc_cache);
+	if (rsci_ch)
+		cache_put(&rsci_ch->h, sn->rsc_cache);
 	return ret;
 }
 
@@ -1762,7 +2045,8 @@ svcauth_gss_release(struct svc_rqst *rqstp)
 	int stat = -EINVAL;
 	struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
 
-	if (gc->gc_proc != RPC_GSS_PROC_DATA)
+	if (!(gc->gc_proc == RPC_GSS_PROC_DATA ||
+	      gc->gc_proc == RPC_GSS_PROC_CREATE))
 		goto out;
 	/* Release can be called twice, but we only wrap once. */
 	if (gsd->verf_start == NULL)
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 16/17] SUNRPC SVCAUTH_GSS set gss3 label on nfsd thread
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (14 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 15/17] SUNRPC SVCAUTH_GSS gss3 create label andros
@ 2017-02-24 22:19 ` andros
  2017-02-24 22:19 ` [PATCH Version 5 17/17] SUNRPC SVCAUTH_gss store gss3 child handles in parent rsc andros
  2017-03-09 21:47 ` [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set J. Bruce Fields
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Note: will need to give nfsd selinux authority to change thread label.

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 fs/nfsd/auth.c                    | 11 ++++++++++-
 include/linux/sunrpc/svcauth.h    |  1 +
 net/sunrpc/auth_gss/svcauth_gss.c | 41 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 62469c6..0330fe9 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -1,6 +1,7 @@
 /* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */
 
 #include <linux/sched.h>
+#include <linux/selinux.h>
 #include "nfsd.h"
 #include "auth.h"
 
@@ -22,7 +23,7 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 	struct group_info *rqgi;
 	struct group_info *gi;
 	struct cred *new;
-	int i;
+	int i, ret;
 	int flags = nfsexp_flags(rqstp, exp);
 
 	validate_process_creds();
@@ -77,6 +78,14 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 	else
 		new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
 							new->cap_permitted);
+
+	if (selinux_is_enabled() && rqstp->rq_authop->set_label &&
+	    (exp->ex_flags & NFSEXP_SECURITY_LABEL)) {
+		ret = rqstp->rq_authop->set_label(rqstp, new);
+		if (ret < 0)
+			/* Should nfsd fail this request? */
+			pr_warn("%s set_label FAILED  ret %d\n", __func__, ret);
+	}
 	validate_process_creds();
 	put_cred(override_creds(new));
 	put_cred(new);
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index d039320..eed6880 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -128,6 +128,7 @@ struct auth_ops {
 	int	(*release)(struct svc_rqst *rq);
 	void	(*domain_release)(struct auth_domain *);
 	int	(*set_client)(struct svc_rqst *rq);
+	int	(*set_label)(struct svc_rqst *rq, struct cred *new);
 };
 
 #define	SVC_GARBAGE	1
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index bd7ceab..f4c4ea1 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1068,6 +1068,46 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
 	return SVC_OK;
 }
 
+/**
+ * the svcdata->rsci pointer is the parent context.
+ * the svcdata->cl_cred->gc_ctx may hold the child context handle
+ * assume one GSS3_LABEL per child context.
+ */
+static int
+svcauth_gss_set_label(struct svc_rqst *rqstp, struct cred *new)
+{
+	struct gss_svc_data *svcdata = rqstp->rq_auth_data;
+	struct rpc_gss_wire_cred *gc = &svcdata->clcred;
+	struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net,
+						sunrpc_net_id);
+	struct rsc *rsci;
+	struct gss3_svc_assert *g3a;
+	struct gss3_label *g3l;
+	int ret = -1;
+
+	rsci = gss_svc_searchbyctx(sn->rsc_cache, &gc->gc_ctx);
+	if (!rsci)
+		goto out;
+
+	if (rsci->parent_handle.len == 0 || !rsci->assertions)
+		goto out_put;
+
+	g3a = rsci->assertions;
+	g3l = &g3a->sa_assert.u.au_label;
+
+	if (g3a->sa_num != 1 || g3a->sa_assert.au_type != GSS3_LABEL ||
+	    g3l->la_label.len == 0)
+		goto out_put;
+
+	/* Assume SeLinux - need to validate la_lfs and la_pi ? */
+	ret = set_security_override_from_ctx(new, (char *)g3l->la_label.data);
+
+out_put:
+	cache_put(&rsci->h, sn->rsc_cache);
+out:
+	return ret;
+}
+
 static inline int
 gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
 		    struct rpc_gss_wire_cred *gc,
@@ -2110,6 +2150,7 @@ static struct auth_ops svcauthops_gss = {
 	.release	= svcauth_gss_release,
 	.domain_release = svcauth_gss_domain_release,
 	.set_client	= svcauth_gss_set_client,
+	.set_label	= svcauth_gss_set_label,
 };
 
 static int rsi_cache_create_net(struct net *net)
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH Version 5 17/17] SUNRPC SVCAUTH_gss store gss3 child handles in parent rsc
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (15 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 16/17] SUNRPC SVCAUTH_GSS set gss3 label on nfsd thread andros
@ 2017-02-24 22:19 ` andros
  2017-03-09 21:47 ` [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set J. Bruce Fields
  17 siblings, 0 replies; 29+ messages in thread
From: andros @ 2017-02-24 22:19 UTC (permalink / raw)
  To: bfields; +Cc: trond.myklebust, schumaker.anna, linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

GSSv3 parent handles use the new children list field protected
by the new ch_lock to hold child handles created by successful
RPCSEC_GSS_CREATE calls. This list is used upon parent rsc entry
destruction to lookup child rsc cache entries so as to reap the
children. The net field is needed for the lookup.

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 net/sunrpc/auth_gss/svcauth_gss.c | 129 +++++++++++++++++++++++++++++++++++---
 1 file changed, 121 insertions(+), 8 deletions(-)

diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index f4c4ea1..ab987e3 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -345,7 +345,12 @@ struct gss_svc_seq_data {
  *     the parent.
  *     2) assertions: set on a child rsc cache entry to hold the
  *     RPCSEC_GSS_CREATE data to assert.
- *
+ *     3) net:  set on the parent rsc cache entry and is required for the
+ *     lookup associated child rsc cache entries upon parent destruction.
+ *     4) ch_lock: used by the parent; protects the children list
+ *     5) children: used by the parent rsc cache entry to hold a list of
+ *     associated child rsc cache entries and used upon parent destruction
+ *     to lookup child rsc cache entries so as to destroy the children.
  */
 struct rsc {
 	struct cache_head	h;
@@ -355,11 +360,20 @@ struct rsc {
 	struct gss_svc_seq_data	seqdata;
 	struct gss_ctx		*mechctx;
 	struct gss3_svc_assert  *assertions;
+	struct net		*net;
+	spinlock_t		ch_lock; /* for children */
+	struct list_head	children;
+};
+
+struct rsc_child_entry {
+	struct list_head	ce_list;
+	struct xdr_netobj	ce_chandle;
 };
 
 static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old);
 static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item);
 static void gss3_free_svc_assert(struct gss3_svc_assert *g3a);
+static void gss3_free_rsc_children(struct rsc *rsci);
 
 static void rsc_free(struct rsc *rsci)
 {
@@ -370,6 +384,8 @@ static void rsc_free(struct rsc *rsci)
 	free_svc_cred(&rsci->cred);
 	if (rsci->assertions)
 		gss3_free_svc_assert(rsci->assertions);
+	if (!list_empty(&rsci->children))
+		gss3_free_rsc_children(rsci);
 }
 
 static void rsc_put(struct kref *ref)
@@ -396,6 +412,14 @@ rsc_match(struct cache_head *a, struct cache_head *b)
 }
 
 static void
+init_rsc(struct rsc *rsci)
+{
+	memset(rsci, 0, sizeof(struct rsc));
+	spin_lock_init(&rsci->ch_lock);
+	INIT_LIST_HEAD(&rsci->children);
+}
+
+static void
 rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
 {
 	struct rsc *new = container_of(cnew, struct rsc, h);
@@ -414,6 +438,9 @@ rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
 	new->mechctx = NULL;
 	init_svc_cred(&new->cred);
 	new->assertions = NULL;
+	new->net = NULL;
+	spin_lock_init(&new->ch_lock);
+	INIT_LIST_HEAD(&new->children);
 }
 
 static void
@@ -434,6 +461,16 @@ update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
 	new->assertions = tmp->assertions;
 	tmp->assertions = NULL;
 	init_svc_cred(&tmp->cred);
+	new->net = tmp->net;
+	tmp->net = NULL;
+	spin_lock_init(&new->ch_lock);
+	INIT_LIST_HEAD(&new->children);
+	spin_lock(&tmp->ch_lock);
+	if (!list_empty(&tmp->children)) {
+		list_move(&tmp->children, &new->children);
+		INIT_LIST_HEAD(&tmp->children);
+	}
+	spin_unlock(&tmp->ch_lock);
 }
 
 static struct cache_head *
@@ -458,7 +495,7 @@ static int rsc_parse(struct cache_detail *cd,
 	int status = -EINVAL;
 	struct gss_api_mech *gm = NULL;
 
-	memset(&rsci, 0, sizeof(rsci));
+	init_rsc(&rsci);
 	/* context handle */
 	len = qword_get(&mesg, buf, mlen);
 	if (len < 0) goto out;
@@ -610,7 +647,7 @@ gss_svc_searchbyctx(struct cache_detail *cd, struct xdr_netobj *handle)
 	struct rsc rsci;
 	struct rsc *found;
 
-	memset(&rsci, 0, sizeof(rsci));
+	init_rsc(&rsci);
 	if (dup_to_netobj(&rsci.handle, handle->data, handle->len))
 		return NULL;
 	found = rsc_lookup(cd, &rsci);
@@ -1290,7 +1327,7 @@ static int gss_proxy_save_rsc(struct cache_detail *cd,
 	time_t expiry;
 	int status = -EINVAL;
 
-	memset(&rsci, 0, sizeof(rsci));
+	init_rsc(&rsci);
 	/* context handle */
 	status = -ENOMEM;
 	/* the handle needs to be just a unique id,
@@ -1549,6 +1586,68 @@ static void gss3_free_svc_assert(struct gss3_svc_assert *g3a)
 	kfree(g3a);
 }
 
+static void gss3_free_rsc_children(struct rsc *rsci)
+{
+	struct rsc_child_entry *cep, *tmp;
+	LIST_HEAD(free);
+	struct sunrpc_net *sn = net_generic(rsci->net, sunrpc_net_id);
+	struct rsc *child;
+
+	spin_lock(&rsci->ch_lock);
+
+	list_for_each_entry_safe(cep, tmp, &rsci->children, ce_list)
+		list_move(&cep->ce_list, &free);
+
+	spin_unlock(&rsci->ch_lock);
+
+	list_for_each_entry_safe(cep, tmp, &free, ce_list) {
+		list_del(&cep->ce_list);
+		child = gss_svc_searchbyctx(sn->rsc_cache, &cep->ce_chandle);
+		if (child) {
+			/* balance gss_svc_searchbyctx cache_get */
+			cache_put(&child->h, sn->rsc_cache);
+			 /* reap the child */
+			sunrpc_cache_unhash(sn->rsc_cache, &child->h);
+		} else
+			pr_warn("RPC    %s child in children list not found\n",
+				__func__);
+	}
+}
+
+/**
+ * After a gss3 child rsc is created, add it's context handle to the
+ * children list of the parent rsc.
+ * Required: gss_svc_searchbyctx has already been called on parent_rsc.
+ */
+static int
+gss3_add_child_rsc(struct cache_detail *cd, struct rsc *parent_rsc,
+		   struct xdr_netobj *chandle)
+{
+	struct rsc_child_entry *cep;
+	int status = -ENOMEM;
+
+	cep = kmalloc(sizeof(*cep), GFP_KERNEL);
+	if (!cep)
+		goto out;
+
+	/* child handle */
+	if (dup_netobj(&cep->ce_chandle, chandle))
+		goto out_free;
+
+	parent_rsc->net = cd->net;
+	INIT_LIST_HEAD(&cep->ce_list);
+	spin_lock(&parent_rsc->ch_lock);
+	list_add(&cep->ce_list, &parent_rsc->children);
+	spin_unlock(&parent_rsc->ch_lock);
+
+	status = 0;
+out:
+	return status;
+out_free:
+	kfree(cep);
+	goto out;
+}
+
 /**
  * gss3_save_child_rsc()
  * Create a child handle, set the parent handle, assertions, and add to
@@ -1570,8 +1669,7 @@ gss3_save_child_rsc(struct cache_detail *cd, uint64_t *handle,
 	long dummy;
 	long long ctxh;
 
-	memset(&child, 0, sizeof(child));
-
+	init_rsc(&child);
 	/* context handle */
 	ctxh = atomic64_inc_return(&ctxhctr);
 
@@ -1689,6 +1787,22 @@ gss3_handle_create_req(struct kvec *resv, struct kvec *argv, struct rsc *rsci,
 	child_handle.data = (u8 *)&c_handle;
 	child_handle.len = sizeof(c_handle);
 
+	ret = gss3_add_child_rsc(sn->rsc_cache, rsci, &child_handle);
+	if (ret < 0) {
+		struct rsc *child;
+
+		pr_warn("%s failed to add child rsc to parent\n", __func__);
+		/* delete child */
+		child = gss_svc_searchbyctx(sn->rsc_cache, &child_handle);
+		if (child) {
+			/* balance gss_svc_searchbyctx cache_get */
+			cache_put(&child->h, sn->rsc_cache);
+			 /* reap the child */
+			sunrpc_cache_unhash(sn->rsc_cache, &child->h);
+		}
+		goto auth_err;
+	}
+
 	/* calculate the assert length. Support one assert per request */
 	switch (g3a->sa_assert.au_type) {
 	case GSS3_LABEL:
@@ -1763,8 +1877,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 	dprintk("RPC:       svcauth_gss: argv->iov_len = %zd\n",
 			argv->iov_len);
 
-	*authp = rpc_autherr_badcred;
-	if (!svcdata)
+	*authp = rpc_autherr_badcred; if (!svcdata)
 		svcdata = kmalloc(sizeof(*svcdata), GFP_KERNEL);
 	if (!svcdata)
 		goto auth_err;
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 08/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload
  2017-02-24 22:19 ` [PATCH Version 5 08/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload andros
@ 2017-02-27 21:47   ` Anna Schumaker
  2017-03-10 17:31   ` J. Bruce Fields
  1 sibling, 0 replies; 29+ messages in thread
From: Anna Schumaker @ 2017-02-27 21:47 UTC (permalink / raw)
  To: andros, bfields; +Cc: trond.myklebust, linux-nfs

Hi Andy,

On 02/24/2017 05:19 PM, andros@netapp.com wrote:
> From: Andy Adamson <andros@netapp.com>
> 
> Signed-off-by: Andy Adamson <andros@netapp.com>
> ---
>  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
>  */
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set
  2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
                   ` (16 preceding siblings ...)
  2017-02-24 22:19 ` [PATCH Version 5 17/17] SUNRPC SVCAUTH_gss store gss3 child handles in parent rsc andros
@ 2017-03-09 21:47 ` J. Bruce Fields
  2017-03-10 14:48   ` Andy Adamson
  17 siblings, 1 reply; 29+ messages in thread
From: J. Bruce Fields @ 2017-03-09 21:47 UTC (permalink / raw)
  To: andros; +Cc: trond.myklebust, schumaker.anna, linux-nfs

On Fri, Feb 24, 2017 at 05:19:36PM -0500, andros@netapp.com wrote:
> From: Andy Adamson <andros@netapp.com>
> 
> This patchset implements RFC 7861  RPCSEC_GSS Version 3 RPCSEC_GSS_CREATE
> operation with rgs3_label payloads to provide  full mode Mandatory Access
> Control (MAC) when run with NFSv4.2 Labeled NFS using SeLinux.

Is GSSv3 also still planned to be used for COPY?  I lost track of that
discussion.

--b.

> 
> A lot more testing is needed - and planned :)
> 
> Client was built on Trond's testing branch, 4.10.0 kernel.
> Server was  built on Bruce's nfsd-next branch, 4.10.0-rc7 kernel
> 
> nfsd-next branch has these server required patches missing from Tronds
> testing branch:
> 
> 1) svcrpc: free contexts immediately on PROC_DESTROY
> 2) nfsd: opt in to labeled nfs per export
> 
> Version-5.
> ---------
> - responded to comments from Anna Schumaker
> - refactored code to split generice RPCSEC_GSS_CREATE from label payload
> - nfsd check for NFSEXP_SECURITY_LABEL export flag
> 
> Requires on Client:
> -------------------
> gssd patches:  "RFC: GSSD changes for RPCSEC_GSS version 3"
> libtirpc patches "RFC: Libtirpc changes for RPCSEC_GSS version 3"
> 
> Implementation Features:
> ------------------------
> 
> GSSv3
> - Negotiate GSS version - starts with GSSv3 then falls back to GSSv1 if
>   GSSv3 is not supported.
> - New GSSv3 reply verifier
> - RPCSEC_GSS_CREATE operation generic code is separated from the payload code.
> - rgss3_label assertion payload carries each client SeLinux thread label
> - Supports one label assertion payload per RPCSEC_GSS_CREATE
> - Kerberos pseudoflavor support (krb5, krb5i, krb5p)
> 
> TODO:
> ----
> - Send all RPCSEC_GSS_CREATE calls with integrity or privacy
> - Ensure SeLinux function exported in patch "SELINUX export
>   security_current_sid_to_context" is OK with SeLinux experts.
> - Perhaps add administrative ability on the client to indicate Full Mode
>   MAC is desired and that NFSv4.2 Labeled NFS (LNFS) is used.
> 
> Prototype description:
> ---------------------
> Parent GSS context: the normal GSS context
>  - "Normal" GSSv3 context is the same as a "normal" GSSv1 context except
>    for the new GSS Version and new reply verifier. For GSSv3 this "normal"
>    context is called the parent context.
> 
> Child GSS3 context: Is returned by a successful RPCSEC_GSS_CREATE operation
>  - Child context is associated with the parent context on both the client
>    and the server.
> 
> If SeLinux is enabled and GSSv3 is in use, assume LNFS and GSSv3 full mode MAC.
> 
> When Full Mode MAC is used:
> - Each new GSS3 context (parent) kicks off an RPCSEC_GSS_CREATE with the
> client thread's SeLinux label as a payload.
>   - Upon success, the RPCSEC_GSS_CREATE call creates a GSSv3 child context
>     handle that asserts the thread label, and uses the parent context for
>     encrytion services.
>   - CLIENT: Child context and assertion is stored in an assertion list
>     off the struct gss_cl_ctx.
>   - SERVER: Child context has it's own rsc cache entry, and the child
>     handle is stored in a list of children handles off the parent rsc entry.
>   - CLIENT and SERVER: child contexts are destroyed when parent context is
>     destroyed.
>   - CLIENT: child context associated with the client NFS request thread
>     is used for the NFS request.
>   - SERVER: Using the child context handle looks up the child rsc entry.
>     Using the parent context handle stored in the child rsc entry looks up
>     the parent rsc entry to use for MIC creation/verification, integrity
>     (krb5i)  and/or privacy (krb5p).
>   - SERVER: the label asserted by the NFS request child handle is imposed
>     upon the NFSD thread servicing the request just like the UID/GIDs in
>     the rpc credential.
> 
> Each time a call is made, the client makes a check in gss_match to see if
> the curren thread's SeLinux label has an associated GSS3 child context handle
> to use. If not, an RPCSEC_GSS_CREATE call is kicked off to establish the
> child context prior to the NFS request being sent. The NFS request then
> uses the child context that asserts the client NFS request thread label
> when sending the NFS request to the server.
> 
> Smoke Test;
> ----------
> Setup:
> - Ensure SeLinux is enabled on both client and server
> - Turn on NFSv4.2 in client and server
>   - SERVER: in /etc/sysconfig/nfs: RPCNFSDARGS="-V 4.2" (not needed in
>     Fedora 25 as NFSv4.2 is turned on)
>   - Fedora 25 SERVER export option "security_label" must be set:
>     /export *(sec=krb5:sys,rw,no_subtree_check,no_root_squash,security_label)
>   - CLIENT: mount -o v4.2 <server>:<export> <mntpoint>
>   - Note: LNFS sends the file label in the OPEN compound GETATTR.
>   - GSS3 sends the client thread label in the RPCSEC_GSS_CREATE call.
> - Useful SeLinux commands
>   - getenforce (setenforce) will let you know if Selinux is enforced
>   - ls -Z  (shows label and fetches it via GETATTR usin LNFS)
>   - ls -scontext  (shows just the label)
> 
> Note: Server should be Fedora 25 as the nfs-utils-2.1.1.2.rc1.fc25 and
> kernel 5.9.10-200.fc25 supports the new "security_label" export option
> which needs to be set on an exported file system that wants to support
> LNFS and GSS3 labels.
> 
> Test: (run with wireshark capture)
> Note: labels and conext values are from my setup. I restart gssd each test run.
> Note: my server /etc/export is "/export *(sec=krb5:sys,rw,no_root_squash)"
> 
> - # mount -o v4.2,sec=krb5 <server>:<export>  <mntpoint>
>   # ls <mntpoint>
>   - This will create a parent GSS context for kb5i (010000000000000 say 01),
>     and a GSS3 child context for krb5i parent with the client thread
>     label "system_u:system_r:kernel_t:s0" with handle 02.
>    - The child handle 02 is used for the EXCHANGE_ID, CREATE_SESSION, and
>      RECLAIM_COMPLETE calls.
>   - Then a parent GSS handle is created for krb5 (03) and a GSS3 child
>     context for the krb5 parent with hanel (04) for the client thread label
>     "unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023"
>    - The child handle 04 is used for the PUTROOT_FH, all the mount GETATTRs
>      and the LOOKUP of "/export"
>    - A new GSS3 child context (05) is created for krb5 parent with label
>      "system_u:system_r:kernel_t:s0"
>      The child handle 05 is used for LOOKUP, ACCESS, READDIR, etc.
> 
> 
> - # umount <mntpoint>
>    - This will create a new GSS3 child context (06) for krb5i parent with the
>      client thread label
>      "unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023"
>     - The child handle 06 is used for DESTROY_SESSION and DESTROY_CLIENTID.
>   - RPCSEC_GSS_DESTROY messages are sent for the two parent contexts 01 and 03.
>   - CHILD: the parent contexts and associated child contexts are destroyed.
>   - SERVER: the parent context and associated child contexts are destroyed.
> 
> -->Andy
> 
> 
> Andy Adamson (17):
>   SUNRPC handle unsupported RPCSEC_GSS security service
>   SUNRPC: RPCNULL call with payload for GSSv3
>   SELINUX export security_current_sid_to_context
>   SUNRPC GSSv3: base definitions
>   SUNRPC AUTH_GSS get RPCSEC_GSS version from gssd downcall
>   SUNRPC AUTH_GSS gss3 reply verifier
>   SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with no payload
>   SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload
>   SUNRPC AUTH_GSS store GSS3 assertions in parent gss_cl_ctx
>   SUNRPC AUTH_GSS store and use gss3 label assertion
>   SUNRPC AUTH_GSS free assertions
>   SUNRPC: AUTH_GSS add RPC_GSS_PROC_CREATE case for wrap and unwrap
>   SUNRPC SVCAUTH_GSS allow RPCSEC_GSS version 1 or 3
>   SUNRPC SVCAUTH_GSS gss3 reply verifier
>   SUNRPC SVCAUTH_GSS gss3 create label
>   SUNRPC SVCAUTH_GSS set gss3 label on nfsd thread
>   SUNRPC SVCAUTH_gss store gss3 child handles in parent rsc
> 
>  fs/nfsd/auth.c                     |  11 +-
>  include/linux/selinux.h            |   7 +
>  include/linux/sunrpc/auth_gss.h    |  76 ++++-
>  include/linux/sunrpc/clnt.h        |   3 +
>  include/linux/sunrpc/gss_api.h     |  11 +
>  include/linux/sunrpc/svcauth.h     |   1 +
>  include/linux/sunrpc/svcauth_gss.h |   1 +
>  net/sunrpc/auth_gss/auth_gss.c     | 564 ++++++++++++++++++++++++++++++++++++-
>  net/sunrpc/auth_gss/svcauth_gss.c  | 549 ++++++++++++++++++++++++++++++++++--
>  net/sunrpc/clnt.c                  |  20 ++
>  security/selinux/hooks.c           |  14 +
>  11 files changed, 1217 insertions(+), 40 deletions(-)
> 
> -- 
> 2.9.3

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 01/17] SUNRPC handle unsupported RPCSEC_GSS security service
  2017-02-24 22:19 ` [PATCH Version 5 01/17] SUNRPC handle unsupported RPCSEC_GSS security service andros
@ 2017-03-09 21:54   ` J. Bruce Fields
  0 siblings, 0 replies; 29+ messages in thread
From: J. Bruce Fields @ 2017-03-09 21:54 UTC (permalink / raw)
  To: andros; +Cc: trond.myklebust, schumaker.anna, linux-nfs

I don't think these cases are possible; ->gc_service is set from a
gss_auth->service, which is set to the return value from
gss_pseudoflavor_to_service, which shouldn't return arbitrary values.

Well, maybe there's no great harm in checking anyway, but I probably
wouldn't.

--b.

On Fri, Feb 24, 2017 at 05:19:37PM -0500, andros@netapp.com wrote:
> From: Andy Adamson <andros@netapp.com>
> 
> Signed-off-by: Andy Adamson <andros@netapp.com>
> ---
>  net/sunrpc/auth_gss/auth_gss.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
> index cdeb1d8..d8395ce 100644
> --- a/net/sunrpc/auth_gss/auth_gss.c
> +++ b/net/sunrpc/auth_gss/auth_gss.c
> @@ -1869,6 +1869,11 @@ gss_wrap_req(struct rpc_task *task,
>  	case RPC_GSS_SVC_PRIVACY:
>  		status = gss_wrap_req_priv(cred, ctx, encode, rqstp, p, obj);
>  		break;
> +	default:
> +		status = -EIO;
> +		pr_warn("RPC    Unsupported service level %d\n",
> +			gss_cred->gc_service);
> +		break;
>  	}
>  out:
>  	gss_put_ctx(ctx);
> @@ -1979,6 +1984,11 @@ gss_unwrap_resp(struct rpc_task *task,
>  		if (status)
>  			goto out;
>  		break;
> +	default:
> +		status = -EIO;
> +		pr_warn("RPC    Unsupported service level %d\n",
> +			gss_cred->gc_service);
> +		goto out;
>  	}
>  	/* take into account extra slack for integrity and privacy cases: */
>  	cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp)
> -- 
> 2.9.3

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 02/17] SUNRPC: RPCNULL call with payload for GSSv3
  2017-02-24 22:19 ` [PATCH Version 5 02/17] SUNRPC: RPCNULL call with payload for GSSv3 andros
@ 2017-03-09 22:11   ` J. Bruce Fields
  0 siblings, 0 replies; 29+ messages in thread
From: J. Bruce Fields @ 2017-03-09 22:11 UTC (permalink / raw)
  To: andros; +Cc: trond.myklebust, schumaker.anna, linux-nfs

I'm not sure why this is really necessary.  And it does it really have
anything to do with null calls?  It seems like it could be used for any
call?

--b.

On Fri, Feb 24, 2017 at 05:19:38PM -0500, andros@netapp.com wrote:
> From: Andy Adamson <andros@netapp.com>
> 
> RPCSEC_GSS_CREATE and RPCSEC_GSS_LIST are RPCNULL calls with a payload
> 
> Signed-off-by: Andy Adamson <andros@netapp.com>
> ---
>  include/linux/sunrpc/clnt.h |  3 +++
>  net/sunrpc/clnt.c           | 20 ++++++++++++++++++++
>  2 files changed, 23 insertions(+)
> 
> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
> index 333ad11..6d9e4ac 100644
> --- a/include/linux/sunrpc/clnt.h
> +++ b/include/linux/sunrpc/clnt.h
> @@ -175,6 +175,9 @@ int		rpc_call_sync(struct rpc_clnt *clnt,
>  			      const struct rpc_message *msg, int flags);
>  struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
>  			       int flags);
> +struct rpc_task *rpc_call_null_payload(struct rpc_clnt *clnt,
> +				struct rpc_cred *cred, int flags, void *argp,
> +				void *resp, struct rpc_procinfo *pinfo);
>  int		rpc_restart_call_prepare(struct rpc_task *);
>  int		rpc_restart_call(struct rpc_task *);
>  void		rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> index 1dc9f3b..c6f1d04 100644
> --- a/net/sunrpc/clnt.c
> +++ b/net/sunrpc/clnt.c
> @@ -2508,6 +2508,26 @@ static int rpcproc_decode_null(void *rqstp, struct xdr_stream *xdr, void *obj)
>  	return 0;
>  }
>  
> +struct rpc_task *
> +rpc_call_null_payload(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags,
> +		      void *argp, void *resp, struct rpc_procinfo *pinfo)
> +{
> +	struct rpc_message msg = {
> +		.rpc_proc = pinfo,
> +		.rpc_argp = argp,
> +		.rpc_resp = resp,
> +		.rpc_cred = cred,
> +	};
> +	struct rpc_task_setup task_setup_data = {
> +		.rpc_client = clnt,
> +		.rpc_message = &msg,
> +		.callback_ops = &rpc_default_ops,
> +		.flags = flags,
> +	};
> +	return rpc_run_task(&task_setup_data);
> +}
> +EXPORT_SYMBOL_GPL(rpc_call_null_payload);
> +
>  static struct rpc_procinfo rpcproc_null = {
>  	.p_encode = rpcproc_encode_null,
>  	.p_decode = rpcproc_decode_null,
> -- 
> 2.9.3

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set
  2017-03-09 21:47 ` [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set J. Bruce Fields
@ 2017-03-10 14:48   ` Andy Adamson
  2017-03-10 16:36     ` J. Bruce Fields
  0 siblings, 1 reply; 29+ messages in thread
From: Andy Adamson @ 2017-03-10 14:48 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: Trond Myklebust, Anna Schumaker, NFS list

On Thu, Mar 9, 2017 at 4:47 PM, J. Bruce Fields <bfields@fieldses.org> wrote:
> On Fri, Feb 24, 2017 at 05:19:36PM -0500, andros@netapp.com wrote:
>> From: Andy Adamson <andros@netapp.com>
>>
>> This patchset implements RFC 7861  RPCSEC_GSS Version 3 RPCSEC_GSS_CREATE
>> operation with rgs3_label payloads to provide  full mode Mandatory Access
>> Control (MAC) when run with NFSv4.2 Labeled NFS using SeLinux.
>
> Is GSSv3 also still planned to be used for COPY?  I lost track of that
> discussion.


Yes. I'm starting on that now.

-->Andy
>
> --b.
>
>>
>> A lot more testing is needed - and planned :)
>>
>> Client was built on Trond's testing branch, 4.10.0 kernel.
>> Server was  built on Bruce's nfsd-next branch, 4.10.0-rc7 kernel
>>
>> nfsd-next branch has these server required patches missing from Tronds
>> testing branch:
>>
>> 1) svcrpc: free contexts immediately on PROC_DESTROY
>> 2) nfsd: opt in to labeled nfs per export
>>
>> Version-5.
>> ---------
>> - responded to comments from Anna Schumaker
>> - refactored code to split generice RPCSEC_GSS_CREATE from label payload
>> - nfsd check for NFSEXP_SECURITY_LABEL export flag
>>
>> Requires on Client:
>> -------------------
>> gssd patches:  "RFC: GSSD changes for RPCSEC_GSS version 3"
>> libtirpc patches "RFC: Libtirpc changes for RPCSEC_GSS version 3"
>>
>> Implementation Features:
>> ------------------------
>>
>> GSSv3
>> - Negotiate GSS version - starts with GSSv3 then falls back to GSSv1 if
>>   GSSv3 is not supported.
>> - New GSSv3 reply verifier
>> - RPCSEC_GSS_CREATE operation generic code is separated from the payload code.
>> - rgss3_label assertion payload carries each client SeLinux thread label
>> - Supports one label assertion payload per RPCSEC_GSS_CREATE
>> - Kerberos pseudoflavor support (krb5, krb5i, krb5p)
>>
>> TODO:
>> ----
>> - Send all RPCSEC_GSS_CREATE calls with integrity or privacy
>> - Ensure SeLinux function exported in patch "SELINUX export
>>   security_current_sid_to_context" is OK with SeLinux experts.
>> - Perhaps add administrative ability on the client to indicate Full Mode
>>   MAC is desired and that NFSv4.2 Labeled NFS (LNFS) is used.
>>
>> Prototype description:
>> ---------------------
>> Parent GSS context: the normal GSS context
>>  - "Normal" GSSv3 context is the same as a "normal" GSSv1 context except
>>    for the new GSS Version and new reply verifier. For GSSv3 this "normal"
>>    context is called the parent context.
>>
>> Child GSS3 context: Is returned by a successful RPCSEC_GSS_CREATE operation
>>  - Child context is associated with the parent context on both the client
>>    and the server.
>>
>> If SeLinux is enabled and GSSv3 is in use, assume LNFS and GSSv3 full mode MAC.
>>
>> When Full Mode MAC is used:
>> - Each new GSS3 context (parent) kicks off an RPCSEC_GSS_CREATE with the
>> client thread's SeLinux label as a payload.
>>   - Upon success, the RPCSEC_GSS_CREATE call creates a GSSv3 child context
>>     handle that asserts the thread label, and uses the parent context for
>>     encrytion services.
>>   - CLIENT: Child context and assertion is stored in an assertion list
>>     off the struct gss_cl_ctx.
>>   - SERVER: Child context has it's own rsc cache entry, and the child
>>     handle is stored in a list of children handles off the parent rsc entry.
>>   - CLIENT and SERVER: child contexts are destroyed when parent context is
>>     destroyed.
>>   - CLIENT: child context associated with the client NFS request thread
>>     is used for the NFS request.
>>   - SERVER: Using the child context handle looks up the child rsc entry.
>>     Using the parent context handle stored in the child rsc entry looks up
>>     the parent rsc entry to use for MIC creation/verification, integrity
>>     (krb5i)  and/or privacy (krb5p).
>>   - SERVER: the label asserted by the NFS request child handle is imposed
>>     upon the NFSD thread servicing the request just like the UID/GIDs in
>>     the rpc credential.
>>
>> Each time a call is made, the client makes a check in gss_match to see if
>> the curren thread's SeLinux label has an associated GSS3 child context handle
>> to use. If not, an RPCSEC_GSS_CREATE call is kicked off to establish the
>> child context prior to the NFS request being sent. The NFS request then
>> uses the child context that asserts the client NFS request thread label
>> when sending the NFS request to the server.
>>
>> Smoke Test;
>> ----------
>> Setup:
>> - Ensure SeLinux is enabled on both client and server
>> - Turn on NFSv4.2 in client and server
>>   - SERVER: in /etc/sysconfig/nfs: RPCNFSDARGS="-V 4.2" (not needed in
>>     Fedora 25 as NFSv4.2 is turned on)
>>   - Fedora 25 SERVER export option "security_label" must be set:
>>     /export *(sec=krb5:sys,rw,no_subtree_check,no_root_squash,security_label)
>>   - CLIENT: mount -o v4.2 <server>:<export> <mntpoint>
>>   - Note: LNFS sends the file label in the OPEN compound GETATTR.
>>   - GSS3 sends the client thread label in the RPCSEC_GSS_CREATE call.
>> - Useful SeLinux commands
>>   - getenforce (setenforce) will let you know if Selinux is enforced
>>   - ls -Z  (shows label and fetches it via GETATTR usin LNFS)
>>   - ls -scontext  (shows just the label)
>>
>> Note: Server should be Fedora 25 as the nfs-utils-2.1.1.2.rc1.fc25 and
>> kernel 5.9.10-200.fc25 supports the new "security_label" export option
>> which needs to be set on an exported file system that wants to support
>> LNFS and GSS3 labels.
>>
>> Test: (run with wireshark capture)
>> Note: labels and conext values are from my setup. I restart gssd each test run.
>> Note: my server /etc/export is "/export *(sec=krb5:sys,rw,no_root_squash)"
>>
>> - # mount -o v4.2,sec=krb5 <server>:<export>  <mntpoint>
>>   # ls <mntpoint>
>>   - This will create a parent GSS context for kb5i (010000000000000 say 01),
>>     and a GSS3 child context for krb5i parent with the client thread
>>     label "system_u:system_r:kernel_t:s0" with handle 02.
>>    - The child handle 02 is used for the EXCHANGE_ID, CREATE_SESSION, and
>>      RECLAIM_COMPLETE calls.
>>   - Then a parent GSS handle is created for krb5 (03) and a GSS3 child
>>     context for the krb5 parent with hanel (04) for the client thread label
>>     "unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023"
>>    - The child handle 04 is used for the PUTROOT_FH, all the mount GETATTRs
>>      and the LOOKUP of "/export"
>>    - A new GSS3 child context (05) is created for krb5 parent with label
>>      "system_u:system_r:kernel_t:s0"
>>      The child handle 05 is used for LOOKUP, ACCESS, READDIR, etc.
>>
>>
>> - # umount <mntpoint>
>>    - This will create a new GSS3 child context (06) for krb5i parent with the
>>      client thread label
>>      "unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023"
>>     - The child handle 06 is used for DESTROY_SESSION and DESTROY_CLIENTID.
>>   - RPCSEC_GSS_DESTROY messages are sent for the two parent contexts 01 and 03.
>>   - CHILD: the parent contexts and associated child contexts are destroyed.
>>   - SERVER: the parent context and associated child contexts are destroyed.
>>
>> -->Andy
>>
>>
>> Andy Adamson (17):
>>   SUNRPC handle unsupported RPCSEC_GSS security service
>>   SUNRPC: RPCNULL call with payload for GSSv3
>>   SELINUX export security_current_sid_to_context
>>   SUNRPC GSSv3: base definitions
>>   SUNRPC AUTH_GSS get RPCSEC_GSS version from gssd downcall
>>   SUNRPC AUTH_GSS gss3 reply verifier
>>   SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with no payload
>>   SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload
>>   SUNRPC AUTH_GSS store GSS3 assertions in parent gss_cl_ctx
>>   SUNRPC AUTH_GSS store and use gss3 label assertion
>>   SUNRPC AUTH_GSS free assertions
>>   SUNRPC: AUTH_GSS add RPC_GSS_PROC_CREATE case for wrap and unwrap
>>   SUNRPC SVCAUTH_GSS allow RPCSEC_GSS version 1 or 3
>>   SUNRPC SVCAUTH_GSS gss3 reply verifier
>>   SUNRPC SVCAUTH_GSS gss3 create label
>>   SUNRPC SVCAUTH_GSS set gss3 label on nfsd thread
>>   SUNRPC SVCAUTH_gss store gss3 child handles in parent rsc
>>
>>  fs/nfsd/auth.c                     |  11 +-
>>  include/linux/selinux.h            |   7 +
>>  include/linux/sunrpc/auth_gss.h    |  76 ++++-
>>  include/linux/sunrpc/clnt.h        |   3 +
>>  include/linux/sunrpc/gss_api.h     |  11 +
>>  include/linux/sunrpc/svcauth.h     |   1 +
>>  include/linux/sunrpc/svcauth_gss.h |   1 +
>>  net/sunrpc/auth_gss/auth_gss.c     | 564 ++++++++++++++++++++++++++++++++++++-
>>  net/sunrpc/auth_gss/svcauth_gss.c  | 549 ++++++++++++++++++++++++++++++++++--
>>  net/sunrpc/clnt.c                  |  20 ++
>>  security/selinux/hooks.c           |  14 +
>>  11 files changed, 1217 insertions(+), 40 deletions(-)
>>
>> --
>> 2.9.3
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 05/17] SUNRPC AUTH_GSS get RPCSEC_GSS version from gssd downcall
  2017-02-24 22:19 ` [PATCH Version 5 05/17] SUNRPC AUTH_GSS get RPCSEC_GSS version from gssd downcall andros
@ 2017-03-10 16:18   ` J. Bruce Fields
  0 siblings, 0 replies; 29+ messages in thread
From: J. Bruce Fields @ 2017-03-10 16:18 UTC (permalink / raw)
  To: andros; +Cc: trond.myklebust, schumaker.anna, linux-nfs

How are you maintaining backwards compatibility with older gssd?

--b.

On Fri, Feb 24, 2017 at 05:19:41PM -0500, andros@netapp.com wrote:
> From: Andy Adamson <andros@netapp.com>
> 
> Signed-off-by: Andy Adamson <andros@netapp.com>
> ---
>  include/linux/sunrpc/auth_gss.h |  1 +
>  net/sunrpc/auth_gss/auth_gss.c  | 16 ++++++++++++----
>  2 files changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
> index 8939db4..4ab63a9 100644
> --- a/include/linux/sunrpc/auth_gss.h
> +++ b/include/linux/sunrpc/auth_gss.h
> @@ -71,6 +71,7 @@ struct rpc_gss_init_res {
>  
>  struct gss_cl_ctx {
>  	atomic_t		count;
> +	u32			gc_v;
>  	enum rpc_gss_proc	gc_proc;
>  	u32			gc_seq;
>  	spinlock_t		gc_seq_lock;
> diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
> index d8395ce..216a78e 100644
> --- a/net/sunrpc/auth_gss/auth_gss.c
> +++ b/net/sunrpc/auth_gss/auth_gss.c
> @@ -213,6 +213,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
>  	unsigned int seclen;
>  	unsigned int timeout;
>  	unsigned long now = jiffies;
> +	unsigned int gss_v;
>  	u32 window_size;
>  	int ret;
>  
> @@ -226,6 +227,13 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
>  	if (timeout == 0)
>  		timeout = GSSD_MIN_TIMEOUT;
>  	ctx->gc_expiry = now + ((unsigned long)timeout * HZ);
> +
> +	/* RPCSEC_GSS version used to obtain context */
> +	p = simple_get_bytes(p, end, &gss_v, sizeof(gss_v));
> +	if (IS_ERR(p))
> +		goto err;
> +	ctx->gc_v = gss_v;
> +
>  	/* Sequence number window. Determines the maximum number of
>  	 * simultaneous requests
>  	 */
> @@ -1511,10 +1519,10 @@ gss_marshal(struct rpc_task *task, __be32 *p)
>  	req->rq_seqno = ctx->gc_seq++;
>  	spin_unlock(&ctx->gc_seq_lock);
>  
> -	*p++ = htonl((u32) RPC_GSS_VERSION);
> -	*p++ = htonl((u32) ctx->gc_proc);
> -	*p++ = htonl((u32) req->rq_seqno);
> -	*p++ = htonl((u32) gss_cred->gc_service);
> +	*p++ = htonl((u32)ctx->gc_v);
> +	*p++ = htonl((u32)ctx->gc_proc);
> +	*p++ = htonl((u32)req->rq_seqno);
> +	*p++ = htonl((u32)gss_cred->gc_service);
>  	p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);
>  	*cred_len = htonl((p - (cred_len + 1)) << 2);
>  
> -- 
> 2.9.3

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set
  2017-03-10 14:48   ` Andy Adamson
@ 2017-03-10 16:36     ` J. Bruce Fields
  0 siblings, 0 replies; 29+ messages in thread
From: J. Bruce Fields @ 2017-03-10 16:36 UTC (permalink / raw)
  To: Andy Adamson; +Cc: Trond Myklebust, Anna Schumaker, NFS list

On Fri, Mar 10, 2017 at 09:48:23AM -0500, Andy Adamson wrote:
> On Thu, Mar 9, 2017 at 4:47 PM, J. Bruce Fields <bfields@fieldses.org> wrote:
> > On Fri, Feb 24, 2017 at 05:19:36PM -0500, andros@netapp.com wrote:
> >> From: Andy Adamson <andros@netapp.com>
> >>
> >> This patchset implements RFC 7861  RPCSEC_GSS Version 3 RPCSEC_GSS_CREATE
> >> operation with rgs3_label payloads to provide  full mode Mandatory Access
> >> Control (MAC) when run with NFSv4.2 Labeled NFS using SeLinux.
> >
> > Is GSSv3 also still planned to be used for COPY?  I lost track of that
> > discussion.
> 
> 
> Yes. I'm starting on that now.

Great, thanks.

Also:  do you know if there are any other implementations coming?  And
is wireshark support on the way?

--b.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 06/17] SUNRPC AUTH_GSS gss3 reply verifier
  2017-02-24 22:19 ` [PATCH Version 5 06/17] SUNRPC AUTH_GSS gss3 reply verifier andros
@ 2017-03-10 16:51   ` J. Bruce Fields
  0 siblings, 0 replies; 29+ messages in thread
From: J. Bruce Fields @ 2017-03-10 16:51 UTC (permalink / raw)
  To: andros; +Cc: trond.myklebust, schumaker.anna, linux-nfs

On Fri, Feb 24, 2017 at 05:19:42PM -0500, andros@netapp.com wrote:
> From: Andy Adamson <andros@netapp.com>
> 
> The new GSS Version 3 reply  verifier is taken over the same data as
> the call verifier, caveat REPLY direction
> 
> Verifier Data
> 
>    xid          tk_rqstp->rq_xid
>    direction    REPLY (always a 1) RPC_REPLY
>    rpcvers      RPC_VERSION
>    prog         clnt->cl_prog
>    vers         clnt->cl_vers
>    proc         tk_msg.rpc_proc->p_proc
>    credential
>          flavor       RPC_AUTH_GSS
>          length       cred_len is in gss_marshal (new gv_crlen)
>          gss version  ctx->gc_v
>          gss proc     ctx->gv_proc
>          gss seq      tk_rqstp->rq_seqno
>          gss svc      gss_cred->gc_service
>          gss ctx len  ctx->gc_wire_ctx
>          gss ctx data ctx->gc_wire_ctx
> 
> Signed-off-by: Andy Adamson <andros@netapp.com>
> ---
>  net/sunrpc/auth_gss/auth_gss.c | 59 ++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 57 insertions(+), 2 deletions(-)
> 
> diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
> index 216a78e..499cf99 100644
> --- a/net/sunrpc/auth_gss/auth_gss.c
> +++ b/net/sunrpc/auth_gss/auth_gss.c
> @@ -1624,6 +1624,53 @@ gss_refresh_null(struct rpc_task *task)
>  	return 0;
>  }
>  
> +/**
> + * gss3_reply_verifier: The new gssv3 verifier uses same data as call
> + * caveat REPLY direction - see rpc_encode_header
> + */
> +static  void *
> +gss3_reply_verifier(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
> +		    struct rpc_task *task, __be32 *seq, struct kvec *iov)
> +{
> +	struct gss_cred *g_cred = container_of(cred, struct gss_cred, gc_base);
> +	void	*gss3_buf = NULL;
> +	__be32 *crlen, *ptr = NULL;
> +	int len;
> +
> +	/* freed in gss_validate */

Minor nit, but isn't this:

> +	len = (13 * 4) + ctx->gc_wire_ctx.len;
> +	gss3_buf = kmalloc(len, GFP_NOFS);
> +	if (!gss3_buf) {
> +		gss3_buf = ERR_PTR(-EIO);
> +		goto out;
> +	}
> +	ptr = (__be32 *)gss3_buf;
> +
> +	*ptr++ = htonl(task->tk_rqstp->rq_xid);
> +	*ptr++ = htonl(RPC_REPLY);
> +	*ptr++ = htonl(RPC_VERSION);
> +	*ptr++ = htonl(task->tk_client->cl_prog);
> +	*ptr++ = htonl(task->tk_client->cl_vers);
> +	*ptr++ = htonl(task->tk_msg.rpc_proc->p_proc);
> +	*ptr++ = htonl(RPC_AUTH_GSS);
> +
> +	/* credential */
> +	crlen = ptr++;
> +	*ptr++ = htonl(ctx->gc_v);
> +	*ptr++ = htonl(ctx->gc_proc);
> +	*ptr++ = *seq;
> +	*ptr++ = htonl(g_cred->gc_service);
> +	ptr = xdr_encode_netobj(ptr, &ctx->gc_wire_ctx);
> +
> +	/* backfill cred length */
> +	*crlen = htonl((ptr - (crlen + 1)) << 2);
> +
> +	iov->iov_base = gss3_buf;

the same as this:

> +	iov->iov_len = (ptr - (__be32 *)gss3_buf) << 2;

?

And I suppose you could calculate crlen gc_wire_ctx.len without the need
for the pointer arithmetic too, it might work out a little simpler.

--b.

> +out:
> +	return gss3_buf;
> +}
> +
>  static __be32 *
>  gss_validate(struct rpc_task *task, __be32 *p)
>  {
> @@ -1633,6 +1680,7 @@ gss_validate(struct rpc_task *task, __be32 *p)
>  	struct kvec	iov;
>  	struct xdr_buf	verf_buf;
>  	struct xdr_netobj mic;
> +	void	*g3_buf = NULL;
>  	u32		flav,len;
>  	u32		maj_stat;
>  	__be32		*ret = ERR_PTR(-EIO);
> @@ -1648,14 +1696,21 @@ gss_validate(struct rpc_task *task, __be32 *p)
>  	if (!seq)
>  		goto out_bad;
>  	*seq = htonl(task->tk_rqstp->rq_seqno);
> -	iov.iov_base = seq;
> -	iov.iov_len = 4;
> +	if (ctx->gc_v == RPC_GSS_VERSION) {
> +		iov.iov_base = seq;
> +		iov.iov_len = 4;
> +	} else if (ctx->gc_v == RPC_GSS3_VERSION) {
> +		g3_buf = gss3_reply_verifier(cred, ctx, task, seq, &iov);
> +		if (IS_ERR(g3_buf))
> +			goto out_bad;
> +	}
>  	xdr_buf_from_iov(&iov, &verf_buf);
>  	mic.data = (u8 *)p;
>  	mic.len = len;
>  
>  	ret = ERR_PTR(-EACCES);
>  	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
> +	kfree(g3_buf);
>  	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
>  		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
>  	if (maj_stat) {
> -- 
> 2.9.3

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 07/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with no payload
  2017-02-24 22:19 ` [PATCH Version 5 07/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with no payload andros
@ 2017-03-10 17:25   ` J. Bruce Fields
  0 siblings, 0 replies; 29+ messages in thread
From: J. Bruce Fields @ 2017-03-10 17:25 UTC (permalink / raw)
  To: andros; +Cc: trond.myklebust, schumaker.anna, linux-nfs

On Fri, Feb 24, 2017 at 05:19:43PM -0500, andros@netapp.com wrote:
> From: Andy Adamson <andros@netapp.com>
> 
> Signed-off-by: Andy Adamson <andros@netapp.com>
> ---
>  include/linux/sunrpc/auth_gss.h |  54 ++++++++++++
>  net/sunrpc/auth_gss/auth_gss.c  | 182 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 236 insertions(+)
> 
> diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
> index 4ab63a9..b2a5a61 100644
> --- a/include/linux/sunrpc/auth_gss.h
> +++ b/include/linux/sunrpc/auth_gss.h
> @@ -93,6 +93,60 @@ struct gss_cred {
>  	unsigned long		gc_upcall_timestamp;
>  };
>  
> +/** GSS3 */
> +enum gss3_type {
> +	GSS3_LABEL = 0,
> +	GSS3_PRIVS = 1,
> +};
> +
> +struct gss3_chan_binding {
> +	u32	cb_len;
> +	void	*cb_binding;
> +};
> +
> +struct gss3_mp_auth {
> +	u32	mp_handle_len;
> +	void	*mp_handle;
> +	u32	*mp_mic_len;
> +	void	*mp_mic;	/* header mic */
> +};
> +
> +struct gss3_label {
> +	u32			la_lfs;
> +	u32			la_pi;
> +	struct xdr_netobj	la_label;
> +};
> +
> +struct gss3_privs {
> +	char	*pr_name;
> +	u32	pr_num;
> +	void	*pr_data;
> +};
> +
> +struct gss3_assertion_u {
> +	u32	au_type;
> +	union {
> +		struct gss3_label	au_label;
> +		struct gss3_privs	au_privs;
> +	} u;
> +};
> +
> +struct gss3_create_args {
> +	struct gss3_mp_auth		*ca_mp_auth;
> +	struct gss3_chan_binding	*ca_chan_bind;
> +	u32			ca_num;
> +	struct gss3_assertion_u	*ca_assertions;
> +};
> +
> +struct gss3_create_res {
> +	u32		cr_hlen;
> +	void		*cr_handle;
> +	struct gss3_mp_auth		*cr_mp_auth;
> +	struct gss3_chan_binding	*cr_chan_bind;
> +	u32			cr_num;
> +	struct gss3_assertion_u	*cr_assertions;
> +};
> +
>  #endif /* __KERNEL__ */
>  #endif /* _LINUX_SUNRPC_AUTH_GSS_H */
>  
> diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
> index 499cf99..6ffb16d 100644
> --- a/net/sunrpc/auth_gss/auth_gss.c
> +++ b/net/sunrpc/auth_gss/auth_gss.c
> @@ -1591,6 +1591,188 @@ static int gss_cred_is_negative_entry(struct rpc_cred *cred)
>  	return 0;
>  }
>  
> +/**
> + * GSS3_createargs_maxsz and GSS3_createres_maxsz
> + * include no rgss3_assertion_u payload.
> + */
> +#define GSS3_createargs_maxsz  (1 /* empty ca_mp_auth */ + \
> +				1 /* empty ca_chan_bind */ + \
> +				1 /* ca_num */ + \
> +				1 /* au_type */)
> +#define GSS3_createres_maxsz   (1 /* cr_hlen */ + \
> +				XDR_QUADLEN(1024) /* cr_handle*/ + \
> +				GSS3_createargs_maxsz)
> +
> +static void
> +gss3_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr,
> +		const struct gss3_create_args *g3ca)
> +{
> +	u32 type;
> +	__be32 *p;
> +
> +	p = xdr_reserve_space(xdr, GSS3_createargs_maxsz << 2);
> +	*p++ = cpu_to_be32(0); /* NULL ca_mp_auth */
> +	*p++ = cpu_to_be32(0); /* NULL ca_chan_bind */
> +	*p++ = cpu_to_be32(g3ca->ca_num);
> +	type = cpu_to_be32(g3ca->ca_assertions->au_type);
> +	*p++ = type;
> +	switch (type) {
> +	case GSS3_LABEL:
> +	case GSS3_PRIVS:
> +	default:
> +		/* drop through to return */
> +		pr_warn("RPC    Unsupported gss3 create assertion %d\n", type);
> +	}
> +}
> +
> +static int
> +gss3_dec_create(struct rpc_rqst *req, struct xdr_stream *xdr,
> +		struct gss3_create_res *g3cr)
> +{
> +	u32 dummy, type;
> +	__be32 *p;
> +
> +	p = xdr_inline_decode(xdr, 4);
> +	if (unlikely(!p))
> +		goto out_overflow;
> +	g3cr->cr_hlen = be32_to_cpup(p++);
> +
> +	p = xdr_inline_decode(xdr, g3cr->cr_hlen + 16);
> +	if (unlikely(!p))
> +		goto out_overflow;
> +
> +	g3cr->cr_handle = kmemdup(p, g3cr->cr_hlen, GFP_KERNEL);
> +	if (!g3cr->cr_handle)
> +		goto out_err;
> +
> +	p += XDR_QUADLEN(g3cr->cr_hlen);
> +
> +	/* cr_mp_auth: not supported */
> +	dummy = be32_to_cpup(p++);
> +	if (dummy != 0) {
> +		pr_warn("RPC    gss3 create cr_mp_auth not supported\n");
> +		goto out_free_handle;
> +	}
> +
> +	/* cr_chan_bind: not supported */
> +	dummy = be32_to_cpup(p++);
> +	if (dummy != 0) {
> +		pr_warn("RPC    gss3 create cr_chan_bind not supported\n");
> +		goto out_free_handle;
> +	}
> +
> +	/* XXX Support one assertion */
> +	g3cr->cr_num = be32_to_cpup(p++);
> +	if (g3cr->cr_num != 1) {
> +		pr_warn("RPC    gss3 multiple assertions %d unspported\n",
> +			g3cr->cr_num);
> +		goto out_free_handle;
> +	}
> +
> +	/* au_type */
> +	type = be32_to_cpup(p++);
> +	switch (type) {
> +	case GSS3_LABEL:
> +	case GSS3_PRIVS:
> +	default:
> +		pr_warn("RPC    Unsupported gss3 create assertion %d\n", type);
> +		goto out_free_handle;
> +	}

It's a little confusing to have a decode routine that always fails;
maybe just squash this patch together with the following one?

--b.

> +	return 0;
> +
> +out_free_handle:
> +	kfree(g3cr->cr_handle);
> +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_err;
> +}
> +
> +#define RPC_PROC_NULL 0
> +
> +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_statidx	= RPC_GSS_PROC_CREATE,
> +		.p_timer	= 0,
> +		.p_name		= "GSS_PROC_CREATE",
> +	},
> +};
> +
> +/**
> + * RPC_GSS_PROC_CREATE operation
> + *
> + * Notes:
> + *    1) Spec says we MUST use integrity or privacy security service.
> + *    First pass; use rpc_gss_svc_none.
> + *    2) asserts are allocated by caller, and freed here.
> + */
> +static int
> +gss3_proc_create(struct rpc_cred *cred, struct gss3_assertion_u *asserts,
> +		 int numasserts)
> +{
> +	struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth,
> +						 rpc_auth);
> +	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
> +	struct rpc_task *task;
> +	struct gss3_create_res cres = {
> +		.cr_mp_auth = 0,
> +	};
> +	struct gss3_create_args *cargs = NULL;
> +	int ret = -EINVAL;
> +
> +	if (!ctx || !asserts)
> +		goto out;
> +	/**
> +	 * Take a reference to ensure the cred sticks around as we create
> +	 * a child context
> +	 * XXX does grabbing a reference to the context (gss_cred_get_ctx)
> +	 * also keep the cred from being removed?
> +	 * XXX do we need to keep this cred reference until the child context
> +	 * handle and associated assertion is removed?
> +	 */
> +	get_rpccred(cred);
> +
> +	ret = -ENOMEM;
> +	cargs = kzalloc(sizeof(*cargs), GFP_NOFS);
> +	if (!cargs)
> +		goto out_err;
> +
> +	cargs->ca_assertions = asserts;
> +	cargs->ca_num = numasserts;
> +	ctx->gc_proc = RPC_GSS_PROC_CREATE;
> +	cred->cr_ops = &gss_credops;
> +
> +	/* Want a sync rpc call */
> +	task = rpc_call_null_payload(gss_auth->client, cred, 0, cargs, &cres,
> +				    &gss3_label_assertion[RPC_GSS_PROC_CREATE]);
> +	if (IS_ERR(task)) {
> +		ret = PTR_ERR(task);
> +		goto out_free_assert;
> +	}
> +	if (task->tk_status != 0) {
> +		ret = task->tk_status;
> +		goto out_free_assert;
> +	}
> +	rpc_put_task(task);
> +
> +out_free_assert:
> +	kfree(cargs->ca_assertions);
> +	kfree(cargs);
> +out_err:
> +	ctx->gc_proc = RPC_GSS_PROC_DATA;
> +	gss_put_ctx(ctx);
> +	put_rpccred(cred);
> +out:
> +	return ret;
> +}
> +
>  /*
>  * Refresh credentials. XXX - finish
>  */
> -- 
> 2.9.3

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 08/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload
  2017-02-24 22:19 ` [PATCH Version 5 08/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload andros
  2017-02-27 21:47   ` Anna Schumaker
@ 2017-03-10 17:31   ` J. Bruce Fields
  2017-03-10 17:33     ` J. Bruce Fields
  1 sibling, 1 reply; 29+ messages in thread
From: J. Bruce Fields @ 2017-03-10 17:31 UTC (permalink / raw)
  To: andros; +Cc: trond.myklebust, schumaker.anna, linux-nfs

On Fri, Feb 24, 2017 at 05:19:44PM -0500, andros@netapp.com wrote:
> From: Andy Adamson <andros@netapp.com>
> 
> Signed-off-by: Andy Adamson <andros@netapp.com>
> ---
>  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.

Eventually I guess we may want support for GSSv3-enabled copy without
full MAC, so we'll want some way to configure this.

Also, do I understand right that currently it's gssd that decides
whether to enable GSSv3, by passing down the new version number?  How
will the user choose whether to enable GSSv3 or not?

Should that be a mount option?

The mount option could then cause some "use_gss3" flag to be added in
rpc_pipefs, in an info file or whatever.  I think that'd also provide
backwards compatibility (if you're not already handling that some other
way), since gssd could use the presence of that flag to decide whether
the kernel was new enough to support the new downcall.

--b.

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH Version 5 08/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload
  2017-03-10 17:31   ` J. Bruce Fields
@ 2017-03-10 17:33     ` J. Bruce Fields
  0 siblings, 0 replies; 29+ messages in thread
From: J. Bruce Fields @ 2017-03-10 17:33 UTC (permalink / raw)
  To: andros; +Cc: trond.myklebust, schumaker.anna, linux-nfs

On Fri, Mar 10, 2017 at 12:31:07PM -0500, J. Bruce Fields wrote:
> On Fri, Feb 24, 2017 at 05:19:44PM -0500, andros@netapp.com wrote:
> > From: Andy Adamson <andros@netapp.com>
> > 
> > Signed-off-by: Andy Adamson <andros@netapp.com>
> > ---
> >  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.
> 
> Eventually I guess we may want support for GSSv3-enabled copy without
> full MAC, so we'll want some way to configure this.
> 
> Also, do I understand right that currently it's gssd that decides
> whether to enable GSSv3, by passing down the new version number?  How
> will the user choose whether to enable GSSv3 or not?
> 
> Should that be a mount option?
> 
> The mount option could then cause some "use_gss3" flag to be added in
> rpc_pipefs, in an info file or whatever.  I think that'd also provide
> backwards compatibility (if you're not already handling that some other
> way), since gssd could use the presence of that flag to decide whether
> the kernel was new enough to support the new downcall.

By the way, I didn't notice on a quick skim of the rest of the patches:
what happens if the server doesn't support GSSv3?  Does gssd negotiate
down to GSSv2 automatically?

How do you configure this on the server?  (It probably needs to be
possible to turn of mac labeling on the server.)

--b.

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2017-03-10 17:33 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-24 22:19 [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set andros
2017-02-24 22:19 ` [PATCH Version 5 01/17] SUNRPC handle unsupported RPCSEC_GSS security service andros
2017-03-09 21:54   ` J. Bruce Fields
2017-02-24 22:19 ` [PATCH Version 5 02/17] SUNRPC: RPCNULL call with payload for GSSv3 andros
2017-03-09 22:11   ` J. Bruce Fields
2017-02-24 22:19 ` [PATCH Version 5 03/17] SELINUX export security_current_sid_to_context andros
2017-02-24 22:19 ` [PATCH Version 5 04/17] SUNRPC GSSv3: base definitions andros
2017-02-24 22:19 ` [PATCH Version 5 05/17] SUNRPC AUTH_GSS get RPCSEC_GSS version from gssd downcall andros
2017-03-10 16:18   ` J. Bruce Fields
2017-02-24 22:19 ` [PATCH Version 5 06/17] SUNRPC AUTH_GSS gss3 reply verifier andros
2017-03-10 16:51   ` J. Bruce Fields
2017-02-24 22:19 ` [PATCH Version 5 07/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with no payload andros
2017-03-10 17:25   ` J. Bruce Fields
2017-02-24 22:19 ` [PATCH Version 5 08/17] SUNRPC AUTH_GSS RPCSEC_GSS_CREATE with label payload andros
2017-02-27 21:47   ` Anna Schumaker
2017-03-10 17:31   ` J. Bruce Fields
2017-03-10 17:33     ` J. Bruce Fields
2017-02-24 22:19 ` [PATCH Version 5 09/17] SUNRPC AUTH_GSS store GSS3 assertions in parent gss_cl_ctx andros
2017-02-24 22:19 ` [PATCH Version 5 10/17] SUNRPC AUTH_GSS store and use gss3 label assertion andros
2017-02-24 22:19 ` [PATCH Version 5 11/17] SUNRPC AUTH_GSS free assertions andros
2017-02-24 22:19 ` [PATCH Version 5 12/17] SUNRPC: AUTH_GSS add RPC_GSS_PROC_CREATE case for wrap and unwrap andros
2017-02-24 22:19 ` [PATCH Version 5 13/17] SUNRPC SVCAUTH_GSS allow RPCSEC_GSS version 1 or 3 andros
2017-02-24 22:19 ` [PATCH Version 5 14/17] SUNRPC SVCAUTH_GSS gss3 reply verifier andros
2017-02-24 22:19 ` [PATCH Version 5 15/17] SUNRPC SVCAUTH_GSS gss3 create label andros
2017-02-24 22:19 ` [PATCH Version 5 16/17] SUNRPC SVCAUTH_GSS set gss3 label on nfsd thread andros
2017-02-24 22:19 ` [PATCH Version 5 17/17] SUNRPC SVCAUTH_gss store gss3 child handles in parent rsc andros
2017-03-09 21:47 ` [PATCH Version 5 00/17] RPCSEC_GSS3 full mode label kernel patch set J. Bruce Fields
2017-03-10 14:48   ` Andy Adamson
2017-03-10 16:36     ` J. Bruce Fields

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.