[sr-dev] git:4.1: websocket: Set pointers to NULL when freeing ws connection strcutures

Hugh Waite hugh.waite at crocodile-rcs.com
Tue Dec 3 16:13:58 CET 2013


Module: sip-router
Branch: 4.1
Commit: 48a3412afe166f5cbd41a057a22a3333337a2856
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=48a3412afe166f5cbd41a057a22a3333337a2856

Author: Hugh Waite <hugh.waite at crocodile-rcs.com>
Committer: Hugh Waite <hugh.waite at crocodile-rcs.com>
Date:   Tue Dec  3 13:00:55 2013 +0000

websocket: Set pointers to NULL when freeing ws connection strcutures
 - Fixes double free crash FS#364
 - Reported by Vitaliy Aleksandrov
(cherry picked from commit 95749afb7129e2909b449b79706f0de5d06a3c5d)

---

 modules/websocket/ws_conn.c      |    1 -
 modules/websocket/ws_frame.c     |   51 +++++++++++++++++++++++++------------
 modules/websocket/ws_handshake.c |    2 +-
 3 files changed, 35 insertions(+), 19 deletions(-)

diff --git a/modules/websocket/ws_conn.c b/modules/websocket/ws_conn.c
index 263b49f..613f14e 100644
--- a/modules/websocket/ws_conn.c
+++ b/modules/websocket/ws_conn.c
@@ -138,7 +138,6 @@ static inline void _wsconn_rm(ws_connection_t *wsc)
 		update_stat(ws_msrp_current_connections, -1);
 
 	shm_free(wsc);
-	wsc = NULL;
 }
 
 void wsconn_destroy(void)
diff --git a/modules/websocket/ws_frame.c b/modules/websocket/ws_frame.c
index 503722e..a3a4cef 100644
--- a/modules/websocket/ws_frame.c
+++ b/modules/websocket/ws_frame.c
@@ -232,6 +232,7 @@ static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
 		pkg_free(send_buf);
 		if (wsconn_rm(frame->wsc, WSCONN_EVENTROUTE_YES) < 0)
 			LM_ERR("removing WebSocket connection\n");
+		frame->wsc = NULL;
 		return -1;
 	}
 	init_dst_from_rcv(&dst, &con->rcv);
@@ -243,8 +244,10 @@ static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
 			LM_ERR("removing WebSocket connection\n");
 			tcpconn_put(con);
 			pkg_free(send_buf);
+			frame->wsc = NULL;
 			return -1;
 		}
+		frame->wsc = NULL;
 	}
 
 	if (dst.proto == PROTO_WS)
@@ -297,6 +300,7 @@ static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
 			update_stat(ws_msrp_failed_connections, 1);
 		if (wsconn_rm(frame->wsc, WSCONN_EVENTROUTE_YES) < 0)
 			LM_ERR("removing WebSocket connection\n");
+		frame->wsc = NULL;
 		tcpconn_put(con);
 		return -1;
 	}
@@ -317,11 +321,19 @@ static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
 	return 0;
 }
 
