netdb.h redefines "h_addr"

Bug #589855 reported by Jean-Christophe Baptiste
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
eglibc (Ubuntu)
Invalid
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

Revision history for this message
Jean-Christophe Baptiste (jc-baptiste) wrote :
Revision history for this message
Jean-Christophe Baptiste (jc-baptiste) wrote :
Revision history for this message
Jean-Christophe Baptiste (jc-baptiste) wrote :
Revision history for this message
Jean-Christophe Baptiste (jc-baptiste) wrote :
Kees Cook (kees)
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)
Revision history for this message
Kees Cook (kees) wrote : Re: incorrect stack size calculation when building with -O0

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)

Revision history for this message
Kees Cook (kees) wrote :

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

Revision history for this message
Matthias Klose (doko) wrote :

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

Revision history for this message
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

Revision history for this message
Kees Cook (kees) wrote :

Does _not_ fail on 32bit...

Revision history for this message
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)
summary: - incorrect stack size calculation when building with -O0
+ netdb.h redefines "h_addr"
Changed in eglibc (Ubuntu):
importance: Undecided → Wishlist
status: Confirmed → Triaged
Revision history for this message
dino99 (9d9) wrote :

This is no more a supported version now

Changed in eglibc (Ubuntu):
status: Triaged → Invalid
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.