changeset 1082:c62416017121 HEAD

make sure we don't access free'd memory if auth process dies.
author Timo Sirainen <tss@iki.fi>
date Sun, 02 Feb 2003 11:45:07 +0200
parents 98dca3b6b209
children f6ec28683512
files src/login-common/auth-connection.c src/login-common/auth-connection.h
diffstat 2 files changed, 43 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/login-common/auth-connection.c	Sun Feb 02 11:30:18 2003 +0200
+++ b/src/login-common/auth-connection.c	Sun Feb 02 11:45:07 2003 +0200
@@ -27,6 +27,8 @@
 static struct timeout *to;
 
 static void auth_connection_destroy(struct auth_connection *conn);
+static void auth_connection_unref(struct auth_connection *conn);
+
 static void auth_input(void *context);
 static void auth_connect_missing(void);
 
@@ -59,6 +61,7 @@
         net_set_nonblock(fd, FALSE);
 
 	conn = i_new(struct auth_connection, 1);
+	conn->refcount = 1;
 	conn->path = i_strdup(path);
 	conn->fd = fd;
 	conn->io = io_add(fd, IO_READ, auth_input, conn);
@@ -88,12 +91,19 @@
 	i_free(request);
 }
 
+static void request_hash_remove(void *key __attr_unused__, void *value,
+				void *context __attr_unused__)
+{
+	struct auth_request *request = value;
+
+	request->callback(request, NULL, NULL, request->context);
+}
+
 static void request_hash_destroy(void *key __attr_unused__, void *value,
 				 void *context __attr_unused__)
 {
 	struct auth_request *request = value;
 
-	request->callback(request, NULL, NULL, request->context);
 	request_destroy(request);
 }
 
@@ -101,6 +111,9 @@
 {
 	struct auth_connection **pos;
 
+	if (conn->fd == -1)
+		return;
+
 	for (pos = &auth_connections; *pos != NULL; pos = &(*pos)->next) {
 		if (*pos == conn) {
 			*pos = conn->next;
@@ -108,12 +121,24 @@
 		}
 	}
 
+	if (close(conn->fd) < 0)
+		i_error("close(auth) failed: %m");
+	io_remove(conn->io);
+	conn->fd = -1;
+
+	hash_foreach(conn->requests, request_hash_remove, NULL);
+
+        auth_connection_unref(conn);
+}
+
+static void auth_connection_unref(struct auth_connection *conn)
+{
+	if (--conn->refcount > 0)
+		return;
+
 	hash_foreach(conn->requests, request_hash_destroy, NULL);
 	hash_destroy(conn->requests);
 
-	if (close(conn->fd) < 0)
-		i_error("close(auth) failed: %m");
-	io_remove(conn->io);
 	i_stream_unref(conn->input);
 	o_stream_unref(conn->output);
 	i_free(conn->path);
@@ -309,6 +334,16 @@
         request_destroy(request);
 }
 
+void auth_request_ref(struct auth_request *request)
+{
+	request->conn->refcount++;
+}
+
+void auth_request_unref(struct auth_request *request)
+{
+	auth_connection_unref(request->conn);
+}
+
 static void auth_connect_missing(void)
 {
 	DIR *dirp;
--- a/src/login-common/auth-connection.h	Sun Feb 02 11:30:18 2003 +0200
+++ b/src/login-common/auth-connection.h	Sun Feb 02 11:45:07 2003 +0200
@@ -11,6 +11,7 @@
 
 struct auth_connection {
 	struct auth_connection *next;
+	int refcount;
 
 	char *path;
 	int fd;
@@ -50,6 +51,9 @@
 
 void auth_abort_request(struct auth_request *request);
 
+void auth_request_ref(struct auth_request *request);
+void auth_request_unref(struct auth_request *request);
+
 void auth_connection_init(void);
 void auth_connection_deinit(void);