Fix CVE-2018-16884 (rhbz 1660375 1660825)
This commit is contained in:
parent
8674faa8b3
commit
1b52baea41
2 changed files with 236 additions and 0 deletions
230
CVE-2018-16884.patch
Normal file
230
CVE-2018-16884.patch
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
From 321f89f5812405fd3018b162535ae29bda669909 Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Averin <vvs@virtuozzo.com>
|
||||
Date: Mon, 24 Dec 2018 14:44:42 +0300
|
||||
Subject: [PATCH 1/2] sunrpc: use SVC_NET() in svcauth_gss_* functions
|
||||
|
||||
Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
|
||||
Signed-off-by: Jeremy Cline <jcline@redhat.com>
|
||||
---
|
||||
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 860f2a1bbb67..1a65f88d021a 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;
|
||||
--
|
||||
2.20.1
|
||||
|
||||
From b7cde4db1cb620368534aaf89c82e3ee10ef4d72 Mon Sep 17 00:00:00 2001
|
||||
From: Vasily Averin <vvs@virtuozzo.com>
|
||||
Date: Mon, 24 Dec 2018 14:44:52 +0300
|
||||
Subject: [PATCH 2/2] sunrpc: use-after-free in svc_process_common()
|
||||
|
||||
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 <vvs@virtuozzo.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 23c20ecd4475 ("NFS: callback up - users counting cleanup")
|
||||
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
|
||||
Signed-off-by: Jeremy Cline <jcline@redhat.com>
|
||||
---
|
||||
include/linux/sunrpc/svc.h | 5 ++++-
|
||||
include/trace/events/sunrpc.h | 6 ++++--
|
||||
net/sunrpc/svc.c | 9 +++++----
|
||||
net/sunrpc/svc_xprt.c | 5 +++--
|
||||
net/sunrpc/svcsock.c | 2 +-
|
||||
5 files changed, 17 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
|
||||
index 73e130a840ce..fdb6b317d974 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 d13e05f1a990..fb647bc01fc5 100644
|
||||
--- a/net/sunrpc/svc.c
|
||||
+++ b/net/sunrpc/svc.c
|
||||
@@ -1172,7 +1172,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 +1245,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 +1337,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 +1460,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];
|
||||
|
||||
--
|
||||
2.20.1
|
||||
|
||||
|
|
@ -636,6 +636,9 @@ Patch517: 0001-Bluetooth-btsdio-Do-not-bind-to-non-removable-BCM434.patch
|
|||
# CVE-2019-3701 rhbz 1663729 1663730
|
||||
Patch518: CVE-2019-3701.patch
|
||||
|
||||
# CVE-2018-16884 rhbz 1660375 1660825
|
||||
Patch519: CVE-2018-16884.patch
|
||||
|
||||
# END OF PATCH DEFINITIONS
|
||||
|
||||
%endif
|
||||
|
|
@ -1887,6 +1890,9 @@ fi
|
|||
#
|
||||
#
|
||||
%changelog
|
||||
* Wed Jan 09 2019 Jeremy Cline <jeremy@jcline.org>
|
||||
- Fix CVE-2018-16884 (rhbz 1660375 1660825)
|
||||
|
||||
* Wed Jan 09 2019 Justin M. Forbes <jforbes@fedoraproject.org>
|
||||
- Fix CVE-2019-3701 (rhbz 1663729 1663730)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue