Bug 34154 - Segfault in sock_eq after res_init() returns -1, due to stale _u._ext.nscount in __res_iclose
Summary: Segfault in sock_eq after res_init() returns -1, due to stale _u._ext.nscount...
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: network (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: 2.44
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2026-05-15 09:42 UTC by Adam Yi
Modified: 2026-06-03 14:12 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:


Attachments
Reproduction (214 bytes, text/x-csrc)
2026-05-15 09:42 UTC, Adam Yi
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Adam Yi 2026-05-15 09:42:59 UTC
Created attachment 16716 [details]
Reproduction

A failing res_init() call leaves the per-thread resolver state in an inconsistent condition where subsequent name lookups dereference NULL in resolv/res_send.c:sock_eq().

                Stack trace of thread 3646954:
                #0  0x00007fd845007ed7 sock_eq (libresolv.so.2)
                #1  0x00007fd845008bb7 __res_context_send (libresolv.so.2)
                #2  0x00007fd8450067dd __res_context_query (libresolv.so.2)
                #3  0x00007fd845006e76 __res_context_querydomain (libresolv.so.2)
                #4  0x00007fd8450076cd __res_context_search (libresolv.so.2)
                #5  0x00007fd8454023c0 gethostbyname3_context (libnss_dns.so.2)
                #6  0x00007fd845402ecf _nss_dns_gethostbyname_r (libnss_dns.so.2)
                #7  0x00007fd845d4f8a3 gethostbyname_r@@GLIBC_2.2.5 (libc.so.6)
                #8  0x00007fd845d4eeb7 gethostbyname (libc.so.6)
                #9  0x00000000004011a1 n/a (/home/ayi/res_init_repro)
                #10 0x00007fd845c3a925 __libc_start_main (libc.so.6)
                #11 0x000000000040109e n/a (/home/ayi/res_init_repro)

Root cause: in resolv/res-close.c, when __res_iclose is called with FREE_ADDR=true, it NULLs every statp->_u._ext.nsaddrs[ns] but does not modify statp->_u._ext.nscount. This breaks the invariant relied on by __res_context_send's cache validation loop (resolv/res_send.c:293-312): when _u._ext.nscount > 0, every _u._ext.nsaddrs[ns] corresponding to nsaddr_list[ns].sin_family != 0 is expected to be non-NULL. Normally, res_init would call __res_vinit right after __res_iclose but if __res_vinit fails (e.g. due to allocation failure, file-descriptor exhaustion), it would leave us in this bad state.

A minimal reproduction is attached here and I'll send in a patch shortly.
Comment 2 Adhemerval Zanella 2026-06-03 14:12:17 UTC
Fixed on 2.44.