Bug 2373046 (CVE-2025-48945, GHSA-5qpg-rh4j-qp35)
| Summary: | CVE-2025-48945 pycares: pycares Channel Use-After-Free | ||
|---|---|---|---|
| Product: | [Other] Security Response | Reporter: | OSIDB Bzimport <bzimport> |
| Component: | vulnerability | Assignee: | Product Security DevOps Team <prodsec-dev> |
| Status: | NEW --- | QA Contact: | |
| Severity: | medium | Docs Contact: | |
| Priority: | medium | ||
| Version: | unspecified | CC: | anthomas, dranck, ehelms, ggainey, haoli, hkataria, jajackso, jcammara, jmitchel, jneedle, jtanner, juwatts, kegrant, koliveir, kshier, lbrazdil, mabashia, mhulan, mminar, nmoumoul, osousa, pbraun, pcreech, rbiba, rchan, shvarugh, simaishi, smallamp, smcdonal, sskracic, stcannon, teagle, tfister, thavo, tpfromme, yguenane |
| Target Milestone: | --- | Keywords: | Security |
| Target Release: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | --- | |
| Doc Text: |
A flaw was found in pycares. A use-after-free condition arises when a Channel object is garbage collected while associated DNS queries remain pending, leading to a fatal Python error and interpreter crash. This vulnerability allows a local attacker to trigger the crash by initiating DNS queries and then manipulating the object lifetime. This condition causes a denial of service resulting from interpreter termination.
|
Story Points: | --- |
| Clone Of: | Environment: | ||
| Last Closed: | Type: | --- | |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | 2373112 | ||
| Bug Blocks: | |||
## Summary pycares is vulnerable to a use-after-free condition that occurs when a Channel object is garbage collected while DNS queries are still pending. This results in a fatal Python error and interpreter crash. ## Details ### Root Cause The vulnerability stems from improper handling of callback references when the Channel object is destroyed: 1. When a DNS query is initiated, pycares stores a callback reference using `ffi.new_handle()` 2. If the Channel object is garbage collected while queries are pending, the callback references become invalid 3. When c-ares attempts to invoke the callback, it accesses freed memory, causing a fatal error This issue was much more likely to occur when using `event_thread=True` but could happen without it under the right circumstances. ### Technical Details The core issue is a race condition between Python's garbage collector and c-ares's callback execution: 1. When `__del__` is called from within a c-ares callback context, we cannot immediately call `ares_destroy()` because c-ares is still executing code after the callback returns 2. c-ares needs to execute cleanup code after our Python callback returns (specifically at lines 1422-1429 in ares_process.c) 3. If we destroy the channel too quickly, c-ares accesses freed memory ### Impact Applications using `pycares` can be crashed remotely by triggering DNS queries that result in `Channel` objects being garbage collected before query completion. This is particularly problematic in scenarios where: - Channel objects are created per-request - Multiple failed DNS queries are processed rapidly - The application doesn't properly manage Channel lifecycle The error manifests as: ``` Fatal Python error: b_from_handle: ffi.from_handle() detected that the address passed points to garbage ``` ## Fix The vulnerability has been fixed in pycares 4.9.0 by implementing a safe channel destruction mechanism ## Mitigation ### For Application Developers 1. **Upgrade to pycares >= 4.9.0** - This version includes the fix and requires no code changes 2. **Best practices** (optional but recommended): ```python # Explicit cleanup channel.close() # Or use context manager with pycares.Channel() as channel: # ... use channel ... # Automatically closed ``` 3. **Avoid creating Channel objects per-request** - Prefer long-lived instances for better performance and safety The fix is completely transparent - no API changes or code modifications are required. ## Credit This vulnerability was reported by @vEpiphyte through the aio-libs security program.