[mw-devel] MW3 r1284 - in trunk/src: . server

arthur at sucs.org arthur at sucs.org
Thu Nov 8 15:19:10 GMT 2012


Author: arthur
Date: 2012-11-08 15:19:10 +0000 (Thu, 08 Nov 2012)
New Revision: 1284

Modified:
   trunk/src/Makefile
   trunk/src/incoming.c
   trunk/src/ipc.c
   trunk/src/server/servsock.c
   trunk/src/socket.c
   trunk/src/socket.h
Log:
reorder some socket code to prevent accessing already freed structures


Modified: trunk/src/Makefile
===================================================================
--- trunk/src/Makefile	2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/Makefile	2012-11-08 15:19:10 UTC (rev 1284)
@@ -93,6 +93,7 @@
 	done
 	make libdir="$(TESTDIR)" localstatedir="$(TESTDIR)"
 	make -C server libdir="$(TESTDIR)" localstatedir="$(TESTDIR)"
+	make -C webclient libdir="$(TESTDIR)" localstatedir="$(TESTDIR)"
 
 testclean: clean
 	rm -rf "$(TESTDIR)"

Modified: trunk/src/incoming.c
===================================================================
--- trunk/src/incoming.c	2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/incoming.c	2012-11-08 15:19:10 UTC (rev 1284)
@@ -455,7 +455,13 @@
 		ipcmsg_destroy(msg);
 		msg = read_socket(ipcsock, 0);
 	}
-	if (msg == NULL && !ipc_connected()) fprintf(stderr, "Server disconnected.\n");
+	if (msg == NULL && !ipc_connected()) {
+		if (ipcsock->fd != -1) {
+			close(ipcsock->fd);
+			ipcsock->fd = -1;
+		}
+		fprintf(stderr, "Server disconnected.\n");
+	}
 	if (cm_flags(user->chatmode,CM_ONCHAT,CM_MODE_ANY)) set_talk_rights(); else set_rights();
 }
 

Modified: trunk/src/ipc.c
===================================================================
--- trunk/src/ipc.c	2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/ipc.c	2012-11-08 15:19:10 UTC (rev 1284)
@@ -30,6 +30,7 @@
 	/* we are not connected now */
 	if (ipcsock == NULL) return 0;
 	if (ipcsock->fd == -1) return 0;
+	if (ipcsock->state == IPCSTATE_ERROR) return 0;
 	/* everything must be fine */
 	return 1;
 }
@@ -58,6 +59,7 @@
 
 	ipcsock = ipcconn_create();
 	ipcsock->fd = fd;
+	ipcsock->state = IPCSTATE_CONNECTED;
 
 	pid_t mypid = getpid();
 	ipc_message_t * msg = ipcmsg_create(FOURCC("HELO"), mypid);
@@ -79,6 +81,7 @@
 {
 	if (ipcsock == NULL) return;
 	close(ipcsock->fd);
+	ipcsock->state = IPCSTATE_DELETED;
 	free(ipcsock);
 	ipcsock=NULL;
 }

Modified: trunk/src/server/servsock.c
===================================================================
--- trunk/src/server/servsock.c	2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/server/servsock.c	2012-11-08 15:19:10 UTC (rev 1284)
@@ -81,8 +81,6 @@
 	/* add to list of all connections */
 	list_add_tail(&(new->list), &connection_list);
 
-	INIT_LIST_HEAD(&(new->outq));
-
 	/* register interest in read events */
 	struct epoll_event ev;
 	bzero(&ev, sizeof(ev));
