summaryrefslogtreecommitdiffstats
path: root/net/rds
diff options
context:
space:
mode:
authorKa-Cheong Poon <ka-cheong.poon@oracle.com>2018-04-11 00:57:25 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-04-19 08:56:15 +0200
commit427b8a146973f10acd4aaa605d2377eb4cf43e55 (patch)
treef171fed5f64eacf942a16a259386f7c26a46a2a5 /net/rds
parent856d5d075a92c5b3e41d366369dda1e5a5f7cc67 (diff)
downloadlinux-stable-427b8a146973f10acd4aaa605d2377eb4cf43e55.tar.gz
linux-stable-427b8a146973f10acd4aaa605d2377eb4cf43e55.tar.bz2
linux-stable-427b8a146973f10acd4aaa605d2377eb4cf43e55.zip
rds: MP-RDS may use an invalid c_path
[ Upstream commit a43cced9a348901f9015f4730b70b69e7c41a9c9 ] rds_sendmsg() calls rds_send_mprds_hash() to find a c_path to use to send a message. Suppose the RDS connection is not yet up. In rds_send_mprds_hash(), it does if (conn->c_npaths == 0) wait_event_interruptible(conn->c_hs_waitq, (conn->c_npaths != 0)); If it is interrupted before the connection is set up, rds_send_mprds_hash() will return a non-zero hash value. Hence rds_sendmsg() will use a non-zero c_path to send the message. But if the RDS connection ends up to be non-MP capable, the message will be lost as only the zero c_path can be used. Signed-off-by: Ka-Cheong Poon <ka-cheong.poon@oracle.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/rds')
-rw-r--r--net/rds/send.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/net/rds/send.c b/net/rds/send.c
index f72466c63f0c..23f2d81e7967 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -986,10 +986,15 @@ static int rds_send_mprds_hash(struct rds_sock *rs, struct rds_connection *conn)
if (conn->c_npaths == 0 && hash != 0) {
rds_send_ping(conn, 0);
- if (conn->c_npaths == 0) {
- wait_event_interruptible(conn->c_hs_waitq,
- (conn->c_npaths != 0));
- }
+ /* The underlying connection is not up yet. Need to wait
+ * until it is up to be sure that the non-zero c_path can be
+ * used. But if we are interrupted, we have to use the zero
+ * c_path in case the connection ends up being non-MP capable.
+ */
+ if (conn->c_npaths == 0)
+ if (wait_event_interruptible(conn->c_hs_waitq,
+ conn->c_npaths != 0))
+ hash = 0;
if (conn->c_npaths == 1)
hash = 0;
}