ThreadLocalRandom clinit troubles (original) (raw)

Peter Levart peter.levart at gmail.com
Wed Jun 25 17:41:57 UTC 2014


To sum-up: We have a problem with TLR initialization since by default it uses networking code to compute initial "seeder" value which can execute user code in at least two situations:

We could work-around these problems by delaying initialization of NameService provider(s), by-passing SecurityManager when obtaining MAC address from NetworkInterface and extending the semantics of "java.util.secureRandomSeed" property to specify explicit SecureRandom algorithm and provider to use when obtaining SecureRandom instance, like in the following patch:

http://cr.openjdk.java.net/~plevart/jdk9-dev/TLR.initialSeed/webrev.01/

But on the other hand this seems too many knobs to worry about. Ideally one would like to always use OS provided native seed source, but SecureRandom (with all the security providers infrastructure) seems too heavy-weight to be used in classes like ThreadLocalRandom or SplittableRandom by default since they can be initialized very early in the start-up sequence. I made an experiment with class-loading. Recent JDK9 build loads 381 classes when running the following empty program on Linux:

public class test0 { public static void main(String[] args) { } }

...ThreadLocalRandom is not among them. But in special configurations (like when using java agents) or in the future, it could be. The following program:

public class test { public static void main(String[] args) { java.util.concurrent.ThreadLocalRandom.current(); } }

...loads 403 classes. That's 22 more than an empty program. The following classes are loaded in addition:

If I run the same program but set the "java.util.secureRandomSeed=true", it loads 435 classes. Besides 381 classes loaded by an empty program, the following 54 classes are loaded in addition:

This seems too heavy-weight even if the initialization issue on Windows where default SecureRandom algorithm is using networking code to gather system entropy is worked-around by requesting explicit "Windows-PRNG" SecureRandom algorithm from "SunMSCAPI" provider.

Peeking around in the sun.security.provider package, I found there already is a minimal internal infrastructure for obtaining random seed. It's encapsulated in package-private abstract class sun.security.provider.SeedGenerator with 4 implementations. It turns out that, besides Java-only fall-back implementation called ThreadedSeedGenerator and generic URLSeedGenerator, there are also two implementations of NativeSeedGenerator (one for UNIX-es which is just an extension of URLSeedGenerator and the other for Windows which uses MS CryptoAPI). I made a few tweaks that allow this sub-infrastructure to be used directly in ThreadLocalRandom and SplittableRandom:

http://cr.openjdk.java.net/~plevart/jdk9-dev/TLR_SR_SeedGenerator/webrev.01/

The changes are as follows:

With these changes and modified TLR, running the test program (see above) loads only the following 15 additional classes besides those that are loaded by an empty program on Linux (and I assume the number is the same on Windows):

So what do you think is the best direction to go further with this? Patching networking or exposing NativeSeedGenerator to internal JDK code?

Regards, Peter

-------------- next part -------------- An HTML attachment was scrubbed... URL: <https://mail.openjdk.org/pipermail/security-dev/attachments/20140625/9734239b/attachment.htm>



More information about the security-dev mailing list