Blob Blame History Raw
From 82526d2fe9137e8b604f1bbae6d6e39ba41377f9 Mon Sep 17 00:00:00 2001
From: Christine Caulfield <ccaulfie@redhat.com>
Date: Mon, 16 Mar 2015 11:37:52 +0000
Subject: [PATCH] quorum: don't allow quorum_trackstart to be called twice

If quorum_trackstart() or votequorum_trackstart() are called twice with
CS_TRACK_CHANGES then the client gets added twice to the notifications
list effectively corrupting it. Users have reported segfaults in
corosync when they did this (by mistake!).

As there's already a tracking_enabled flag in the private-data, we check
that before adding to the list again and return an error if
the process is already registered.

Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
Reviewed-by: Jan Friesse <jfriesse@redhat.com>
---
 exec/votequorum.c |   12 ++++++++++--
 exec/vsf_quorum.c |   11 +++++++++--
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/exec/votequorum.c b/exec/votequorum.c
index 2ff0b43..f6faa25 100644
--- a/exec/votequorum.c
+++ b/exec/votequorum.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2014 Red Hat, Inc.
+ * Copyright (c) 2009-2015 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -2615,8 +2615,10 @@ static void message_handler_req_lib_votequorum_trackstart (void *conn,
 	const struct req_lib_votequorum_trackstart *req_lib_votequorum_trackstart = message;
 	struct res_lib_votequorum_status res_lib_votequorum_status;
 	struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
+	cs_error_t error = CS_OK;
 
 	ENTER();
+
 	/*
 	 * If an immediate listing of the current cluster membership
 	 * is requested, generate membership list
@@ -2627,6 +2629,11 @@ static void message_handler_req_lib_votequorum_trackstart (void *conn,
 		votequorum_exec_send_quorum_notification(conn, req_lib_votequorum_trackstart->context);
 	}
 
+	if (quorum_pd->tracking_enabled) {
+		error = CS_ERR_EXIST;
+		goto response_send;
+	}
+
 	/*
 	 * Record requests for tracking
 	 */
@@ -2640,9 +2647,10 @@ static void message_handler_req_lib_votequorum_trackstart (void *conn,
 		list_add (&quorum_pd->list, &trackers_list);
 	}
 
+response_send:
 	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
 	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
-	res_lib_votequorum_status.header.error = CS_OK;
+	res_lib_votequorum_status.header.error = error;
 	corosync_api->ipc_response_send(conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status));
 
 	LEAVE();
diff --git a/exec/vsf_quorum.c b/exec/vsf_quorum.c
index 2a3a263..a6c739d 100644
--- a/exec/vsf_quorum.c
+++ b/exec/vsf_quorum.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2012 Red Hat, Inc.
+ * Copyright (c) 2008-2015 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -409,6 +409,7 @@ static void message_handler_req_lib_quorum_trackstart (void *conn,
 	const struct req_lib_quorum_trackstart *req_lib_quorum_trackstart = msg;
 	struct qb_ipc_response_header res;
 	struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
+	cs_error_t error = CS_OK;
 
 	log_printf(LOGSYS_LEVEL_DEBUG, "got trackstart request on %p", conn);
 
@@ -422,6 +423,11 @@ static void message_handler_req_lib_quorum_trackstart (void *conn,
 		send_library_notification(conn);
 	}
 
+	if (quorum_pd->tracking_enabled) {
+		error = CS_ERR_EXIST;
+		goto response_send;
+	}
+
 	/*
 	 * Record requests for tracking
 	 */
@@ -434,10 +440,11 @@ static void message_handler_req_lib_quorum_trackstart (void *conn,
 		list_add (&quorum_pd->list, &lib_trackers_list);
 	}
 
+response_send:
 	/* send status */
 	res.size = sizeof(res);
 	res.id = MESSAGE_RES_QUORUM_TRACKSTART;
-	res.error = CS_OK;
+	res.error = error;
 	corosync_api->ipc_response_send(conn, &res, sizeof(struct qb_ipc_response_header));
 }
 
-- 
1.7.1