Skip to content

Commit 5a92867

Browse files
andrewjjenkinsmattklein123
authored andcommitted
upstream: Null-deref on TCP health checker if setsockopt fails (#6793)
Signed-off-by: Andrew Jenkins <[email protected]>
1 parent 11c9502 commit 5a92867

File tree

4 files changed

+254
-84
lines changed

4 files changed

+254
-84
lines changed

source/common/upstream/health_checker_impl.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ TcpHealthCheckerImpl::TcpActiveHealthCheckSession::~TcpActiveHealthCheckSession(
360360

361361
void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onDeferredDelete() {
362362
if (client_) {
363+
expect_close_ = true;
363364
client_->close(Network::ConnectionCloseType::NoFlush);
364365
}
365366
}
@@ -371,6 +372,7 @@ void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onData(Buffer::Instance&
371372
data.drain(data.length());
372373
handleSuccess(false);
373374
if (!parent_.reuse_connection_) {
375+
expect_close_ = true;
374376
client_->close(Network::ConnectionCloseType::NoFlush);
375377
}
376378
} else {
@@ -379,12 +381,11 @@ void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onData(Buffer::Instance&
379381
}
380382

381383
void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onEvent(Network::ConnectionEvent event) {
382-
if (event == Network::ConnectionEvent::RemoteClose) {
383-
handleFailure(envoy::data::core::v2alpha::HealthCheckFailureType::NETWORK);
384-
}
385-
386384
if (event == Network::ConnectionEvent::RemoteClose ||
387385
event == Network::ConnectionEvent::LocalClose) {
386+
if (!expect_close_) {
387+
handleFailure(envoy::data::core::v2alpha::HealthCheckFailureType::NETWORK);
388+
}
388389
parent_.dispatcher_.deferredDelete(std::move(client_));
389390
}
390391

@@ -403,6 +404,7 @@ void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onEvent(Network::Connect
403404
// TODO(mattklein123): In the case that a user configured bytes to write, they will not be
404405
// be written, since we currently have no way to know if the bytes actually get written via
405406
// the connection interface. We might want to figure out how to handle this better later.
407+
expect_close_ = true;
406408
client_->close(Network::ConnectionCloseType::NoFlush);
407409
handleSuccess(false);
408410
}
@@ -416,6 +418,7 @@ void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onInterval() {
416418
client_->addConnectionCallbacks(*session_callbacks_);
417419
client_->addReadFilter(session_callbacks_);
418420

421+
expect_close_ = false;
419422
client_->connect();
420423
client_->noDelay(true);
421424
}
@@ -431,6 +434,7 @@ void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onInterval() {
431434
}
432435

433436
void TcpHealthCheckerImpl::TcpActiveHealthCheckSession::onTimeout() {
437+
expect_close_ = true;
434438
host_->setActiveHealthFailureType(Host::ActiveHealthFailureType::TIMEOUT);
435439
client_->close(Network::ConnectionCloseType::NoFlush);
436440
}

source/common/upstream/health_checker_impl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ class TcpHealthCheckerImpl : public HealthCheckerImplBase {
252252
TcpHealthCheckerImpl& parent_;
253253
Network::ClientConnectionPtr client_;
254254
std::shared_ptr<TcpSessionCallbacks> session_callbacks_;
255+
// If true, stream close was initiated by us, not e.g. remote close or TCP reset.
256+
// In this case healthcheck status already reported, only state cleanup required.
257+
bool expect_close_{};
255258
};
256259

257260
typedef std::unique_ptr<TcpActiveHealthCheckSession> TcpActiveHealthCheckSessionPtr;

0 commit comments

Comments
 (0)