-static int close_connection(ws_connection_t *wsc, ws_close_type_t type,
+static int close_connection(ws_connection_t **p_wsc, ws_close_type_t type,
 				short int status, str reason)
 {
 	char *data;
 	ws_frame_t frame;
+	ws_connection_t * wsc = NULL;
+	int sub_proto = -1;
+	if (!p_wsc || !(*p_wsc))
+	{
+		LM_ERR("Invalid parameters\n");
+		return -1;
+	}
+	wsc = *p_wsc;
 
 	if (wsc->state == WS_S_OPEN)
 	{
@@ -342,6 +354,7 @@ static int close_connection(ws_connection_t *wsc, ws_close_type_t type,
 		frame.payload_len = reason.len + 2;
 		frame.payload_data = data;
 		frame.wsc = wsc;
+		sub_proto = wsc->sub_protocol;
 
 		if (encode_and_send_ws_frame(&frame,
 			type ==
@@ -367,16 +380,20 @@ static int close_connection(ws_connection_t *wsc, ws_close_type_t type,
 		else
 		{
 			update_stat(ws_remote_closed_connections, 1);
-			if (frame.wsc->sub_protocol == SUB_PROTOCOL_SIP)
+			if (sub_proto == SUB_PROTOCOL_SIP)
 				update_stat(ws_sip_remote_closed_connections,
 						1);
-			else if (frame.wsc->sub_protocol == SUB_PROTOCOL_MSRP)
+			else if (sub_proto == SUB_PROTOCOL_MSRP)
 				update_stat(ws_msrp_remote_closed_connections,
 						1);
+			*p_wsc = NULL;
 		}
 	}
 	else /* if (frame->wsc->state == WS_S_CLOSING) */
+	{
 		wsconn_close_now(wsc);
+		*p_wsc = NULL;
+	}
 
 	return 0;
 }
@@ -402,7 +419,7 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame,
 	if (len < 2)
 	{
 		LM_WARN("message is too short\n");
-		if (close_connection(frame->wsc, LOCAL_CLOSE, 1002,
+		if (close_connection(&frame->wsc, LOCAL_CLOSE, 1002,
 					str_status_protocol_error) < 0)
 			LM_ERR("closing connection\n");
 		return -1;
@@ -418,7 +435,7 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame,
 	{
 		LM_WARN("WebSocket fragmentation not supported in the sip "
 			"sub-protocol\n");
-		if (close_connection(frame->wsc, LOCAL_CLOSE, 1002,
+		if (close_connection(&frame->wsc, LOCAL_CLOSE, 1002,
 					str_status_protocol_error) < 0)
 			LM_ERR("closing connection\n");
 		return -1;
@@ -427,7 +444,7 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame,
 	if (frame->rsv1 || frame->rsv2 || frame->rsv3)
 	{
 		LM_WARN("WebSocket reserved fields with non-zero values\n");
-		if (close_connection(frame->wsc, LOCAL_CLOSE, 1002,
+		if (close_connection(&frame->wsc, LOCAL_CLOSE, 1002,
 					str_status_protocol_error) < 0)
 			LM_ERR("closing connection\n");
 		return -1;
@@ -451,7 +468,7 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame,
 	default:
 		LM_WARN("unsupported opcode: 0x%x\n",
 			(unsigned char) frame->opcode);
-		if (close_connection(frame->wsc, LOCAL_CLOSE, 1008,
+		if (close_connection(&frame->wsc, LOCAL_CLOSE, 1008,
 					str_status_unsupported_opcode) < 0)
 			LM_ERR("closing connection\n");
 		return -1;
@@ -461,7 +478,7 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame,
 	{
 		LM_WARN("this is a server - all received messages must be "
 			"masked\n");
-		if (close_connection(frame->wsc, LOCAL_CLOSE, 1002,
+		if (close_connection(&frame->wsc, LOCAL_CLOSE, 1002,
 					str_status_protocol_error) < 0)
 			LM_ERR("closing connection\n");
 		return -1;
@@ -474,7 +491,7 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame,
 		if (len < 4)
 		{
 			LM_WARN("message is too short\n");
-			if (close_connection(frame->wsc, LOCAL_CLOSE, 1002,
+			if (close_connection(&frame->wsc, LOCAL_CLOSE, 1002,
 						str_status_protocol_error) < 0)
 				LM_ERR("closing connection\n");
 			return -1;
@@ -489,7 +506,7 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame,
 		if (len < 10)
 		{
 			LM_WARN("message is too short\n");
-			if (close_connection(frame->wsc, LOCAL_CLOSE, 1002,
+			if (close_connection(&frame->wsc, LOCAL_CLOSE, 1002,
 						str_status_protocol_error) < 0)
 				LM_ERR("closing connection\n");
 			return -1;
@@ -500,7 +517,7 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame,
 			|| (buf[4] & 0xff) != 0 || (buf[5] & 0xff) != 0)
 		{
 			LM_WARN("message is too long\n");
-			if (close_connection(frame->wsc, LOCAL_CLOSE, 1009,
+			if (close_connection(&frame->wsc, LOCAL_CLOSE, 1009,
 						str_status_message_too_big) < 0)
 				LM_ERR("closing connection\n");
 			return -1;
@@ -528,7 +545,7 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame,
 	{
 		LM_WARN("message not complete frame size %u but received %u\n",
 			frame->payload_len + mask_start + 4, len);
-		if (close_connection(frame->wsc, LOCAL_CLOSE, 1002,
+		if (close_connection(&frame->wsc, LOCAL_CLOSE, 1002,
 					str_status_protocol_error) < 0)
 			LM_ERR("closing connection\n");
 		return -1;
@@ -564,7 +581,7 @@ static int handle_close(ws_frame_t *frame)
 
 	LM_DBG("Rx Close: %hu %.*s\n", code, reason.len, reason.s);
 
-	if (close_connection(frame->wsc,
+	if (close_connection(&frame->wsc,
 		frame->wsc->state == WS_S_OPEN ? REMOTE_CLOSE : LOCAL_CLOSE,
 		1000, str_status_normal_closure) < 0)
 	{
@@ -758,7 +775,7 @@ struct mi_root *ws_mi_close(struct mi_root *cmd, void *param)
 					str_status_bad_param.len);
 	}
 
-	if (close_connection(wsc, LOCAL_CLOSE, 1000,
+	if (close_connection(&wsc, LOCAL_CLOSE, 1000,
 				str_status_normal_closure) < 0)
 	{
 		LM_WARN("closing connection\n");
@@ -861,7 +878,7 @@ int ws_close(sip_msg_t *msg)
 		return -1;
 	}
 
-	return (close_connection(wsc, LOCAL_CLOSE, 1000,
+	return (close_connection(&wsc, LOCAL_CLOSE, 1000,
 				 str_status_normal_closure) == 0) ? 1: 0;
 }
 
@@ -886,7 +903,7 @@ int ws_close2(sip_msg_t *msg, char *_status, char *_reason)
 		return -1;
 	}
 
-	return (close_connection(wsc, LOCAL_CLOSE, status, reason) == 0) ? 1: 0;
+	return (close_connection(&wsc, LOCAL_CLOSE, status, reason) == 0) ? 1: 0;
 }
 
 int ws_close3(sip_msg_t *msg, char *_status, char *_reason, char *_con)
@@ -916,5 +933,5 @@ int ws_close3(sip_msg_t *msg, char *_status, char *_reason, char *_con)
 		return -1;
 	}
 
-	return (close_connection(wsc, LOCAL_CLOSE, status, reason) == 0) ? 1: 0;
+	return (close_connection(&wsc, LOCAL_CLOSE, status, reason) == 0) ? 1: 0;
 }
diff --git a/modules/websocket/ws_handshake.c b/modules/websocket/ws_handshake.c
index 1ca6fe1..c4e3143 100644
--- a/modules/websocket/ws_handshake.c
+++ b/modules/websocket/ws_handshake.c
@@ -122,7 +122,7 @@ int ws_handle_handshake(struct sip_msg *msg)
 	str key = {0, 0}, headers = {0, 0}, reply_key = {0, 0}, origin = {0, 0};
 	unsigned char sha1[SHA_DIGEST_LENGTH];
 	unsigned int hdr_flags = 0, sub_protocol = 0;
-	int version;
+	int version = 0;
 	struct hdr_field *hdr = msg->headers;
 	struct tcp_connection *con;
 	ws_connection_t *wsc;




More information about the sr-dev mailing list