Note: This is a beta release of Red Hat Bugzilla 5.0. The data contained within is a snapshot of the live data so any changes you make will not be reflected in the production Bugzilla. Also email is disabled so feel free to test any aspect of the site that you want. File any problems you find or give feedback here.
Bug 178986 - X server segfault on null interface address returned by getifaddrs() in os/access.c DefineSelf()
Summary: X server segfault on null interface address returned by getifaddrs() in os/ac...
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: xorg-x11-server
Version: rawhide
Hardware: All
OS: Linux
medium
high
Target Milestone: ---
Assignee: X/OpenGL Maintenance List
QA Contact:
URL:
Whiteboard:
: 174279 (view as bug list)
Depends On:
Blocks: FC5Target
TreeView+ depends on / blocked
 
Reported: 2006-01-26 00:56 UTC by Jason Vas Dias
Modified: 2007-11-30 22:11 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2006-02-06 21:56:22 UTC


Attachments (Terms of Use)

Description Jason Vas Dias 2006-01-26 00:56:42 UTC
Description of problem:

The X server from xorg-x11-server-Xorg-1.0.0-3 generates a memory access
violation when there are NULL interface addresses returned by os/access.c's 
call to getifaddrs() in DefineSelf(), as revealed by installing the debuginfo
package and running gdb on the core:

# gdb /usr/bin/X core.3129
GNU gdb Red Hat Linux (6.3.0.0-1.98rh) 
...
Core was generated by `X -probeonly'.
Program terminated with signal 11, Segmentation fault.
...
#0  ConvertAddr (saddr=0x0, len=0xbf864bc0, addr=0xbf864bbc) at access.c:1861
1861        switch (saddr->sa_family)
(gdb) up
#1  0x0819de57 in DefineSelf (fd=1) at access.c:983
983             family = ConvertAddr(ifr->ifa_addr, &len, (pointer *)&addr);

Having a look at access.c, it appears there is no validation of getifaddr's
returned address list:

@access.c, line 973:
---
    if (getifaddrs(&ifap) < 0) {
	ErrorF("Warning: getifaddrs returns %s\n", strerror(errno));
	return;
    }
    for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
#ifdef DNETCONN
	if (ifr->ifa_addr.sa_family == AF_DECnet) 
	    continue;
#endif /* DNETCONN */
	len = sizeof(*(ifr->ifa_addr));
	family = ConvertAddr(ifr->ifa_addr, &len, (pointer *)&addr);
...
---

I'd suggest at least something like this here :

@access.c, line 977:
   for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
+       if ( ifr->ifa_addr == NULL ) continue;

Version-Release number of selected component (if applicable):
xorg-x11-server-Xorg-1.0.0-3

How reproducible:
100%

Steps to Reproduce:
Start X when no interface addresses are configured 
(eg. bring interfaces up, then 'ip addr del' all the interface addresses.
 interfaces may still be "UP", but have no interface addresses).

Actually, I think there are certain situations where getifaddrs can return
a null address for an interface, even if other interfaces do have addresses -
X should handle these situations gracefully.
  
Actual results:
X does not start and generates a core dump if ulimit -c != 0

Expected results:
X should start OK, or possibly terminate with an error if it really needs
an interface address in order to start correctly.

Comment 1 Jason Vas Dias 2006-01-26 20:42:28 UTC
I've found out that this bug can be reproduced very easily, by attempting to 
bring up the vpnc client (from vpnc-0.3-2rhis) during boot.

vpnc creates the tun0 interface with a NULL ifa_addr - tun0 has a 
point-to-point address instead.

This is exposed by running the following program:
---
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
    struct ifaddrs *ifa=0, *ifap=0;
    char addr[128];

    if( (getifaddrs( &ifap ) != 0) || (ifap == 0L))
    {
        fprintf(stderr,"getifaddrs failed: %s\n", strerror(errno));
        return 0;
    }

    for( ifa = ifap; ifa != 0L; ifa = ifa->ifa_next )
    {
        if( ifa->ifa_addr == 0L )
        {
            printf("%s: NULL ifa_addr\n", ifa->ifa_name);
            continue;
        }
        printf("%s:\t%s\n", ifa->ifa_name,
               inet_ntop( ifa->ifa_addr->sa_family,
                          ifa->ifa_addr->sa_family == AF_INET
                          ? (void*)&(((struct sockaddr_in*)ifa->ifa_addr)->sin_addr)
                          : (void*)&(((struct
sockaddr_in6*)ifa->ifa_addr)->sin6_addr),
                          &(addr[0]), 128
                        )
              );
    }
}
---

When vpnc has brought up the tun0 interface, the output of this program is:
$ ./ifa
lo:     (null)
eth0:   (null)
eth1:   (null)
wifi0:  (null)
sit0:   (null)
tun0: NULL ifa_addr
lo:     127.0.0.1
eth0:   172.16.80.119
eth1:   10.13.253.138
tun0:   172.16.83.172
lo:     ::1
eth0:   fe80::20d:60ff:fecf:98e3
eth1:   fe80::20e:9bff:fe15:896a

So tun0 has a NULL ifa->ifa_addr pointer, as distinct from a valid pointer that
points to an invalid in_addr, which makes inet_pton return a null pointer, so
printf prints '(null)' .


Comment 2 Mike A. Harris 2006-01-27 23:29:44 UTC
Adding to FC5Target tracker.

Comment 3 Mike A. Harris 2006-02-01 01:28:34 UTC
Similar in nature: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=174279


Comment 4 Mike A. Harris 2006-02-06 06:36:08 UTC
I've added a patch which should fix this to xorg-x11-server-1.0.1-2

Please update to the new release and update the report with the status
of test results.

Thanks in advance.

Comment 5 Jason Vas Dias 2006-02-06 21:56:22 UTC
Yes, xorg-x11-server-1.0.1-2 now starts fine when getifaddrs returns a null 
ifa->ifa_addr - thank you !


Comment 6 Mike A. Harris 2006-02-07 10:15:35 UTC
*** Bug 174279 has been marked as a duplicate of this bug. ***

Comment 7 Adam Szalkowski 2006-02-07 11:48:42 UTC
yes, this also works for me now, thanks


Note You need to log in before you can comment on or make changes to this bug.