JDK-4952383 : SSLSocketFactory.getDefault() hangs on machines not doing other I/O
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2003-11-11
  • Updated: 2003-11-12
  • Resolved: 2003-11-12
Related Reports
Duplicate :  
Description
Name: jl125535			Date: 11/11/2003


FULL PRODUCT VERSION :
java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)


FULL OS VERSION :
Linux diskcheck 2.4.20-18.7 #1 Thu May 29 08:32:50 EDT 2003 i686 unknown




EXTRA RELEVANT SYSTEM CONFIGURATION :
Diskless (nfs root filesystem) server. It uses a stock kernel.
(uses initrd to mount root filesystem over NFS)

A DESCRIPTION OF THE PROBLEM :
On a diskless machine, which does no disk I/O, calls to SSLSocketFactory.getDefault() hang. It can be "unhung" by
1) Entering data from the console keyboard
  a) hit the return key 3 times
  b) hit the numlock key 3 times
  c) combos of (a) and (b) (probably other keys...)
2) If a disk is attached, forcing I/O WRITE to the disk.
   (just having a disk mounted isn't enough. I/O must occur)

Network I/O has no effect.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Boot a diskless machine. (Just set it up so that it does no I/O writes
   to the local disk. If that means using tmpfs filesystems for
   /var/log and vmstat reports no I/O, it should work.)

2) Compile and run the program giving in the Source section.

Example:
javac SSLMinimal.java
java -classpath . SSLMinimal

It hangs until a disk write or sufficient I/O on the console keyboard occurs.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected result is immedate completion of the program. Output like

sslSocketFactory=com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl@1749757

ACTUAL -
System hangs until I/O occurs. After I/O, above expected result
happens.


ERROR MESSAGES/STACK TRACES THAT OCCUR :
No error message. Process hangs.

From the jdb debugger, once the process is hanging

  [1] java.io.FileInputStream.readBytes (native method)
  [2] java.io.FileInputStream.read (FileInputStream.java:194)
  [3] java.io.BufferedInputStream.read1 (BufferedInputStream.java:220)
  [4] java.io.BufferedInputStream.read (BufferedInputStream.java:277)
  [5] java.io.BufferedInputStream.fill (BufferedInputStream.java:183)
  [6] java.io.BufferedInputStream.read1 (BufferedInputStream.java:222)
  [7] java.io.BufferedInputStream.read (BufferedInputStream.java:277)
  [8] sun.security.provider.SeedGenerator$URLSeedGenerator.getSeedByte (SeedGenerator.java:467)
  [9] sun.security.provider.SeedGenerator.getSeedBytes (SeedGenerator.java:137)
  [10] sun.security.provider.SeedGenerator.generateSeed (SeedGenerator.java:132)
  [11] sun.security.provider.SecureRandom.engineGenerateSeed (SecureRandom.java:112)
  [12] sun.security.provider.SecureRandom.engineNextBytes (SecureRandom.java:169)
  [13] java.security.SecureRandom.nextBytes (SecureRandom.java:381)
  [14] java.security.SecureRandom.next (SecureRandom.java:403)
  [15] java.util.Random.nextInt (Random.java:191)
  [16] com.sun.net.ssl.internal.ssl.SSLContextImpl.engineInit (null)
  [17] com.sun.net.ssl.internal.ssl.SSLContextImpl.e (null)
  [18] com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.<init> (null)
  [19] sun.reflect.NativeConstructorAccessorImpl.newInstance0 (native method)
  [20] sun.reflect.NativeConstructorAccessorImpl.newInstance (NativeConstructorAccessorImpl.java:39)
  [21] sun.reflect.DelegatingConstructorAccessorImpl.newInstance (DelegatingConstructorAccessorImpl.java:27)
  [22] java.lang.reflect.Constructor.newInstance (Constructor.java:274)
  [23] java.lang.Class.newInstance0 (Class.java:308)
  [24] java.lang.Class.newInstance (Class.java:261)
  [25] javax.net.ssl.SSLSocketFactory.getDefault (null)

(etc... )

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.security.Security;

import javax.net.ssl.SSLSocketFactory;

public class SSLMinimal
{

    static public void main( String args[] ) throws Exception
    {
        try
        {
            SSLSocketFactory sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
            System.out.println( "sslSocketFactory="+sslSocketFactory );
        }
        catch ( Exception e )
        {
            System.out.println( e );
            e.printStackTrace();
        }
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
(initial workaround)
For the servers that make SSL connections, we have been forced to
install disks and mount them under /var/log. The idea being that
we write to the log file just before opening the socket. The output
is buffered, so it normally occurs after the call to
SSLSocketFactory.getDefault().

(revised workaround)
The workaround is to do something like the following:

stat -f /var/log/httpd | grep -i 'Type: EXT2' >/dev/null 2>&1
DISKLESS=$?
.
.
.
if (( DISKLESS > 0 )); then
  OPTIONS="$OPTIONS -Djava.security.egd=file:/dev/urandom"
fi

java $OPTIONS myclass.class


------------------

Setting
java.security.egd=file:/dev/urandom
seems to solve the problem. Although it involves the possibility
of someone figuring out the random number generation, in our case
this isn't that much of a concern. /dev/urandom never blocks, and
that allows the jre to get the random number seed.


(Incident Review ID: 209774) 
======================================================================
###@###.### 2003-11-11

Comments
EVALUATION As mentioned by the customer in the comments section, this is due the way the Linux kernel gathers entropy, which does seem rather limited. In any case, the issue is already addressed by 4705093, closing as a dup. ###@###.### 2003-11-12
12-11-2003