resolver failures without even sending queries, break Postfix
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
GLibC |
Fix Released
|
Critical
|
|||
eglibc (Ubuntu) |
Fix Released
|
Undecided
|
Unassigned | ||
Lucid |
Fix Released
|
Undecided
|
Unassigned | ||
Maverick |
Invalid
|
Undecided
|
Unassigned | ||
Natty |
Invalid
|
Undecided
|
Unassigned | ||
glibc (openSUSE) |
Fix Released
|
High
|
|||
postfix (Ubuntu) |
Fix Released
|
High
|
Unassigned | ||
Lucid |
Fix Released
|
Undecided
|
Unassigned | ||
Maverick |
Invalid
|
Undecided
|
Unassigned | ||
Natty |
Invalid
|
Undecided
|
Unassigned |
Bug Description
The eglibc resolver is broken and doesn't attempt DNS queries for hostnames without dots if the RES_DEFNAMES option gets stripped from the _res.options (resolver options).
This breaks security-sensitive applications (I'd first observed it with Postfix) trying to resolve, for instance, localhost, thus:
res_init();
_res.options &= ~RES_DEFNAMES;
int result = res_search(
returns failure with HOST_NOT_FOUND even if the name server has a localhost zone. FreeBSD and Solaris don't have this bug.
I've reported this upstream as http://
ProblemType: Bug
DistroRelease: Ubuntu 11.04
Package: libc6 2.13-0ubuntu13
ProcVersionSign
Uname: Linux 2.6.38-9-generic x86_64
NonfreeKernelMo
Architecture: amd64
Date: Thu May 5 15:55:40 2011
ProcEnviron:
LANGUAGE=de:en
PATH=(custom, no user)
LANG=de_DE.UTF-8
SHELL=/bin/bash
SourcePackage: eglibc
UpgradeStatus: Upgraded to natty on 2011-05-02 (3 days ago)
tags: | added: regression-release |
Changed in glibc (openSUSE): | |
importance: | Unknown → High |
status: | Unknown → Confirmed |
Changed in glibc: | |
importance: | Unknown → Critical |
status: | Unknown → Fix Released |
Changed in glibc (openSUSE): | |
status: | Confirmed → In Progress |
Changed in eglibc (Ubuntu Natty): | |
status: | New → Confirmed |
Changed in postfix (Ubuntu Natty): | |
status: | New → Confirmed |
Changed in glibc (openSUSE): | |
status: | In Progress → Fix Released |
Created attachment 5707
code to demonstrate the bug
(I've observed this on eglibc 2.13 and glibc 2.11.3 and confirmed it's still present in Git.)
Problem: res_search() can return -1 with h_errno == HOST_NOT_FOUND without ever having attempted a nameserver query even when it should have sent one.
In particular, this affects hostname resolution of "localhost" (without dots) if RES_DEFNAMES isn't set. (Use case: a security-sensitive application strips this flag to avoid the domain search and to avoid getting bogus localhost. example. org results that might not point to 127.0.0.1/::1.)
Pseudo code, without error checking:
res_init(); "localhost" , C_IN, T_A, buf, sizeof buffer);
_res.options &= ~RES_DEFNAMES;
int result = res_search(
This is an important portability issue from BSD or Solaris to Linux and affects, for instance, Postfix 2.8.X.
Compare the glibc source code lines 323 ff. <http:// sourceware. org/git/ ?p=glibc. git;a=blob; f=resolv/ res_query. c;h=5ff352e2fc6 056bad92238df1f b0c826f48a2f51; hb=HEAD# l323> against FreeBSD, lines 371 ff. in <http:// www.freebsd. org/cgi/ cvsweb. cgi/src/ lib/libc/ resolv/ res_query. c?annotate= 1.6;only_ with_tag= MAIN>.
I've attached a test program, show-resolv.c, to demonstrate the problem.
To compile: gcc -ggdb3 -O -std=gnu99 -pedantic -Wall -o show-resolv show-resolv.c -lresolv
To run: strace -e recv,send, recvfrom, sendto ./show-resolv
You will see that no DNS packets are sent to the nameserver configured in /etc/resolv.conf.
Actual output (no send/recv stuff!):
$ strace -e recv,send, recvfrom, sendto ./show-resolv
default _res.options = 802C1
stripped _res.options = 80241
res search result: -1, h_errno: 1 (Unknown host)
Expected output:
$ strace -e recv,send, recvfrom, sendto ./show-resolv 1\0\0\1\ 0\0\0\0\ 0\0\tlocalhost\ 0\0\1\0\ 1", 27, MSG_NOSIGNAL, NULL, 0) = 27 205\200\ 0\1\0\1\ 0\0\0\0\ tlocalhost\ 0\0\1\0\ 1\300\f\ 0\1\0". .., 512, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr= inet_addr( "192.168. 0.4")}, [16]) = 43
default _res.options = 802C1
stripped _res.options = 80241
sendto(3, "\34\264\
recvfrom(3, "\34\264\
res search result: 43
Of course the recvfrom details may differ with /etc/resolv.conf configuration.
And instead of 43, any positive number that makes it plausible we've received a successful reply to a DNS query for localhost IN A is valid, should there be gratuitious other records returned from the name server.
Please fix the resolver so that it actually sends a query for bare hostnames (without any dots, inner or trailing), localhost is a valid TLD.