Bug 178986 - X server segfault on null interface address returned by getifaddrs() in os/access.c DefineSelf()
X server segfault on null interface address returned by getifaddrs() in os/ac...
Status: CLOSED RAWHIDE
Product: Fedora
Classification: Fedora
Component: xorg-x11-server (Show other bugs)
rawhide
All Linux
medium Severity high
: ---
: ---
Assigned To: X/OpenGL Maintenance List
:
: 174279 (view as bug list)
Depends On:
Blocks: FC5Target
  Show dependency treegraph
 
Reported: 2006-01-25 19:56 EST by Jason Vas Dias
Modified: 2007-11-30 17:11 EST (History)
1 user (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2006-02-06 16:56:22 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:


Attachments (Terms of Use)

  None (edit)
Description Jason Vas Dias 2006-01-25 19:56:42 EST
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 15:42:28 EST
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 18:29:44 EST
Adding to FC5Target tracker.
Comment 3 Mike A. Harris 2006-01-31 20:28:34 EST
Similar in nature: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=174279
Comment 4 Mike A. Harris 2006-02-06 01:36:08 EST
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 16:56:22 EST
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 05:15:35 EST
*** Bug 174279 has been marked as a duplicate of this bug. ***
Comment 7 Adam Szalkowski 2006-02-07 06:48:42 EST
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.