Ubuntu

netdb.h redefines "h_addr"

Reported by Jean-Christophe Baptiste on 2010-06-04
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
eglibc (Ubuntu)
Wishlist
Unassigned

Bug Description

The attached code compiles allright (gcc test.c -o test) but when I run it segfaults :

% ./test example.com 80
toto
phocean.net
resolv: phocean.net
zsh: segmentation fault ./test phocean.net 80

Debug session (attached) shows that the resolv function is working as expected, but something on the stack gets crafted and it is unable to return to the main section.

The weired thing is that it compiles and works very well on all others distro I had as virtual machines : Fedora 13 32bits & 64bits, openSUSE 11.2 64bits and Debian 5 32bits.
I also took the binary from one of these VM and ran it on Ubuntu, and it worked.
The binary from Ubuntu crashes anywhere else.

That's why I presume it is libc6 related.

Error in /var/log/messages :
kernel: [81039.332829] test[25870]: segfault at 7fff6d799f39 ip 000000000040077f sp 00007fff7b852b40 error 6 in test[400000+1000]

ProblemType: Bug
DistroRelease: Ubuntu 10.04
Package: libc6 2.11.1-0ubuntu7.1
ProcVersionSignature: Ubuntu 2.6.32-22.36-generic 2.6.32.11+drm33.2
Uname: Linux 2.6.32-22-generic x86_64
Architecture: amd64
Date: Fri Jun 4 20:20:17 2010
InstallationMedia: Ubuntu 10.04 LTS "Lucid Lynx" - Release amd64 (20100429)
ProcEnviron:
 PATH=(custom, user)
 LANG=fr_FR.utf8
 SHELL=/bin/zsh
SourcePackage: eglibc

Kees Cook (kees) on 2010-06-04
summary: - segfault only when compiled on Lucid
+ incorrect stack size calculation when building with -O0
Changed in eglibc (Ubuntu):
status: New → Confirmed
affects: eglibc (Ubuntu) → gcc-4.4 (Ubuntu)

Here's a more minimal test case. It looks like the compiler isn't correctly calculating function stack sizes when building without optimization.

$ gcc -Wall test.c -o test -O1
$ ./test
74.125.127.104
$ gcc -Wall test.c -o test -O0
$ ./test
74.125.127.103
Segmentation fault (core dumped)

Happens with gcc-snapshot in Maverick too:

$ /usr/lib/gcc-snapshot/bin/gcc -Wall test.c -o test -O0
$ ./test
74.125.127.99
Segmentation fault (core dumped)

Kees Cook (kees) wrote :

(actually, this may be a glibc issue, as originally reported; gcc-4.3 fails under lucid too)

Matthias Klose (doko) wrote :

seen on dapper (gcc-4.0), and lenny (4.3) as well.

Matthias Klose (doko) wrote :

seen on sid as well.

the original test case works with -fno-stack-protector, the reduced test case doesn't work with and without stack protector

Kees Cook (kees) wrote :

Does _not_ fail on 32bit...

Kees Cook (kees) wrote :

The problem is the netdb.h include file. This crashes:

#include <netdb.h>
#include <netinet/in.h>
void resolv(void) {
 struct in_addr h_addr;
 *(unsigned int*)&h_addr = 0;
}
int main(int argc, char *argv[] ) {
 resolv();
 return 0;
}

If netdb.h is removed, it's fine. This appears to be because the "h_addr" macro is retained, and rewrites the main body of the code:

- struct in_addr h_addr;
+ struct in_addr h_addr_list[0];
- *(unsigned int*)&h_addr = 0;
+ *(unsigned int*)&h_addr_list[0] = 0;

It seems that "h_addr" is a reserved name if netdb.h is included to support the old-style naming. From "man gethostbyname":

       The hostent structure is defined in <netdb.h> as follows:

           struct hostent {
               char *h_name; /* official name of host */
               char **h_aliases; /* alias list */
               int h_addrtype; /* host address type */
               int h_length; /* length of address */
               char **h_addr_list; /* list of addresses */
           }
           #define h_addr h_addr_list[0] /* for backward compatibility */

Is this a bug in glibc, then, or user error?

affects: gcc-4.4 (Ubuntu) → eglibc (Ubuntu)
Kees Cook (kees) on 2010-06-07
summary: - incorrect stack size calculation when building with -O0
+ netdb.h redefines "h_addr"
Changed in eglibc (Ubuntu):
importance: Undecided → Wishlist
status: Confirmed → Triaged
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers