Skip to content

Commit

Permalink
test: fix heap use-after-free in ~IntegrationTestServer. (envoyproxy#…
Browse files Browse the repository at this point in the history
…4319)

When the server thread exits independently of the main test thread (e.g. exception catch), we
could race on the access to the server admin port via server_. We latch this in this PR to avoid
unsafe behavior. We might still have a stale address, but the request should then fail or timeout.

Fixes oss-fuzz issues https://oss-fuzz.com/v2/testcase-detail/5719024990683136 and
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10027.

Risk level: Low
Testing: TSAN integration tests.

Signed-off-by: Harvey Tuch <htuch@google.com>
  • Loading branch information
htuch authored Sep 4, 2018
1 parent cddc732 commit 0a1e92a
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 5 deletions.
15 changes: 10 additions & 5 deletions test/integration/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,12 @@ void IntegrationTestServer::start(const Network::Address::IpVersion version,
IntegrationTestServer::~IntegrationTestServer() {
ENVOY_LOG(info, "stopping integration test server");

BufferingStreamDecoderPtr response =
IntegrationUtil::makeSingleRequest(server_->admin().socket().localAddress(), "POST",
"/quitquitquit", "", Http::CodecClient::Type::HTTP1);
EXPECT_TRUE(response->complete());
EXPECT_STREQ("200", response->headers().Status()->value().c_str());
if (admin_address_ != nullptr) {
BufferingStreamDecoderPtr response = IntegrationUtil::makeSingleRequest(
admin_address_, "POST", "/quitquitquit", "", Http::CodecClient::Type::HTTP1);
EXPECT_TRUE(response->complete());
EXPECT_STREQ("200", response->headers().Status()->value().c_str());
}

thread_->join();
}
Expand Down Expand Up @@ -107,6 +108,10 @@ void IntegrationTestServer::threadRoutine(const Network::Address::IpVersion vers
restarter, stats_store, lock, *this, std::move(random_generator), tls));
pending_listeners_ = server_->listenerManager().listeners().size();
ENVOY_LOG(info, "waiting for {} test server listeners", pending_listeners_);
// This is technically thread unsafe (assigning to a shared_ptr accessed
// across threads), but because we synchronize below on server_set, the only
// consumer on the main test thread in ~IntegrationTestServer will not race.
admin_address_ = server_->admin().socket().localAddress();
server_set_.setReady();
server_->run();
server_.reset();
Expand Down
1 change: 1 addition & 0 deletions test/integration/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ class IntegrationTestServer : Logger::Loggable<Logger::Id::testing>,
Stats::Store* stat_store_{};
std::function<void()> on_worker_listener_added_cb_;
std::function<void()> on_worker_listener_removed_cb_;
Network::Address::InstanceConstSharedPtr admin_address_;
};

} // namespace Envoy

0 comments on commit 0a1e92a

Please sign in to comment.