From patchwork Fri Jul 28 20:21:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Adamson X-Patchwork-Id: 9869385 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 77A8D60382 for ; Fri, 28 Jul 2017 20:22:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6DC3D28923 for ; Fri, 28 Jul 2017 20:22:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 60D0528926; Fri, 28 Jul 2017 20:22:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BC3A72891A for ; Fri, 28 Jul 2017 20:22:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752505AbdG1UWJ (ORCPT ); Fri, 28 Jul 2017 16:22:09 -0400 Received: from mx144.netapp.com ([216.240.21.25]:62496 "EHLO mx144.netapp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752633AbdG1UWJ (ORCPT ); Fri, 28 Jul 2017 16:22:09 -0400 X-IronPort-AV: E=Sophos;i="5.40,427,1496127600"; d="scan'208";a="207894572" Received: from vmwexchts03-prd.hq.netapp.com ([10.122.105.31]) by mx144-out.netapp.com with ESMTP; 28 Jul 2017 12:58:29 -0700 Received: from smtp1.corp.netapp.com (10.57.156.124) by VMWEXCHTS03-PRD.hq.netapp.com (10.122.105.31) with Microsoft SMTP Server id 15.0.1210.3; Fri, 28 Jul 2017 13:22:07 -0700 Received: from localhost.localdomain.localdomain (dros-16.vpn.netapp.com [10.55.79.21]) by smtp1.corp.netapp.com (8.13.1/8.13.1/NTAP-1.6) with ESMTP id v6SKM1lf007987; Fri, 28 Jul 2017 13:22:07 -0700 (PDT) From: To: CC: , , , , Andy Adamson Subject: [PATCH Version 6 06/12] SUNRPC AUTH_GSS store and use gss3 label assertion Date: Fri, 28 Jul 2017 16:21:52 -0400 Message-ID: <1501273318-14200-7-git-send-email-andros@netapp.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1501273318-14200-1-git-send-email-andros@netapp.com> References: <1501273318-14200-1-git-send-email-andros@netapp.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Andy Adamson 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. Choose to use a child or parent context handle in gss_marshal and in gss3_reply_verifier. Add the RPC_GSS_PROC_CREATE case for wrap and unwrap Signed-off-by: Andy Adamson --- include/linux/sunrpc/svcauth_gss.h | 1 + net/sunrpc/auth_gss/auth_gss.c | 74 +++++++++++++++++++++++++++++++++++--- net/sunrpc/auth_gss/svcauth_gss.c | 2 +- 3 files changed, 72 insertions(+), 5 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 @@ 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 46c0068..1014521 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -57,6 +57,9 @@ #include "../netns.h" static int gss3_create_label(struct rpc_cred *cred); +static struct gss3_assert *gss3_use_child_handle(struct rpc_cred *cred, + struct gss_cl_ctx *ctx); +static struct gss3_assert *gss3_match_label(struct gss3_assert_list *in); static const struct rpc_authops authgss_ops; @@ -1480,6 +1483,9 @@ static void gss_pipe_free(struct gss_pipe *p) { struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); struct gss_cl_ctx *ctx; + struct gss3_assert *g3a; + rpc_authflavor_t flavor = rc->cr_auth->au_flavor; + bool use_labels = false; int ret; if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) @@ -1491,6 +1497,7 @@ static void gss_pipe_free(struct gss_pipe *p) rcu_read_unlock(); return 0; } + use_labels = gss3_label_assertion_is_enabled(ctx->gc_v, flavor); rcu_read_unlock(); if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags)) return 0; @@ -1517,6 +1524,13 @@ static void gss_pipe_free(struct gss_pipe *p) /* tell NFS layer that key will expire soon */ set_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); } + if (ret && use_labels) { + ctx = gss_cred_get_ctx(rc); + g3a = gss3_match_label(&ctx->gc_alist); + if (!g3a) + gss3_create_label(rc); + gss_put_ctx(ctx); + } return ret; } @@ -1537,6 +1551,7 @@ static void gss_pipe_free(struct gss_pipe *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__); @@ -1551,7 +1566,11 @@ static void gss_pipe_free(struct gss_pipe *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(cred, 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 @@ -1653,6 +1672,46 @@ static void gss3_free_label(struct gss3_label *gl) kfree(gl->la_label.data); } +static struct gss3_assert * +gss3_match_label(struct gss3_assert_list *in) +{ + struct gss3_assert *found; + struct xdr_netobj label; + int ret; + + /* 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 rpc_cred *cred, struct gss_cl_ctx *ctx) +{ + struct gss3_assert *g3a = NULL; + rpc_authflavor_t flavor = cred->cr_auth->au_flavor; + + if (gss3_label_assertion_is_enabled(ctx->gc_v, flavor) && + 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. @@ -2036,6 +2095,7 @@ struct rpc_procinfo gss3_ops[] = { { 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; @@ -2062,7 +2122,11 @@ struct rpc_procinfo gss3_ops[] = { *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(cred, 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); @@ -2315,7 +2379,8 @@ static void gss_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, 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. */ @@ -2429,7 +2494,8 @@ static void gss_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, 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: 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); }