nghttpx: Fix heap-use-after-free

The bug was introduced by 8c3b379b66.
This commit is contained in:
Tatsuhiro Tsujikawa 2015-04-08 13:43:57 +09:00
parent 8c3b379b66
commit e9660c3558
3 changed files with 27 additions and 2 deletions

View File

@ -405,7 +405,7 @@ ClientHandler::~ClientHandler() {
--worker_stat->num_connections; --worker_stat->num_connections;
if (worker_stat->num_connections == 0) { if (worker_stat->num_connections == 0) {
worker_->get_mcpool()->clear(); worker_->schedule_clear_mcpool();
} }
ev_timer_stop(conn_.loop, &reneg_shutdown_timer_); ev_timer_stop(conn_.loop, &reneg_shutdown_timer_);

View File

@ -46,6 +46,16 @@ void eventcb(struct ev_loop *loop, ev_async *w, int revents) {
} }
} // namespace } // namespace
namespace {
void mcpool_clear_cb(struct ev_loop *loop, ev_timer *w, int revents) {
auto worker = static_cast<Worker *>(w->data);
if (worker->get_worker_stat()->num_connections != 0) {
return;
}
worker->get_mcpool()->clear();
}
} // namespace
Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx, Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
ssl::CertLookupTree *cert_tree, ssl::CertLookupTree *cert_tree,
const std::shared_ptr<TicketKeys> &ticket_keys) const std::shared_ptr<TicketKeys> &ticket_keys)
@ -57,6 +67,9 @@ Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
w_.data = this; w_.data = this;
ev_async_start(loop_, &w_); ev_async_start(loop_, &w_);
ev_timer_init(&mcpool_clear_timer_, mcpool_clear_cb, 0., 0.);
mcpool_clear_timer_.data = this;
if (get_config()->downstream_proto == PROTO_HTTP2) { if (get_config()->downstream_proto == PROTO_HTTP2) {
auto n = get_config()->http2_downstream_connections_per_worker; auto n = get_config()->http2_downstream_connections_per_worker;
for (; n > 0; --n) { for (; n > 0; --n) {
@ -66,7 +79,17 @@ Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
} }
} }
Worker::~Worker() { ev_async_stop(loop_, &w_); } Worker::~Worker() {
ev_async_stop(loop_, &w_);
ev_timer_stop(loop_, &mcpool_clear_timer_);
}
void Worker::schedule_clear_mcpool() {
// libev manual says: "If the watcher is already active nothing will
// happen." Since we don't change any timeout here, we don't have
// to worry about querying ev_is_active.
ev_timer_start(loop_, &mcpool_clear_timer_);
}
void Worker::wait() { void Worker::wait() {
#ifndef NOTHREADS #ifndef NOTHREADS

View File

@ -108,6 +108,7 @@ public:
bool get_graceful_shutdown() const; bool get_graceful_shutdown() const;
MemchunkPool *get_mcpool(); MemchunkPool *get_mcpool();
void schedule_clear_mcpool();
private: private:
std::vector<std::unique_ptr<Http2Session>> http2sessions_; std::vector<std::unique_ptr<Http2Session>> http2sessions_;
@ -118,6 +119,7 @@ private:
std::mutex m_; std::mutex m_;
std::deque<WorkerEvent> q_; std::deque<WorkerEvent> q_;
ev_async w_; ev_async w_;
ev_timer mcpool_clear_timer_;
MemchunkPool mcpool_; MemchunkPool mcpool_;
DownstreamConnectionPool dconn_pool_; DownstreamConnectionPool dconn_pool_;
WorkerStat worker_stat_; WorkerStat worker_stat_;