]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master API changed to avoid accidentally leaking client connections.
authorTimo Sirainen <tss@iki.fi>
Thu, 27 May 2010 11:16:36 +0000 (12:16 +0100)
committerTimo Sirainen <tss@iki.fi>
Thu, 27 May 2010 11:16:36 +0000 (12:16 +0100)
This change also fixes many such leaks.

--HG--
branch : HEAD

17 files changed:
src/anvil/main.c
src/auth/main.c
src/config/main.c
src/dict/main.c
src/director/main.c
src/dns/dns-client.c
src/dsync/dsync.c
src/imap/main.c
src/lib-master/master-service.c
src/lib-master/master-service.h
src/lmtp/main.c
src/log/main.c
src/login-common/main.c
src/pop3/main.c
src/ssl-params/main.c
src/util/script.c
src/util/tcpwrap.c

index 2ba01c9538571c7282e9cd1700214907cbc5aa25..8c8c77e560d6cfcd936b1f11b64e8b82ffa9a4b1 100644 (file)
@@ -18,10 +18,11 @@ struct connect_limit *connect_limit;
 struct penalty *penalty;
 static struct io *log_fdpass_io;
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
        bool master = conn->listen_fd == MASTER_LISTEN_FD_FIRST;
 
+       master_service_client_connection_accept(conn);
        anvil_connection_create(conn->fd, master, conn->fifo);
 }
 
index 4acf2cf4af9852dfe1bb317e17d871feb3d7d96f..9c58a2fa78d51b8b6a0233a18656b1a22e6830b8 100644 (file)
@@ -182,18 +182,18 @@ static void main_deinit(void)
        pool_unref(&auth_set_pool);
 }
 
-static void worker_connected(const struct master_service_connection *conn)
+static void worker_connected(struct master_service_connection *conn)
 {
        if (auth_worker_client != NULL) {
                i_error("Auth workers can handle only a single client");
-               (void)close(conn->fd);
                return;
        }
 
+       master_service_client_connection_accept(conn);
        (void)auth_worker_client_create(auth_find_service(NULL), conn->fd);
 }
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
        enum auth_socket_type *type;
        const char *path, *name, *suffix;
@@ -245,6 +245,7 @@ static void client_connected(const struct master_service_connection *conn)
        default:
                i_unreached();
        }
+       master_service_client_connection_accept(conn);
 }
 
 
index c1616f341b471a68a07ca317ed97acffa6611674..7db4deeede45f43b3ef4fe12b7ede312965ea092 100644 (file)
@@ -8,8 +8,9 @@
 #include "config-parser.h"
 #include "config-request.h"
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
+       master_service_client_connection_accept(conn);
        config_connection_create(conn->fd);
 }
 
index 61379ec7484c2236ddaba89686f6645c740f7c85..683122743b43ba1bdebdde1cacf3be13b38f96af 100644 (file)
@@ -20,8 +20,9 @@ static void dict_die(void)
        /* hope that other processes relying on us will die first. */
 }
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
+       master_service_client_connection_accept(conn);
        dict_connection_create(conn->fd);
 }
 
index 099ef8d1ee43dacc6d1b4abf8bdf190dc846631f..37596f6808c2af9f2e67f22cd5d7e7d59e6926ab 100644 (file)
@@ -37,7 +37,7 @@ static int director_client_connected(int fd, const struct ip_addr *ip)
        return 0;
 }
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
        struct auth_connection *auth;
        const char *path, *name;
@@ -47,9 +47,9 @@ static void client_connected(const struct master_service_connection *conn)
        if (conn->fifo) {
                if (notify_conn != NULL) {
                        i_error("Received another proxy-notify connection");
-                       (void)close(conn->fd);
                        return;
                }
+               master_service_client_connection_accept(conn);
                notify_conn = notify_connection_init(director, conn->fd);
                return;
        }
