summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>2015-08-11 19:22:20 -0300
committerDavid Teigland <teigland@redhat.com>2015-08-17 16:22:15 -0500
commit28926a0965a943f7c1586342f9482a6e41b4f0c9 (patch)
treea8c435d7771edfac196c15d10c16fe322e77ef6d
parentf7644cbfcdf03528f0f450f3940c4985b2291f49 (diff)
dlm: fix connection stealing if using SCTP
When using SCTP and accepting a new connection, DLM currently validates if the peer trying to connect to it is one of the cluster nodes, but it doesn't check if it already has a connection to it or not. If it already had a connection, it will be overwritten, and the new one will be used for writes, possibly causing the node to leave the cluster due to communication breakage. Still, one could DoS the node by attempting N connections and keeping them open. As said, but being explicit, both situations are only triggerable from other cluster nodes, but are doable with only user-level perms. Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David Teigland <teigland@redhat.com>
-rw-r--r--fs/dlm/lowcomms.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 754fd6c0b747..bc04f5e3af7a 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -535,7 +535,9 @@ static void close_connection(struct connection *con, bool and_other)
mutex_unlock(&con->sock_mutex);
}
-/* We only send shutdown messages to nodes that are not part of the cluster */
+/* We only send shutdown messages to nodes that are not part of the cluster
+ * or if we get multiple connections from a node.
+ */
static void sctp_send_shutdown(sctp_assoc_t associd)
{
static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
@@ -718,6 +720,14 @@ static void process_sctp_notification(struct connection *con,
if (!new_con)
return;
+ if (new_con->sock) {
+ log_print("reject connect from node %d: "
+ "already has a connection.",
+ nodeid);
+ sctp_send_shutdown(prim.ssp_assoc_id);
+ return;
+ }
+
/* Peel off a new sock */
lock_sock(con->sock->sk);
ret = sctp_do_peeloff(con->sock->sk,