From patchwork Thu Apr 4 08:38:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Khalid Elmously X-Patchwork-Id: 1076977 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44Zbvq2lWCz9sRX; Thu, 4 Apr 2019 19:39:00 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1hBxtb-0001dt-Nh; Thu, 04 Apr 2019 08:38:51 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1hBxta-0001dW-9B for kernel-team@lists.ubuntu.com; Thu, 04 Apr 2019 08:38:50 +0000 Received: from mail-qt1-f199.google.com ([209.85.160.199]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1hBxtZ-00042r-S2 for kernel-team@lists.ubuntu.com; Thu, 04 Apr 2019 08:38:49 +0000 Received: by mail-qt1-f199.google.com with SMTP id z34so1617585qtz.14 for ; Thu, 04 Apr 2019 01:38:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=HN/tZzFDsuiaD1YdyS/TB/uw5TAXA81G0hSUYBzLpRo=; b=Xhr4bMIon1Pf32nRbsoX5KkTcr2Ex0elkvXlteeFXHYXmwGdzNUn/EZKT5fkZyRxXB JXvJ6uTs0cpAqSPmMj7yevwCo10R1iZMjmmlhWUXz/sJA+G4NtarMc+UF2zf/q6N2Ly0 KjsnfJD/onmPVn3V5xcXkMdSDskVJrmrLktJRRAhTT/xQ7LoLuKdZnhh8OayY/2WuRo+ kCgipjun7SpkLXsYsip74Jo1AUeE2l8NOOiU3opdFpNxoewTPv1YpduKUDHiM2rRSnBA /594/hrz5nX1cShEbCfADszGSTNaL3JeRG3gSuRZjMwFv+MLoCDD2EHQ5zWDriHG61YE d0Ng== X-Gm-Message-State: APjAAAXdWAZczUb0gYG3voY01PSS/6cC5WYg90DU7VhYWr8/bbD9LyZi aLL/JSTPuulqPcQ1ZeoCPr88XqpGrB6Ymbu6k6gEQHuBfA6znLx77SxZsdBYUuJi2IQo5lwefaN t+zoRge4MUZbtnklloQXV8BN4qhXM8l2RiZBWwFHEUg== X-Received: by 2002:a37:4957:: with SMTP id w84mr3927246qka.147.1554367128886; Thu, 04 Apr 2019 01:38:48 -0700 (PDT) X-Google-Smtp-Source: APXvYqwzmkf0z0dtlg1V0dpXEoqIDAB1rpY2GxFTJB13f9qzxA8VSp34iDa9w5PYaFH4sNhdwVayMQ== X-Received: by 2002:a37:4957:: with SMTP id w84mr3927236qka.147.1554367128708; Thu, 04 Apr 2019 01:38:48 -0700 (PDT) Received: from localhost.localdomain (ool-45710a9c.dyn.optonline.net. [69.113.10.156]) by smtp.gmail.com with ESMTPSA id w9sm9111481qkf.94.2019.04.04.01.38.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 04 Apr 2019 01:38:48 -0700 (PDT) From: Khalid Elmously To: kernel-team@lists.ubuntu.com Subject: [SRU][C][PATCH v2 1/2] sunrpc: use SVC_NET() in svcauth_gss_* functions Date: Thu, 4 Apr 2019 04:38:38 -0400 Message-Id: <20190404083839.14841-2-khalid.elmously@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190404083839.14841-1-khalid.elmously@canonical.com> References: <20190404083839.14841-1-khalid.elmously@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Vasily Averin Signed-off-by: Vasily Averin Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields (cherry picked from commit b8be5674fa9a6f3677865ea93f7803c4212f3e10) Signed-off-by: Khalid Elmously --- net/sunrpc/auth_gss/svcauth_gss.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 5089dbb96d58..c69f2053c5be 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1122,7 +1122,7 @@ static int svcauth_gss_legacy_init(struct svc_rqst *rqstp, struct kvec *resv = &rqstp->rq_res.head[0]; struct rsi *rsip, rsikey; int ret; - struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); + struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); memset(&rsikey, 0, sizeof(rsikey)); ret = gss_read_verf(gc, argv, authp, @@ -1233,7 +1233,7 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp, uint64_t handle; int status; int ret; - struct net *net = rqstp->rq_xprt->xpt_net; + struct net *net = SVC_NET(rqstp); struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); memset(&ud, 0, sizeof(ud)); @@ -1424,7 +1424,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) __be32 *rpcstart; __be32 *reject_stat = resv->iov_base + resv->iov_len; int ret; - struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); + struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n", argv->iov_len); @@ -1714,7 +1714,7 @@ svcauth_gss_release(struct svc_rqst *rqstp) struct rpc_gss_wire_cred *gc = &gsd->clcred; struct xdr_buf *resbuf = &rqstp->rq_res; int stat = -EINVAL; - struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); + struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); if (gc->gc_proc != RPC_GSS_PROC_DATA) goto out; From patchwork Thu Apr 4 08:38:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Khalid Elmously X-Patchwork-Id: 1076975 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44Zbvq3TpPz9sST; Thu, 4 Apr 2019 19:39:00 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1hBxtd-0001et-SP; Thu, 04 Apr 2019 08:38:53 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1hBxtb-0001dn-EY for kernel-team@lists.ubuntu.com; Thu, 04 Apr 2019 08:38:51 +0000 Received: from mail-qt1-f197.google.com ([209.85.160.197]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1hBxtb-000432-0D for kernel-team@lists.ubuntu.com; Thu, 04 Apr 2019 08:38:51 +0000 Received: by mail-qt1-f197.google.com with SMTP id g17so1595001qte.17 for ; Thu, 04 Apr 2019 01:38:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=nkpKBoWcfjSs629AbBBtvqVv+0Tbvfbx7CVctM5IHQA=; b=Wvuuvjk+IumeUgMrnCRIk/RqTAgjm5EPIKKHwE4/cONuIHVFfVCAy0nwH60opnH5Wx AgYXKZgNAeO2P3f/p69di+wiQb8cp3GRqr/1o/MKsN0HE+rz3SOe/0Gg8daW3ohxziGM 7zC7rfROLp/IHYLEo7bIPd9BlOAYcw9hxR6YnQ4zxioymEGfnCFn/F5nnHaHKbR65Kkq VmUFUZ9PbaPeA5d8T6rrk5dz+LlUB6tjEh/oHs2uqLsa5vRAiSczHJNreiDjmRa1dxxv d21KjSpfuV6vxT27KrRYUEJwacIIzpgzctn8Bmpe4yJEzradxp4GoGyRNrK2+LfqZ8R7 ro3g== X-Gm-Message-State: APjAAAV0wCdn3cqFFmzydU7UpJfPIuxgDxk2J7gquSNw3rrSRL6Kp2yX LP5WL0GQEw3b8b/VMaFp7frsMUPSAQEgqy1/YlStzXho0qNSdLuU4T9a9Z38QnfEeUADij4zWF1 KkP1ggKeiMWYFpNEA0dofbODcs17OvWa4IwbyYAh5hg== X-Received: by 2002:ac8:1008:: with SMTP id z8mr4151574qti.240.1554367129972; Thu, 04 Apr 2019 01:38:49 -0700 (PDT) X-Google-Smtp-Source: APXvYqz1FzPdiBATdU4Jns3Scti7uFHBdNvuUuumKOgak38Dy87+xHnUgn8o0hH9iAFiSv10QftN2A== X-Received: by 2002:ac8:1008:: with SMTP id z8mr4151566qti.240.1554367129728; Thu, 04 Apr 2019 01:38:49 -0700 (PDT) Received: from localhost.localdomain (ool-45710a9c.dyn.optonline.net. [69.113.10.156]) by smtp.gmail.com with ESMTPSA id w9sm9111481qkf.94.2019.04.04.01.38.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 04 Apr 2019 01:38:48 -0700 (PDT) From: Khalid Elmously To: kernel-team@lists.ubuntu.com Subject: [SRU][C][PATCH v2 2/2] sunrpc: use-after-free in svc_process_common() Date: Thu, 4 Apr 2019 04:38:39 -0400 Message-Id: <20190404083839.14841-3-khalid.elmously@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190404083839.14841-1-khalid.elmously@canonical.com> References: <20190404083839.14841-1-khalid.elmously@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Vasily Averin if node have NFSv41+ mounts inside several net namespaces it can lead to use-after-free in svc_process_common() svc_process_common() /* Setup reply header */ rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); <<< HERE svc_process_common() can use incorrect rqstp->rq_xprt, its caller function bc_svc_process() takes it from serv->sv_bc_xprt. The problem is that serv is global structure but sv_bc_xprt is assigned per-netnamespace. According to Trond, the whole "let's set up rqstp->rq_xprt for the back channel" is nothing but a giant hack in order to work around the fact that svc_process_common() uses it to find the xpt_ops, and perform a couple of (meaningless for the back channel) tests of xpt_flags. All we really need in svc_process_common() is to be able to run rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr() Bruce J Fields points that this xpo_prep_reply_hdr() call is an awfully roundabout way just to do "svc_putnl(resv, 0);" in the tcp case. This patch does not initialiuze rqstp->rq_xprt in bc_svc_process(), now it calls svc_process_common() with rqstp->rq_xprt = NULL. To adjust reply header svc_process_common() just check rqstp->rq_prot and calls svc_tcp_prep_reply_hdr() for tcp case. To handle rqstp->rq_xprt = NULL case in functions called from svc_process_common() patch intruduces net namespace pointer svc_rqst->rq_bc_net and adjust SVC_NET() definition. Some other function was also adopted to properly handle described case. Signed-off-by: Vasily Averin Cc: stable@vger.kernel.org Fixes: 23c20ecd4475 ("NFS: callback up - users counting cleanup") Signed-off-by: J. Bruce Fields (backported from commit d4b09acf924b84bae77cad090a9d108e70b43643) [ kmously: Added a declaration for svc_tcp_prep_reply_hdr() to avoid implicit-function-declaration warnings/errors ] Signed-off-by: Khalid Elmously --- include/linux/sunrpc/svc.h | 5 ++++- include/trace/events/sunrpc.h | 6 ++++-- net/sunrpc/svc.c | 12 ++++++++---- net/sunrpc/svc_xprt.c | 5 +++-- net/sunrpc/svcsock.c | 2 +- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 574368e8a16f..dd459d3d822f 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -295,9 +295,12 @@ struct svc_rqst { struct svc_cacherep * rq_cacherep; /* cache info */ struct task_struct *rq_task; /* service thread */ spinlock_t rq_lock; /* per-request lock */ + struct net *rq_bc_net; /* pointer to backchannel's + * net namespace + */ }; -#define SVC_NET(svc_rqst) (svc_rqst->rq_xprt->xpt_net) +#define SVC_NET(rqst) (rqst->rq_xprt ? rqst->rq_xprt->xpt_net : rqst->rq_bc_net) /* * Rigorous type checking on sockaddr type conversions diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index bbb08a3ef5cc..a2644c494a9c 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h @@ -582,7 +582,8 @@ TRACE_EVENT(svc_process, __field(u32, vers) __field(u32, proc) __string(service, name) - __string(addr, rqst->rq_xprt->xpt_remotebuf) + __string(addr, rqst->rq_xprt ? + rqst->rq_xprt->xpt_remotebuf : "(null)") ), TP_fast_assign( @@ -590,7 +591,8 @@ TRACE_EVENT(svc_process, __entry->vers = rqst->rq_vers; __entry->proc = rqst->rq_proc; __assign_str(service, name); - __assign_str(addr, rqst->rq_xprt->xpt_remotebuf); + __assign_str(addr, rqst->rq_xprt ? + rqst->rq_xprt->xpt_remotebuf : "(null)"); ), TP_printk("addr=%s xid=0x%08x service=%s vers=%u proc=%u", diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 30a4226baf03..13694ccdf22c 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -34,6 +34,9 @@ static void svc_unregister(const struct svc_serv *serv, struct net *net); +void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp); + + #define svc_serv_is_pooled(serv) ((serv)->sv_ops->svo_function) #define SVC_POOL_DEFAULT SVC_POOL_GLOBAL @@ -1172,7 +1175,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) clear_bit(RQ_DROPME, &rqstp->rq_flags); /* Setup reply header */ - rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); + if (rqstp->rq_prot == IPPROTO_TCP) + svc_tcp_prep_reply_hdr(rqstp); svc_putu32(resv, rqstp->rq_xid); @@ -1244,7 +1248,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) * for lower versions. RPC_PROG_MISMATCH seems to be the closest * fit. */ - if (versp->vs_need_cong_ctrl && + if (versp->vs_need_cong_ctrl && rqstp->rq_xprt && !test_bit(XPT_CONG_CTRL, &rqstp->rq_xprt->xpt_flags)) goto err_bad_vers; @@ -1336,7 +1340,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) return 0; close: - if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags)) + if (rqstp->rq_xprt && test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags)) svc_close_xprt(rqstp->rq_xprt); dprintk("svc: svc_process close\n"); return 0; @@ -1459,10 +1463,10 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, dprintk("svc: %s(%p)\n", __func__, req); /* Build the svc_rqst used by the common processing routine */ - rqstp->rq_xprt = serv->sv_bc_xprt; rqstp->rq_xid = req->rq_xid; rqstp->rq_prot = req->rq_xprt->prot; rqstp->rq_server = serv; + rqstp->rq_bc_net = req->rq_xprt->xprt_net; rqstp->rq_addrlen = sizeof(req->rq_xprt->addr); memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 83ccd0221c98..6cf0fd37cbf0 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -469,10 +469,11 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool) */ void svc_reserve(struct svc_rqst *rqstp, int space) { + struct svc_xprt *xprt = rqstp->rq_xprt; + space += rqstp->rq_res.head[0].iov_len; - if (space < rqstp->rq_reserved) { - struct svc_xprt *xprt = rqstp->rq_xprt; + if (xprt && space < rqstp->rq_reserved) { atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved); rqstp->rq_reserved = space; diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 5445145e639c..0221f565538e 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1198,7 +1198,7 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp) /* * Setup response header. TCP has a 4B record length field. */ -static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) +void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) { struct kvec *resv = &rqstp->rq_res.head[0];