Skip to content

Use-after-free in DnsCacheManager after listener filter-chain replacement #46266

Description

@yanavlasov

Originally reported by @yueshangzuo

Summary

DnsCacheManagerImpl is a server-wide singleton that retains a non-owning stats-scope reference from its first caller. If that caller's listener filter chain is destroyed, a later cache miss dereferences the stale scope, causing a use-after-free that can crash Envoy.

Details

The manager's copied context preserves the caller's bare Stats::Scope&. Cache hits return directly, but a miss calls DnsCacheImpl::createDnsCacheImpl(); its constructor then calls:

context.scope().createScope("dns_cache.<name>.")

If the first caller's filter chain has already been destroyed, this dereferences the freed scope.

Tests using IsolatedStoreImpl can mask the bug because it retains strong references to child scopes. Production ThreadLocalStoreImpl tracks them weakly, so destroying the filter chain releases the scope.

Reproduction

A focused test using ThreadLocalStoreImpl:

  1. Create filter-chain scope A and instantiate the manager from its factory context.
  2. Create cache A.
  3. Destroy context A and scope A.
  4. Request cache B from a new caller, forcing a cache miss.

Before the fix, ASAN reports:

ERROR: AddressSanitizer: heap-use-after-free
    #0 Envoy::Stats::Scope::createScope(...)
    #1 DnsCacheImpl::DnsCacheImpl(...)
    #2 DnsCacheImpl::createDnsCacheImpl(...)
    #3 DnsCacheManagerImpl::getCache(...)
freed by thread T0 here:
    std::__shared_ptr_emplace<Stats::ThreadLocalStoreImpl::ScopeImpl>::__on_zero_shared_weak()

Impact

The issue can crash Envoy during dynamic listener updates; no request-only trigger has been identified.

Proposed fix

Bind DnsCacheManagerImpl and its DNS cache stats to server-lifetime state, eliminating references to caller-owned scopes. Metric names remain unchanged; the stats are now governed by the global stats matcher.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugtriageIssue requires triage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions