From: Azat Khuzhin Date: Tue, 13 Nov 2018 18:26:12 +0000 (+0300) Subject: Fix conceivable UAF of the bufferevent in evhttp_connection_free() X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5dc88b387f7baa4bcd528832e94987a85be3b263;p=libevent Fix conceivable UAF of the bufferevent in evhttp_connection_free() Although this is not a problem, since bufferevent uses finalizers and will free itself only from the loop (well this is not a problem if you do not play games with various event_base in different threads) it generates questions, so rewrite it in more reliable way. Fixes: #712 --- diff --git a/http.c b/http.c index cd3f2f05..27d3bd9e 100644 --- a/http.c +++ b/http.c @@ -1203,6 +1203,7 @@ void evhttp_connection_free(struct evhttp_connection *evcon) { struct evhttp_request *req; + int need_close = 0; /* notify interested parties that this connection is going down */ if (evcon->fd != -1) { @@ -1229,21 +1230,22 @@ evhttp_connection_free(struct evhttp_connection *evcon) event_debug_unassign(&evcon->retry_ev); } - if (evcon->bufev != NULL) - bufferevent_free(evcon->bufev); - event_deferred_cb_cancel_(get_deferred_queue(evcon), &evcon->read_more_deferred_cb); - if (evcon->fd == -1) - evcon->fd = bufferevent_getfd(evcon->bufev); + if (evcon->bufev != NULL) { + need_close = + !(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE); + if (evcon->fd == -1) + evcon->fd = bufferevent_getfd(evcon->bufev); + + bufferevent_free(evcon->bufev); + } if (evcon->fd != -1) { - bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE); shutdown(evcon->fd, EVUTIL_SHUT_WR); - if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) { + if (need_close) evutil_closesocket(evcon->fd); - } } if (evcon->bind_address != NULL)