Bug 40841 - mod_proxy_ftp segfaults on IPv4 requests to hosts with DNS AAAA records
Summary: mod_proxy_ftp segfaults on IPv4 requests to hosts with DNS AAAA records
Status: RESOLVED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_proxy (show other bugs)
Version: 2.2.3
Hardware: All Linux
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-10-29 07:04 UTC by Andrew Rucker Jones
Modified: 2012-11-01 15:03 UTC (History)
0 users



Attachments
Patch for APR and mod_proxy_ftp (1.98 KB, patch)
2006-10-29 07:05 UTC, Andrew Rucker Jones
Details | Diff
rediff against 2.2.22 modified to affect only mod_proxy_ftp.c (1.63 KB, patch)
2012-08-26 23:11 UTC, ast
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Rucker Jones 2006-10-29 07:04:27 UTC
On an IPv6-enabled host with an IPv6-enabled Apache, but only IPv4 connectivity
to the Internet, proxy requests for FTP data from FTP servers that have an IPv6
(and IPv4) entry in DNS cause the assigned Apache worker process to crash with a
SIGSEGV. There are two reasons for this. The first is that apr_socket_connect()
doesn't check its input parameters to see if they are NULL before dereferencing
them. The second is that proxy_ftp_handler() first does a lookup with
apr_sockaddr_info_get(), which primarily returns the AAAA record, and family ==
AF_INET6. Later, i assume during ap_proxy_acquire_connection(),
ap_proxy_connect_backend(), or ap_proxy_connection_create(), something is
intelligent enough to figure out that the IPv6 address cannot be reached, and
uses the IPv4 address for the control connection. Over the control connection,
the EPSV command is issued. After the result is returned (assuming the server
supports EPSV), apr_sockaddr_info_get() is called with connect_addr->family as
the family parameter, and data_ip as the address. connect_addr->family still has
AF_INET6, but data_ip has the IPv4 address of the server. This causes glibc to
return EAI_ADDRFAMILY, and epsv_addr is left NULL. That is passed to
apr_socket_connect(), and we know what happens after that.

In addition, there is the potential for a *slight* performance improvement. On
line 1235 of mod_proxy_ftp.c apr_sockaddr_info_get() is called with flags == 0.
Since, as far as i can determine, these flags are passed to getaddrinfo(), if
flags is set to at least AI_NUMERICHOST (this is guarunteed by the code above),
some coding and/or DNS lookups could be avoided. The 0 can't simply be replaced
with AI_NUMERICHOST, because the proper header file (netdb.h on Linux) is not
included.

I am attaching a patch to fix both problems. I realize that the first problem is
in APR, and not in Apache, but i ran across both as part of my attempt to fix my
problem.
Comment 1 Andrew Rucker Jones 2006-10-29 07:05:48 UTC
Created attachment 19050 [details]
Patch for APR and mod_proxy_ftp
Comment 2 Andrew Rucker Jones 2006-10-29 07:06:20 UTC
I should have mentioned a test case: ftp.isc.org.
Comment 3 Andrew Rucker Jones 2006-10-29 07:17:47 UTC
I originally put this under 2.3-HEAD because i wasn't thinking. It's actually in
2.2.3, for which there is not a version entry in Bugzilla.
Comment 4 Andrew Rucker Jones 2006-11-01 11:36:57 UTC
By the way, the same problem most likely exists a few lines down in the PASV
section, and again a few lines down from that in the PORT section.
Comment 5 ast 2012-08-26 23:11:00 UTC
Created attachment 29281 [details]
rediff against 2.2.22 modified to affect only mod_proxy_ftp.c

The segfault still happens with 2.2.22 and the patch still fixes it.

Example: ftp.netfilter.org returns an AAAA as well as an A address.

AAAA 2001:780:45:1d:20d:93ff:fe9b:e442
A    213.95.27.115

When trying to connect to the AAAA address we get a "connection refused":


flepo tmp # tcpdump -i ppp0 -n -v -s 2048 -A ip6
tcpdump: listening on ppp0, link-type LINUX_SLL (Linux cooked), capture size 2048 bytes
00:31:59.102705 IP6 (hlim 64, next-header TCP (6) payload length: 40) 2001:a60:18ff:eedf:d11d:2256:d944:ad16.3798 > 2001:780:45:1d:20d:93ff:fe9b:e442.21: Flags [S], cksum 0x4d0c (incorrect -> 0x5481), seq 2079833585, win 14320, options [mss 1432,sackOK,TS val 73277849 ecr 0,nop,wscale 9], length 0
`....(.@ .
.....B....{.........7.M..........
.^!........
00:31:59.115245 IP6 (hlim 58, next-header TCP (6) payload length: 20) 2001:780:45:1d:20d:93ff:fe9b:e442.21 > 2001:a60:18ff:eedf:d11d:2256:d944:ad16.3798: Flags [R.], cksum 0x1a1e (correct), seq 0, ack 2079833586, win 0, length 0
.....B . ....E...
`......"V.D..........{...P.......
^C
2 packets captured
2 packets received by filter
0 packets dropped by kernel



Then mod_proxy_ftp tries the "A" address and segfaults after doing the "EPSV" command without the patch.
Comment 6 Jim Jagielski 2012-11-01 15:03:24 UTC
Updated for new conn_rec info.
Committed revision 1404625