- Package:
- libnss-mdns
- Source:
- libnss-mdns
- Description:
- NSS module for Multicast DNS name resolution
- Submitter:
- 황병주
- Date:
- 2026-02-07 10:53:04 UTC
- Severity:
- normal
- Tags:
mDNS name resolution via libnss-mdns is completely broken on Debian trixie with glibc 2.41. The NSS module is loaded but never called, causing .local hostnames to fall through to DNS instead of being resolved via mDNS. ** Background ** glibc 2.41 changed NSS module loading to resolve all possible NSS function symbols at load time (not just the ones relevant to the requested database). Since libnss-mdns only provides hosts-related functions, glibc fails to find symbols like _nss_mdns4_minimal_getpwnam_r, _nss_mdns4_minimal_getgrent_r, etc., and marks every missing symbol as "fatal". As a result, the module is effectively treated as UNAVAIL, and the [NOTFOUND=return] directive in nsswitch.conf is never triggered. ** Steps to reproduce ** 1. Install libnss-mdns and avahi-daemon on Debian trixie (glibc 2.41). 2. Ensure /etc/nsswitch.conf contains: hosts: files mdns4_minimal [NOTFOUND=return] dns 3. Have another host advertising via mDNS on the local network. 4. Run: getent hosts <hostname>.local ** Expected result ** The .local hostname is resolved via mDNS (e.g., 192.168.0.25). ** Actual result ** The hostname is resolved via DNS, returning an incorrect address (in my case, an ISP DNS hijacking address 218.38.137.27 instead of 192.168.0.25). ** Diagnosis ** avahi-daemon and the avahi socket work correctly: $ avahi-resolve -4 -n pluto.local pluto.local 192.168.0.25 $ echo "RESOLVE-HOSTNAME-IPV4 pluto.local" | nc -U /run/avahi-daemon/socket + 2 0 pluto.local 192.168.0.25 But NSS-based resolution bypasses mDNS entirely: $ getent hosts pluto.local 218.38.137.27 pluto.local strace confirms the .so files are loaded but no avahi socket connection is attempted — the process goes straight to DNS: $ strace -e trace=openat,connect getent hosts pluto.local (opens libnss_mdns4_minimal.so.2 successfully) (opens libnss_mdns6_minimal.so.2 successfully) (no AF_UNIX connect to /run/avahi-daemon/socket) (connects to DNS server on port 53) LD_DEBUG reveals the root cause — glibc tries to resolve all NSS functions and marks each missing one as fatal: $ LD_DEBUG=symbols getent hosts pluto.local 2>&1 | grep fatal | head -5 symbol=_nss_mdns4_minimal_endaliasent; ... undefined symbol (fatal) symbol=_nss_mdns4_minimal_endetherent; ... undefined symbol (fatal) symbol=_nss_mdns4_minimal_endgrent; ... undefined symbol (fatal) symbol=_nss_mdns4_minimal_endhostent; ... undefined symbol (fatal) symbol=_nss_mdns4_minimal_endnetent; ... undefined symbol (fatal) The library only exports hosts-related symbols, which is expected: $ nm -D /lib/x86_64-linux-gnu/libnss_mdns4_minimal.so.2 | grep ' T ' _nss_mdns4_minimal_gethostbyaddr_r _nss_mdns4_minimal_gethostbyname2_r _nss_mdns4_minimal_gethostbyname3_r _nss_mdns4_minimal_gethostbyname4_r _nss_mdns4_minimal_gethostbyname_r Note: The same libnss-mdns version works correctly on Ubuntu 24.04 which ships glibc 2.39, confirming that this is a glibc 2.41 compatibility issue. ** Possible fix ** Either libnss-mdns needs to be rebuilt/patched to be compatible with glibc 2.41's new module loading behavior, or this may need to be addressed on the glibc side as a backward compatibility regression. I'm filing against libnss-mdns first, but please reassign to glibc if appropriate.
Control: retitle -1 libnss-mdns: DNS tried before mDNS despite configuration for mdns4_minimal first
Control: tags -1 + moreinfo
I was unable to reproduce this on a trixie machine.
Steps:
1. Install libnss-mdns and avahi-daemon on Debian trixie (glibc 2.41)
. Have another host ($OTHER) with mDNS, on the same network
3. Edit /etc/nsswitch.conf to contain:
hosts: files dns
4. getent hosts $OTHER.local; echo $? -> no output, exit status 2
5. Edit /etc/nsswitch.conf to contain:
hosts: files mdns4_minimal [NOTFOUND=return] dns
6. getent hosts $OTHER.local; echo $? -> resolved, exit status 0
But, something that I *do* observe in this configuration is that a
strace'd getent process does a connect() to my DNS server (in my case
it's systemd-resolved) *before* connecting to the Avahi socket:
$ strace -e openat,connect getent hosts remnant.local
...
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_mdns4_minimal.so.2", O_RDONLY|O_CLOEXEC) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 0
openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 0
connect(3, {sa_family=AF_FILE, path="/run/avahi-daemon/socket"}, 110) = 0
REDACTED remnant.local
I think that could result in the same symptom that you reported, where an
ISP DNS server that (inappropriately) intercepts resolution of .local
names results in the ISP's DNS resolution being used before
mdns4_minimal gets an opportunity to step in.
I wonder whether this means that glibc is doing multiple lower-level NSS
lookups for a single higher-level getent operation, only some of which
are of a form implemented by mdns4_minimal, and as a result DNS
effectively takes precedence over mDNS even though the configuration
says the opposite?
really mean it. I think this should be read as "fatal to this particular
attempt to resolve the symbol", and not as "fatal to any attempt to look
up NSS".
smcv