@@ -57,8 +57,8 @@ static void client_connected(const struct master_service_connection *conn)
        if (net_getpeername(conn->fd, &ip, &port) == 0 &&
            (IPADDR_IS_V4(&ip) || IPADDR_IS_V6(&ip))) {
                /* TCP/IP connection - this is another director */
-               if (director_client_connected(conn->fd, &ip) < 0)
-                       (void)close(conn->fd);
+               if (director_client_connected(conn->fd, &ip) == 0)
+                       master_service_client_connection_accept(conn);
                return;
        }
 
@@ -74,14 +74,15 @@ static void client_connected(const struct master_service_connection *conn)
        len = strlen(name);
        if (len > 6 && strcmp(name + len - 6, "-admin") == 0) {
                /* doveadm connection */
+               master_service_client_connection_accept(conn);
                (void)doveadm_connection_init(director, conn->fd);
        } else {
                /* login connection */
                auth = auth_connection_init(auth_socket_path);
-               if (auth_connection_connect(auth) == 0)
+               if (auth_connection_connect(auth) == 0) {
+                       master_service_client_connection_accept(conn);
                        login_connection_init(director, conn->fd, auth);
-               else {
-                       (void)close(conn->fd);
+               } else {
                        auth_connection_deinit(&auth);
                }
        }
index fc44b606e6c185546592b16256666ffa74a5b312..fdbccbbceac075590a918e1efdca8306fb2288a8 100644 (file)
@@ -115,13 +115,14 @@ static void dns_client_destroy(struct dns_client **_client)
        master_service_client_connection_destroyed(master_service);
 }
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
        if (dns_client != NULL) {
                i_error("dns-client must be configured with client_limit=1");
-               (void)close(conn->fd);
                return;
        }
+
+       master_service_client_connection_accept(conn);
        dns_client = dns_client_create(conn->fd);
 }
 
index 169cf53418cc9afade52ee224f50741438d8528d..2719444fe433030439c4fc3f748d6450d4d858b0 100644 (file)
@@ -67,7 +67,7 @@ usage(void)
 }
 
 static void
-dsync_connected(const struct master_service_connection *conn ATTR_UNUSED)
+dsync_connected(struct master_service_connection *conn ATTR_UNUSED)
 {
        i_fatal("Running as service not supported currently");
 }
index 5ddf8c3266213c88591e78eeb9ca4f79fb8a94fc..bf9f084fa0a43b70a72f8ee6e3fcc02dbe14b1fa 100644 (file)
@@ -276,12 +276,12 @@ static void login_client_failed(const struct master_login_client *client,
        }
 }
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
        if (master_login == NULL) {
                /* running standalone, we shouldn't even get here */
-               (void)close(conn->fd);
        } else {
+               master_service_client_connection_accept(conn);
                master_login_add(master_login, conn->fd);
        }
 }
index d09c0d1367b28f2c9434447175c96ca67335fcf9..48a087cc354db916b52456f64999f2c3b8a93b55 100644 (file)
@@ -537,6 +537,11 @@ void master_service_anvil_send(struct master_service *service, const char *cmd)
        }
 }
 
+void master_service_client_connection_accept(struct master_service_connection *conn)
+{
+       conn->accepted = TRUE;
+}
+
 void master_service_client_connection_destroyed(struct master_service *service)
 {
        /* we can listen again */
@@ -711,6 +716,12 @@ static void master_service_listen(struct master_service_listener *l)
        master_status_update(service);
 
        service->callback(&conn);
+
+       if (!conn.accepted) {
+               if (close(conn.fd) < 0)
+                       i_error("close(service connection) failed: %m");
+               master_service_client_connection_destroyed(service);
+       }
 }
 
 static void io_listeners_init(struct master_service *service)
index ddbc08eb7e6b95ce0ad5631c85d6565b8f54b66c..16e08f5ed30044716afd89f750756247424bffe2 100644 (file)
@@ -29,10 +29,12 @@ struct master_service_connection {
 
        unsigned int fifo:1;
        unsigned int ssl:1;
+
+       unsigned int accepted:1;
 };
 
 typedef void
-master_service_connection_callback_t(const struct master_service_connection *conn);
+master_service_connection_callback_t(struct master_service_connection *conn);
 
 extern struct master_service *master_service;
 