@@ -117,20 +115,22 @@
 {
 	struct epoll_event ev;
 
-	printf("Drop connection\n");
+	printf("Drop connection fd=%d\n", conn->fd);
 	bzero(&ev, sizeof(ev));
 	epoll_ctl(pollfd, EPOLL_CTL_DEL, conn->fd, &ev);
 	list_del_init(&conn->list);
 	if (conn->fd != -1) close(conn->fd);
 	conn->fd = -1;
-	conn->state = IPCSTATE_ERROR;
 	who_delete(conn->addr);
+	conn->state = IPCSTATE_DELETED;
 	if (!list_empty(&conn->outq)) {
 		struct list_head *pos, *q;
 		list_for_each_safe(pos, q, &conn->outq) {
-			ipc_message_t * msg = list_entry(pos, ipc_message_t, list);
-			list_del(pos);
-			ipcmsg_destroy(msg);
+			outq_msg_t * q = list_entry(pos, outq_msg_t, list);
+			list_del(&(q->list));
+			q->msg->refcount--;
+			if (q->msg->refcount <= 0) ipcmsg_destroy(q->msg);
+			free(q);
 		}
 	}
 	bzero(conn, sizeof(ipc_connection_t));
@@ -172,13 +172,10 @@
 			} else {
 				ipc_connection_t *c = event[i].data.ptr;
 				if (event[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) {
-					drop_connection(c);
+					ipcconn_bad(c);
 				} else
 				if (event[i].events & (EPOLLIN | EPOLLPRI)) {
 					ipc_message_t *msg = read_socket(c, 1);
-					if (c->fd == -1) {
-						drop_connection(c);
-					}else
 					while (msg != NULL) {
 						process_msg(c, msg);
 						msg=read_socket(c,0);
@@ -190,6 +187,15 @@
 					fprintf(stderr, "unexpected event on fd=%d.\n", c->fd);
 				}
 			}
+
+			/* check if we had to drop any connections and clean them away */
+			struct list_head *pos, *q;
+			list_for_each_safe(pos, q, &connection_list) {
+				ipc_connection_t * c = list_entry(pos, ipc_connection_t, list);
+				if (c->fd != -1 && c->state == IPCSTATE_ERROR) {
+					drop_connection(c);
+				}
+			}
 		}
 		/* end of events handling, do periodic stuff here */
 	}
@@ -203,6 +209,9 @@
 
 void write_socket(ipc_connection_t * conn)
 {
+	if (conn == NULL) return;
+	if (conn->state == IPCSTATE_ERROR) return;
+
 	if (list_empty(&conn->outq)) {
 		/* tx queue is empty, stop write events */
 		struct epoll_event ev;

Modified: trunk/src/socket.c
===================================================================
--- trunk/src/socket.c	2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/socket.c	2012-11-08 15:19:10 UTC (rev 1284)
@@ -6,6 +6,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netdb.h>
+#include <errno.h>
 #include "socket.h"
 
 /* generate FOURCC code from a string */
@@ -45,7 +46,8 @@
 /* free a message */
 void ipcmsg_destroy(ipc_message_t * msg)
 {
-	if (msg->body) free(msg->body);
+	if (msg == NULL) return;
+	if (msg->body != NULL) free(msg->body);
 	bzero(msg, sizeof(ipc_message_t));
 	free(msg);
 }
@@ -82,8 +84,7 @@
 /* mark this socket as bad/gone */
 void ipcconn_bad(ipc_connection_t * conn)
 {
-	close(conn->fd);
-	conn->fd = -1;
+	conn->state = IPCSTATE_ERROR;
 }
 
 /* create an empty connection socket struct */
@@ -92,6 +93,7 @@
 	ipc_connection_t * conn = malloc(sizeof(ipc_connection_t));
 	bzero(conn, sizeof(ipc_connection_t));
 	conn->fd = -1;
+	conn->state = IPCSTATE_ERROR;
 	INIT_LIST_HEAD(&(conn->outq));
 	return conn;
 }
@@ -160,10 +162,11 @@
  */
 ipc_message_t * read_socket(ipc_connection_t * conn, int doread)
 {
-	if (doread) {
+	if (doread && conn->state != IPCSTATE_ERROR && conn->fd != -1) {
 		int remain = sizeof(conn->p_buffer) - conn->i_buffer;
 		int ret = read(conn->fd, &conn->p_buffer[conn->i_buffer], remain);
 		if (ret <= 0) {
+			fprintf(stderr, "fd=%d bad read ret=%d %s\n", conn->fd, ret, strerror(errno));
 			ipcconn_bad(conn);
 			return NULL;
 		}
@@ -180,6 +183,8 @@
 
 	       if (conn->incoming->head.len > 8192){
 		       fprintf(stderr, "fd=%d Stupidly long message %d bytes.\n", conn->fd, conn->incoming->head.len);
+		       ipcmsg_destroy(conn->incoming);
+		       conn->incoming = NULL;
 		       ipcconn_bad(conn);
 		       return NULL;
 	       }

Modified: trunk/src/socket.h
===================================================================
--- trunk/src/socket.h	2012-11-08 11:56:53 UTC (rev 1283)
+++ trunk/src/socket.h	2012-11-08 15:19:10 UTC (rev 1284)
@@ -10,7 +10,8 @@
 enum ipcsock_state {
 	IPCSTATE_CONNECTED,
 	IPCSTATE_VALID,
-	IPCSTATE_ERROR
+	IPCSTATE_ERROR,
+	IPCSTATE_DELETED
 };
 
 /* packed struct for socket ipc */
@@ -22,7 +23,6 @@
 } __attribute__((packed)) ipc_msghead_t;
 
 typedef struct {
-	struct list_head	list;
 	ipc_msghead_t		head;
 	char *			body;
 	int			bodylen;




More information about the mw-devel mailing list