From 222a33cb84a2e52ad55a88900b7895bf9dd0262c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bonicoli Date: Sat, 7 Jan 2012 11:41:02 +0100 Subject: [PATCH] Buffer Overflow: check against the implicit size of select() arrays Reported by Julien Tinnes (Fix #269) exit is called when the listening socket can not be created --- src/bip.c | 2 +- src/connection.c | 46 ++++++++++++++++++++++++++++++++++++++-------- src/irc.c | 7 ++++--- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/bip.c b/src/bip.c index d46ee2b..b4ac706 100644 --- a/src/bip.c +++ b/src/bip.c @@ -1311,7 +1311,7 @@ int main(int argc, char **argv) close(fd); bip.listener = listen_new(conf_ip, conf_port, conf_css); - if (!bip.listener) + if (!bip.listener || bip.listener->connected == CONN_ERROR) fatal("Could not create listening socket"); for (;;) { diff --git a/src/connection.c b/src/connection.c index 07ab431..5c4c24a 100644 --- a/src/connection.c +++ b/src/connection.c @@ -124,6 +124,18 @@ static void connect_trynext(connection_t *cn) continue; } + if (cn->handle >= FD_SETSIZE) { + mylog(LOG_WARN, "too many fd used, close socket %d", + cn->handle); + + if (close(cn->handle) == -1) + mylog(LOG_WARN, "Error on socket close: %s", + strerror(errno)); + + cn->handle = -1; + break; + } + socket_set_nonblock(cn->handle); if (cn->connecting_data->src) { @@ -789,13 +801,8 @@ list_t *wait_event(list_t *cn_list, int *msec, int *nc) /* * This shouldn't happen ! just in case... */ - if (cn->handle < 0) { - mylog(LOG_WARN, "wait_event invalid socket %d", - cn->handle); - if (cn_is_connected(cn)) - cn->connected = CONN_ERROR; - continue; - } + if (cn->handle < 0 || cn->handle >= FD_SETSIZE) + fatal("wait_event invalid socket %d", cn->handle); /* exceptions are OOB and disconnections */ FD_SET(cn->handle, &fds_except); @@ -966,6 +973,18 @@ static void create_listening_socket(char *hostname, char *port, continue; } + if (cn->handle >= FD_SETSIZE) { + mylog(LOG_WARN, "too many fd used, close listening socket %d", + cn->handle); + + if (close(cn->handle) == -1) + mylog(LOG_WARN, "Error on socket close: %s", + strerror(errno)); + + cn->handle = -1; + break; + } + if (setsockopt(cn->handle, SOL_SOCKET, SO_REUSEADDR, (char *)&multi_client, sizeof(multi_client)) < 0) { @@ -1113,10 +1132,21 @@ connection_t *accept_new(connection_t *cn) mylog(LOG_DEBUG, "Trying to accept new client on %d", cn->handle); err = accept(cn->handle, &sa, &sa_len); + if (err < 0) { - mylog(LOG_ERROR, "accept failed: %s", strerror(errno)); + fatal("accept failed: %s", strerror(errno)); + } + + if (err >= FD_SETSIZE) { + mylog(LOG_WARN, "too many client connected, close %d", err); + + if (close(err) == -1) + mylog(LOG_WARN, "Error on socket close: %s", + strerror(errno)); + return NULL; } + socket_set_nonblock(err); conn = connection_init(cn->anti_flood, cn->ssl, cn->timeout, 0); diff --git a/src/irc.c b/src/irc.c index ebc1b34..147a315 100644 --- a/src/irc.c +++ b/src/irc.c @@ -2439,9 +2439,10 @@ void bip_on_event(bip_t *bip, connection_t *conn) if (conn == bip->listener) { struct link_client *n = irc_accept_new(conn); - assert(n); - list_add_last(&bip->conn_list, CONN(n)); - list_add_last(&bip->connecting_client_list, n); + if (n) { + list_add_last(&bip->conn_list, CONN(n)); + list_add_last(&bip->connecting_client_list, n); + } return; }