Bug 178986
| Summary: | X server segfault on null interface address returned by getifaddrs() in os/access.c DefineSelf() | ||
|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Jason Vas Dias <jvdias> |
| Component: | xorg-x11-server | Assignee: | X/OpenGL Maintenance List <xgl-maint> |
| Status: | CLOSED RAWHIDE | QA Contact: | |
| Severity: | high | Docs Contact: | |
| Priority: | medium | ||
| Version: | rawhide | CC: | adam |
| Target Milestone: | --- | ||
| Target Release: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | Bug Fix | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2006-02-06 21:56:22 UTC | Type: | --- |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | |||
| Bug Blocks: | 150221 | ||
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)' .
Adding to FC5Target tracker. Similar in nature: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=174279 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. Yes, xorg-x11-server-1.0.1-2 now starts fine when getifaddrs returns a null ifa->ifa_addr - thank you ! *** Bug 174279 has been marked as a duplicate of this bug. *** yes, this also works for me now, thanks |
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.