@@ -109,6 +111,8 @@ void master_service_stop_new_connections(struct master_service *service);
 
 /* Send command to anvil process, if we have fd to it. */
 void master_service_anvil_send(struct master_service *service, const char *cmd);
+/* Call to accept the client connection. Otherwise the connection is closed. */
+void master_service_client_connection_accept(struct master_service_connection *conn);
 /* Call whenever a client connection is destroyed. */
 void master_service_client_connection_destroyed(struct master_service *service);
 
index 09d90e2b7895943735871bd4cb5561884880d861..5e5419a07982da7e558c4eb05b51578bf9b5cd8c 100644 (file)
@@ -28,8 +28,9 @@
 const char *dns_client_socket_path;
 struct mail_storage_service_ctx *storage_service;
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
+       master_service_client_connection_accept(conn);
        (void)client_create(conn->fd, conn->fd, conn);
 }
 
index 8ae655d904868cf0944c9c3e051595e7b4588774..54990bb39755752572f757ed2f8376ffc2379ea4 100644 (file)
@@ -28,8 +28,9 @@ static void main_deinit(void)
        log_connections_deinit();
 }
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
+       master_service_client_connection_accept(conn);
        log_connection_create(conn->fd, conn->listen_fd);
 }
 
index 9b2783e8b169d42d2ec2b93d93682684a31dc99a..c8dafe44558718c5b784996c5d84252bb1393a91 100644 (file)
@@ -206,12 +206,14 @@ static void client_input_error(struct login_access_lookup *lookup)
        }
 }
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
        const char *access_sockets =
                global_login_settings->login_access_sockets;
        struct login_access_lookup *lookup;
 
+       master_service_client_connection_accept(conn);
+
        /* make sure we're connected (or attempting to connect) to auth */
        auth_client_connect(auth_client);
 
index dc577a7cbe494a696c98606068f26e5570e430c3..a9f7d43e485dd013ec16f334472899b218b3511a 100644 (file)
@@ -172,12 +172,12 @@ static void login_client_failed(const struct master_login_client *client,
        }
 }
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
        if (master_login == NULL) {
                /* running standalone, we shouldn't even get here */
-               (void)close(conn->fd);
        } else {
+               master_service_client_connection_accept(conn);
                master_login_add(master_login, conn->fd);
        }
 }
index 25b0cc5c1ff9756bcf61eff9b4ba1e144ce633a4..76cd4b806033b3f5e5f63a6f8f055dfdee3890f2 100644 (file)
@@ -54,8 +54,9 @@ static void client_handle(int fd)
        }
 }
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
+       master_service_client_connection_accept(conn);
        if (ssl_params->used == 0) {
                /* waiting for parameter building to finish */
                if (!array_is_created(&delayed_fds))
index 881c1a70d09060313f99472c6090c905430e7dba..1787ec91211dc88fad9e7b0508e535afa8b6346c 100644 (file)
@@ -22,7 +22,7 @@
 static const char **exec_args;
 static bool drop_privileges = FALSE;
 
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
 {
        enum mail_storage_service_flags flags =
                MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS;
@@ -53,8 +53,6 @@ static void client_connected(const struct master_service_connection *conn)
                        i_fatal("read() failed: %m");
                else
                        i_fatal("read() failed: disconnected");
-               (void)close(conn->fd);
-               return;
        }
        if (fd == -1)
                i_fatal("client fd not received");
index b1d3d8db632b5ad6bf9a5bd8357c96113545f673..82414e1a5efe124a09d6b4495fbde739f18cb65e 100644 (file)
@@ -103,9 +103,10 @@ static void client_connected(const struct master_service_connection *conn)
 {
        if (tcpwrap_client != NULL) {
                i_error("tcpwrap must be configured with client_limit=1");
-               (void)close(conn->fd);
                return;
        }
+
+       master_service_client_connection_accept(conn);
        tcpwrap_client = tcpwrap_client_create(conn->fd);
 }