>Number:         189268
>Category:       misc
>Synopsis:       man 3 getaddrinfo - hostanme="localhost", but it returns 
>IN_ADDR_ANY (0.0.0.0)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri May 02 22:00:00 UTC 2014
>Closed-Date:
>Last-Modified:
>Originator:     Dreamcat4
>Release:        9.2-RELEASE-p3
>Organization:
>Environment:
FreeBSD freenas.local 9.2-RELEASE-p3 FreeBSD 9.2-RELEASE-p3 #0 r262572+7b72365: 
Fri Mar 14 15:50:04 PDT 2014     
[email protected]:/home/jkh/9.2.1-BRANCH/freenas/os-base/amd64/tank/home/jkh/9.2.1-BRANCH/freenas/FreeBSD/src/sys/FREENAS.amd64
  amd64

>Description:
* Inside a jail, no lo0 loopback interface.
* Calling this function returns the ip "0.0.0.0" (also known as "IN_ADDR_ANY").
* But we asked for the hostname "localhost" - which in our /etc/hosts file is 
set to "127.0.0.1".

The proof:
Example 'C' test program "test.c" is attached.
getaddrinfo ~/ root~# gcc test.c -o test && ./test
0.0.0.0

This affects the gSOAP library, it's function soap_bind(), which is called by 
VirtualBox's SOAP webservice ("vboxwebsrv").

These applications seem to do everything correctly. But the result is a bug. 
Please see test script "test.c" included.

The real-life bug occurs in this code where:

vboxweb.cpp:858:
    SOAP_SOCKET m, s; // master and slave sockets
    m = soap_bind(&soap,
                  g_pcszBindToHost ? g_pcszBindToHost : "localhost",    // safe 
default host
                  g_uBindToPort,    // port
                  g_uBacklog);      // backlog = max queue size for requests
    if (m < 0)
        WebLogSoapError(&soap);


and:

stdsoap2.cpp:4143:
  err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);

Is passing in "localhost", is told "0.0.0.0". Then later on in soap_bind(), the 
returned address "0.0.0.0" is passed into bind(). And bind() then binds to ALL 
interfaces (not just only the localhost interface, or should error out in the 
jail where lo0 has no IP address).

I looked hard in these applications but the bug isn't in there - it seems to be 
in the result returned be "getaddrinfo()" C library call.

I confirmed this was the case with "test.c" example program (below). Which was 
run in the same jail.

The test jail was created like this:

$ qjail create -4 192.168.1.203 getaddrinfo
$ qjail config -k getaddrinfo
$ qjail start getaddrinfo

>How-To-Repeat:
getaddrinfo ~/ root~# ifconfig
re0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        
options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
        ether 00:1e:ec:d7:3a:1f
        inet 192.168.1.203 netmask 0xffffffff broadcast 192.168.1.203
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
ipfw0: flags=8801<UP,SIMPLEX,MULTICAST> metric 0 mtu 65536
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
getaddrinfo ~/ root~# ping -c 1 "localhost"
PING localhost (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.168 ms

--- localhost ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.168/0.168/0.168/0.000 ms
getaddrinfo ~/ root~# cat /etc/hosts | grep localhost
::1                     localhost localhost.my.domain
127.0.0.1               localhost localhost.my.domain
getaddrinfo ~/ root~# cat test.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>


/* man getaddrinfo */

int main()
{
  struct addrinfo *addrinfo = NULL;
  struct addrinfo hints;
  struct addrinfo res;
  int err;

  memset((void*)&hints, 0, sizeof(hints));
  hints.ai_family   = PF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags    = AI_PASSIVE;

  err = getaddrinfo("localhost", "18083", &hints, &addrinfo);

  if (addrinfo)
  { 
    res = *addrinfo;
    printf("%s\n", inet_ntoa( ((struct 
sockaddr_in*)addrinfo->ai_addr)->sin_addr ));

    freeaddrinfo(addrinfo);
    return(0);
  }

  if (err || !addrinfo)
  {
    printf("getaddrinfo failed with code %i.\n",err);
    return(1);
  }

  printf("end_main()\n");
  return (0);

}

getaddrinfo ~/ root~# gcc test.c -o test && ./test
0.0.0.0
getaddrinfo ~/ root~# exit
logout

>Fix:
I suspect this function (getaddrinfo) shouldn't be returning IN_ADDR_ANY. It 
should either fail, or return "127.0.0.1" as per "/etc/hosts".


>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"

Reply via email to