Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8211842

IPv6_supported wrongly returns false when unix domain socket is bound to fd 0

    XMLWordPrintable

    Details

    • Subcomponent:
    • Resolved In Build:
      b23
    • CPU:
      x86_64
    • OS:
      linux_ubuntu

      Description

      ADDITIONAL SYSTEM INFORMATION :
      $ java -version
      openjdk version "10.0.2" 2018-07-17
      OpenJDK Runtime Environment (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.2)
      OpenJDK 64-Bit Server VM (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.2, mixed mode)

      A DESCRIPTION OF THE PROBLEM :
      When a unix domain socket is bound to fd 0 of a JVM instance all IPv6 functionality is disabled. This for example occurs when the JVM is spawned by Node.js (see https://stackoverflow.com/questions/34108124/ip-addresses-of-network-interfaces-in-a-java-process-spawned-by-nodejs).

      I am completely unexperienced when it comes to the JDK/JVM source code, but I think I might have found the issue. The IPv6_supported function in src/java.base/unix/native/libnet/net_util_md.c contains the following check, whether fd 0 is a socket. If so and this socket is not an IPv6 socket it returns false. However, the comment above the function states that this check should disable IPv6 when the socket is an IPv4 socket.

      I came to the conclusion that this is a bug, because the comment and the implementation do not match, and IPv6 is also disabled if the socket type is AF_UNIX.

       307 /*
       308 * If fd 0 is a socket it means we've been launched from inetd or
       309 * xinetd. If it's a socket then check the family - if it's an
       310 * IPv4 socket then we need to disable IPv6.
       311 */
       312 if (getsockname(0, &sa.sa, &sa_len) == 0) {
       313 if (sa.sa.sa_family != AF_INET6) {
       314 close(fd);
       315 return JNI_FALSE;
       316 }
       317 }

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Launch a JVM with a unix domain socket bound to fd 0 and bind a ServerSocket to an IPv6 address.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      A sucessfully bounded ServerSocket.
      ACTUAL -
      Exception in thread "main" java.net.SocketException: Protocol family unavailable
              at java.net.PlainSocketImpl.socketBind(Native Method)
              at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
              at java.net.ServerSocket.bind(ServerSocket.java:375)
              at java.net.ServerSocket.bind(ServerSocket.java:329)
              at Test.main(Test.java:6)

      ---------- BEGIN SOURCE ----------
      import java.net.*;

      public class Test {
          public static void main(String[] args) throws Exception {
              ServerSocket s = new ServerSocket();
              s.bind(new InetSocketAddress("::", 12345));
          }
      }

      The following python code can be used to start the jvm with a unix domain socket bound to fd 0:
      #!/usr/bin/env python
      import socket
      import subprocess

      sock = socket.socket(socket.AF_UNIX)
      sock.bind('/tmp/socket')
      fd = sock.makefile()

      proc = subprocess.Popen(['/usr/bin/java', 'Test'], stdin=fd)
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      The only "workaround" I found is to not bind a unix domain socket to fd 0.

      FREQUENCY : always


        Attachments

        1. pytest.py
          0.2 kB
          Pallavi Sonal
        2. Test.java
          0.2 kB
          Pallavi Sonal

          Issue Links

            Activity

              People

              Assignee:
              michaelm Michael McMahon
              Reporter:
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: