Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/1.26] repo: Release v1.26.7 #32220

Merged
merged 6 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.26.7-dev
1.26.7
34 changes: 19 additions & 15 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
date: Pending

behavior_changes:
# *Changes that are expected to cause an incompatibility if applicable; deployment changes are likely required*

minor_behavior_changes:
# *Changes that may cause incompatibilities for some users, but should not for most*
date: February 9, 2024

bug_fixes:
# *Changes expected to improve the state of the world and are unlikely to have negative effects*
- area: buffer
change: |
Fixed a bug (https://github.com/envoyproxy/envoy/issues/28760) that the internal listener causes an undefined
behavior due to the unintended release of the buffer memory.
- area: http
change: |
Fixed recursion when HTTP connection is disconnected due to a high number of premature resets.

removed_config_or_runtime:
# *Normally occurs at the end of the* :ref:`deprecation period <deprecated>`

new_features:

deprecated:
- area: proxy protocol
change: |
fixed a crash when Envoy is configured for PROXY protocol on both a listener and cluster, and the listener receives
a PROXY protocol header with address type LOCAL (typically used for health checks).
- area: proxy_protocol
change: |
Fix crash due to uncaught exception when the operating system does not support an address type (such as IPv6) that is
received in a proxy protocol header. Connections will instead be dropped/reset.
- area: proxy_protocol
change: |
Fixed a bug where TLVs with non utf8 characters were inserted as protobuf values into filter metadata circumventing
ext_authz checks when ``failure_mode_allow`` is set to ``true``.
- area: http
change: |
Fixed crash when HTTP request idle and per try timeouts occurs within backoff interval.
- area: url matching
change: |
Fixed excessive CPU utilization when using regex URL template matcher.
Binary file modified docs/inventories/v1.26/objects.inv
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/versions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@
"1.23": 1.23.12
"1.24": 1.24.12
"1.25": 1.25.11
"1.26": 1.26.5
"1.26": 1.26.6
1 change: 1 addition & 0 deletions source/common/network/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ envoy_cc_library(
":socket_interface_lib",
"//envoy/network:address_interface",
"//source/common/common:assert_lib",
"//source/common/common:cleanup_lib",
"//source/common/common:safe_memcpy_lib",
"//source/common/common:statusor_lib",
"//source/common/common:thread_lib",
Expand Down
24 changes: 22 additions & 2 deletions source/common/network/address_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,19 @@ std::string Ipv4Instance::sockaddrToString(const sockaddr_in& addr) {
return std::string(start, str + BufferSize - start);
}

namespace {
bool force_ipv4_unsupported_for_test = false;
}

Cleanup Ipv4Instance::forceProtocolUnsupportedForTest(bool new_val) {
bool old_val = force_ipv4_unsupported_for_test;
force_ipv4_unsupported_for_test = new_val;
return Cleanup([old_val]() { force_ipv4_unsupported_for_test = old_val; });
}

absl::Status Ipv4Instance::validateProtocolSupported() {
static const bool supported = SocketInterfaceSingleton::get().ipFamilySupported(AF_INET);
if (supported) {
if (supported && !force_ipv4_unsupported_for_test) {
return absl::OkStatus();
}
return absl::FailedPreconditionError("IPv4 addresses are not supported on this machine");
Expand Down Expand Up @@ -323,9 +333,19 @@ Ipv6Instance::Ipv6Instance(absl::Status& status, const sockaddr_in6& address, bo
initHelper(address, v6only);
}

namespace {
bool force_ipv6_unsupported_for_test = false;
}

Cleanup Ipv6Instance::forceProtocolUnsupportedForTest(bool new_val) {
bool old_val = force_ipv6_unsupported_for_test;
force_ipv6_unsupported_for_test = new_val;
return Cleanup([old_val]() { force_ipv6_unsupported_for_test = old_val; });
}

absl::Status Ipv6Instance::validateProtocolSupported() {
static const bool supported = SocketInterfaceSingleton::get().ipFamilySupported(AF_INET6);
if (supported) {
if (supported && !force_ipv6_unsupported_for_test) {
return absl::OkStatus();
}
return absl::FailedPreconditionError("IPv6 addresses are not supported on this machine");
Expand Down
13 changes: 13 additions & 0 deletions source/common/network/address_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "envoy/network/socket.h"

#include "source/common/common/assert.h"
#include "source/common/common/cleanup.h"
#include "source/common/common/statusor.h"

namespace Envoy {
Expand Down Expand Up @@ -144,6 +145,12 @@ class Ipv4Instance : public InstanceBase {
// given address if not.
static absl::Status validateProtocolSupported();

/**
* For use in tests only.
* Force validateProtocolSupported() to return false for IPv4.
*/
static Envoy::Cleanup forceProtocolUnsupportedForTest(bool new_val);

private:
/**
* Construct from an existing unix IPv4 socket address (IP v4 address and port).
Expand Down Expand Up @@ -226,6 +233,12 @@ class Ipv6Instance : public InstanceBase {
// Validate that IPv6 is supported on this platform
static absl::Status validateProtocolSupported();

/**
* For use in tests only.
* Force validateProtocolSupported() to return false for IPv6.
*/
static Envoy::Cleanup forceProtocolUnsupportedForTest(bool new_val);

private:
/**
* Construct from an existing unix IPv6 socket address (IP v6 address and port).
Expand Down
1 change: 1 addition & 0 deletions source/common/router/router.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,7 @@ void Filter::onResponseTimeout() {
// Called when the per try timeout is hit but we didn't reset the request
// (hedge_on_per_try_timeout enabled).
void Filter::onSoftPerTryTimeout(UpstreamRequest& upstream_request) {
ASSERT(!upstream_request.retried());
// Track this as a timeout for outlier detection purposes even though we didn't
// cancel the request yet and might get a 2xx later.
updateOutlierDetection(Upstream::Outlier::Result::LocalOriginTimeout, upstream_request,
Expand Down
9 changes: 9 additions & 0 deletions source/common/router/upstream_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -591,11 +591,20 @@ void UpstreamRequest::setupPerTryTimeout() {

void UpstreamRequest::onPerTryIdleTimeout() {
ENVOY_STREAM_LOG(debug, "upstream per try idle timeout", *parent_.callbacks());
if (per_try_timeout_) {
// Disable the per try idle timer, so it does not trigger further retries
per_try_timeout_->disableTimer();
}
stream_info_.setResponseFlag(StreamInfo::ResponseFlag::StreamIdleTimeout);
parent_.onPerTryIdleTimeout(*this);
}

void UpstreamRequest::onPerTryTimeout() {
if (per_try_idle_timeout_) {
// Delete the per try idle timer, so it does not trigger further retries.
// The timer has to be deleted to prevent data flow from re-arming it.
per_try_idle_timeout_.reset();
}
// If we've sent anything downstream, ignore the per try timeout and let the response continue
// up to the global timeout
if (!parent_.downstreamResponseStarted()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ bool generateV2Header(const Network::ProxyProtocolData& proxy_proto_data, Buffer
}

ASSERT(extension_length <= std::numeric_limits<uint16_t>::max());
if (proxy_proto_data.src_addr_ == nullptr || proxy_proto_data.src_addr_->ip() == nullptr) {
IS_ENVOY_BUG("Missing or incorrect source IP in proxy_proto_data_");
return false;
}
if (proxy_proto_data.dst_addr_ == nullptr || proxy_proto_data.dst_addr_->ip() == nullptr) {
IS_ENVOY_BUG("Missing or incorrect dest IP in proxy_proto_data_");
return false;
}

const auto& src = *proxy_proto_data.src_addr_->ip();
const auto& dst = *proxy_proto_data.dst_addr_->ip();
generateV2Header(src.addressAsString(), dst.addressAsString(), src.port(), dst.port(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "source/common/network/address_impl.h"
#include "source/common/network/proxy_protocol_filter_state.h"
#include "source/common/network/utility.h"
#include "source/common/protobuf/utility.h"
#include "source/extensions/common/proxy_protocol/proxy_protocol_header.h"

using envoy::config::core::v3::ProxyProtocolPassThroughTLVs;
Expand Down Expand Up @@ -144,24 +145,37 @@ ReadOrParseState Filter::parseBuffer(Network::ListenerFilterBuffer& buffer) {
if (proxy_protocol_header_.has_value() &&
!cb_->filterState().hasData<Network::ProxyProtocolFilterState>(
Network::ProxyProtocolFilterState::key())) {
if (!proxy_protocol_header_.value().local_command_) {
auto buf = reinterpret_cast<const uint8_t*>(buffer.rawSlice().mem_);
auto buf = reinterpret_cast<const uint8_t*>(buffer.rawSlice().mem_);
if (proxy_protocol_header_.value().local_command_) {
ENVOY_LOG(trace, "Parsed proxy protocol header, cmd: LOCAL, length: {}, buffer: {}",
proxy_protocol_header_.value().wholeHeaderLength(),
Envoy::Hex::encode(buf, proxy_protocol_header_.value().wholeHeaderLength()));

cb_->filterState().setData(
Network::ProxyProtocolFilterState::key(),
std::make_unique<Network::ProxyProtocolFilterState>(Network::ProxyProtocolData{
socket.connectionInfoProvider().remoteAddress(),
socket.connectionInfoProvider().localAddress(), parsed_tlvs_}),
StreamInfo::FilterState::StateType::Mutable,
StreamInfo::FilterState::LifeSpan::Connection);
} else {
ENVOY_LOG(
trace,
"Parsed proxy protocol header, length: {}, buffer: {}, TLV length: {}, TLV buffer: {}",
"Parsed proxy protocol header, cmd: PROXY, length: {}, buffer: {}, TLV length: {}, TLV "
"buffer: {}",
proxy_protocol_header_.value().wholeHeaderLength(),
Envoy::Hex::encode(buf, proxy_protocol_header_.value().wholeHeaderLength()),
proxy_protocol_header_.value().extensions_length_,
Envoy::Hex::encode(buf + proxy_protocol_header_.value().headerLengthWithoutExtension(),
proxy_protocol_header_.value().extensions_length_));
cb_->filterState().setData(
Network::ProxyProtocolFilterState::key(),
std::make_unique<Network::ProxyProtocolFilterState>(Network::ProxyProtocolData{
proxy_protocol_header_.value().remote_address_,
proxy_protocol_header_.value().local_address_, parsed_tlvs_}),
StreamInfo::FilterState::StateType::Mutable,
StreamInfo::FilterState::LifeSpan::Connection);
}

cb_->filterState().setData(
Network::ProxyProtocolFilterState::key(),
std::make_unique<Network::ProxyProtocolFilterState>(Network::ProxyProtocolData{
proxy_protocol_header_.value().remote_address_,
proxy_protocol_header_.value().local_address_, parsed_tlvs_}),
StreamInfo::FilterState::StateType::Mutable, StreamInfo::FilterState::LifeSpan::Connection);
}

if (proxy_protocol_header_.has_value() && !proxy_protocol_header_.value().local_command_) {
Expand Down Expand Up @@ -263,11 +277,20 @@ bool Filter::parseV2Header(const char* buf) {
la4.sin_family = AF_INET;
la4.sin_port = v4->dst_port;
la4.sin_addr.s_addr = v4->dst_addr;
proxy_protocol_header_.emplace(
WireHeader{PROXY_PROTO_V2_HEADER_LEN, hdr_addr_len, PROXY_PROTO_V2_ADDR_LEN_INET,
hdr_addr_len - PROXY_PROTO_V2_ADDR_LEN_INET, Network::Address::IpVersion::v4,
std::make_shared<Network::Address::Ipv4Instance>(&ra4),
std::make_shared<Network::Address::Ipv4Instance>(&la4)});

try {
// TODO(ggreenway): make this work without requiring operating system support for an
// address family.
proxy_protocol_header_.emplace(WireHeader{
PROXY_PROTO_V2_HEADER_LEN, hdr_addr_len, PROXY_PROTO_V2_ADDR_LEN_INET,
hdr_addr_len - PROXY_PROTO_V2_ADDR_LEN_INET, Network::Address::IpVersion::v4,
std::make_shared<Network::Address::Ipv4Instance>(&ra4),
std::make_shared<Network::Address::Ipv4Instance>(&la4)});
} catch (const EnvoyException& e) {
ENVOY_LOG(debug, "Proxy protocol failure: {}", e.what());
return false;
}

return true;
} else if (((proto_family & 0xf0) >> 4) == PROXY_PROTO_V2_AF_INET6) {
PACKED_STRUCT(struct pp_ipv6_addr {
Expand All @@ -289,11 +312,18 @@ bool Filter::parseV2Header(const char* buf) {
la6.sin6_port = v6->dst_port;
safeMemcpy(&(la6.sin6_addr.s6_addr), &(v6->dst_addr));

proxy_protocol_header_.emplace(WireHeader{
PROXY_PROTO_V2_HEADER_LEN, hdr_addr_len, PROXY_PROTO_V2_ADDR_LEN_INET6,
hdr_addr_len - PROXY_PROTO_V2_ADDR_LEN_INET6, Network::Address::IpVersion::v6,
std::make_shared<Network::Address::Ipv6Instance>(ra6),
std::make_shared<Network::Address::Ipv6Instance>(la6)});
try {
proxy_protocol_header_.emplace(WireHeader{
PROXY_PROTO_V2_HEADER_LEN, hdr_addr_len, PROXY_PROTO_V2_ADDR_LEN_INET6,
hdr_addr_len - PROXY_PROTO_V2_ADDR_LEN_INET6, Network::Address::IpVersion::v6,
std::make_shared<Network::Address::Ipv6Instance>(ra6),
std::make_shared<Network::Address::Ipv6Instance>(la6)});
} catch (const EnvoyException& e) {
// TODO(ggreenway): make this work without requiring operating system support for an
// address family.
ENVOY_LOG(debug, "Proxy protocol failure: {}", e.what());
return false;
}
return true;
}
}
Expand Down Expand Up @@ -409,7 +439,9 @@ bool Filter::parseTlvs(const uint8_t* buf, size_t len) {
auto key_value_pair = config_->isTlvTypeNeeded(tlv_type);
if (nullptr != key_value_pair) {
ProtobufWkt::Value metadata_value;
metadata_value.set_string_value(tlv_value.data(), tlv_value.size());
// Sanitize any non utf8 characters.
auto sanitised_tlv_value = MessageUtil::sanitizeUtf8String(tlv_value);
metadata_value.set_string_value(sanitised_tlv_value.data(), sanitised_tlv_value.size());

std::string metadata_key = key_value_pair->metadata_namespace().empty()
? "envoy.filters.listener.proxy_protocol"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ namespace UriTemplate {
namespace Match {

bool UriTemplateMatcher::match(absl::string_view path) const {
RE2 matching_pattern_regex = RE2(convertPathPatternSyntaxToRegex(path_template_).value());
return RE2::FullMatch(Internal::toStringPiece(Http::PathUtil::removeQueryAndFragment(path)),
matching_pattern_regex);
matching_pattern_regex_);
}

absl::string_view UriTemplateMatcher::uriTemplate() const { return path_template_; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class UriTemplateMatcher : public Router::PathMatcher {
public:
explicit UriTemplateMatcher(
const envoy::extensions::path::match::uri_template::v3::UriTemplateMatchConfig& config)
: path_template_(config.path_template()) {}
: path_template_(config.path_template()),
matching_pattern_regex_(convertPathPatternSyntaxToRegex(path_template_).value()) {}

// Router::PathMatcher
bool match(absl::string_view path) const override;
Expand All @@ -38,6 +39,7 @@ class UriTemplateMatcher : public Router::PathMatcher {

private:
const std::string path_template_;
const RE2 matching_pattern_regex_;
};

} // namespace Match
Expand Down
Loading
Loading