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:
Clone Of:
Environment:
Last Closed: 2006-02-06 21:56:22 UTC
Type: ---
Embargoed:


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.