RFR 8160710: Enable Thread to grant VarHandle field access to ThreadLocalRandom/Striped64
Paul Sandoz
paul.sandoz at oracle.com
Wed Jan 11 23:13:49 UTC 2017
> On 11 Jan 2017, at 14:00, Martin Buchholz <martinrb at google.com> wrote:
>
> Thanks, Paul.
>
> Looks good. Nits:
>
> ---
>
> Our inline assignment style is non-standard, but we like it and it saves a byte of bytecode occasionally, making things a tiny bit easier for the JIT.
>
Are you referring to cases like:
964 int r = (int) SECONDARY.get(t);
965 if (r != 0) {
?
I moved it out to make it clearer on the cast, but i can inline it as you prefer.
> ---
>
> The threadgroup creation code that uses cheating has always seemed fishy to me. The straightforward
>
> /**
> * Returns a new group with the system ThreadGroup (the
> * topmost, parent-less group) as parent.
> */
> static final ThreadGroup createThreadGroup(String name) {
> if (name == null)
> throw new NullPointerException();
> ThreadGroup group = Thread.currentThread().getThreadGroup();
> for (ThreadGroup p; (p = group.getParent()) != null; )
> group = p;
> return new ThreadGroup(group, name);
> }
>
> passes all tests. That could be wrapped in a doPrivileged, or we could add something more principled to ThreadGroup itself. I don't know what the motivations are for the threadgroup code.
>
Good point, me neither, nor the association with TLR (perhaps because there are over methods used by InnocuousForkJoinWorkerThread, see below). The Unsafe usage rolled in with:
https://bugs.openjdk.java.net/browse/JDK-8157523
http://hg.openjdk.java.net/jdk9/dev/jdk/rev/fd4819ec5afd
In ForkJoinWorkerThread:
static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
/** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
private static final ThreadGroup innocuousThreadGroup =
ThreadLocalRandom.createThreadGroup("InnocuousForkJoinWorkerThreadGroup”);
In ForkJoinPool:
private ForkJoinPool(byte forCommonPoolOnly) {
...
ForkJoinWorkerThreadFactory fac = null;
...
if (fac == null) {
if (System.getSecurityManager() == null)
fac = defaultForkJoinWorkerThreadFactory;
else // use security-managed default
fac = new InnocuousForkJoinWorkerThreadFactory();
}
…
private static final class InnocuousForkJoinWorkerThreadFactory
implements ForkJoinWorkerThreadFactory {
...
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return AccessController.doPrivileged(new PrivilegedAction<>() {
public ForkJoinWorkerThread run() {
return new ForkJoinWorkerThread.
InnocuousForkJoinWorkerThread(pool);
}}, INNOCUOUS_ACC);
}
}
So everything is wrapped in a doPrivileged block.
My guess as at some point in development it was important to efficiently bypass the security check of ThreadGroup.getParent, and Thread.getGroup came along for the ride.
AFAICT I don’t think we need it, and it would be nice to remove the VarHandle code and move createThreadGroup to be a static method of InnocuousForkJoinWorkerThread. How about:
static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
/** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
private static final ThreadGroup innocuousThreadGroup =
createThreadGroup();
…
private static ThreadGroup createThreadGroup() {
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
ThreadGroup topGroup = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<ThreadGroup>() {
public ThreadGroup run() {
ThreadGroup group = currentGroup;
for (ThreadGroup p; (p = group.getParent()) != null; )
group = p;
return group;
}});
return new ThreadGroup(topGroup, "InnocuousForkJoinWorkerThreadGroup");
}
}
That also passes the tests we have for the Innocuous case.
> ---
>
> 431 // Teleport the lookup to access fields in Thread
>
> Teleport?! Maybe "Obtain a private lookup object" but that should be obvious from the name “privateLookupIn”
>
Yes, i removed the comments.
Thanks,
Paul.
>
> On Wed, Jan 11, 2017 at 12:21 PM, Paul Sandoz <paul.sandoz at oracle.com> wrote:
> Hi,
>
> Please review:
>
> http://cr.openjdk.java.net/~psandoz/jdk9/8160710-thread-to-tlr/webrev/
>
> This patch updates ThreadLocalRandom, Striped64 and LockSupport to use VarHandles instead of Unsafe to access fields in Thread, via the MethodsHandles.privateLookupIn method.
>
> Since there are three usages of MethodsHandles.privateLookupIn in ThreadLocalRandom i consolidated the doPrivileged block in a private static helper method, being paranoid i placed some checks to avoid this method being potentially abused to circumvent the security check, perhaps that is overkill?
>
> I ran this patch though our test infra a few times and have not observed any transient failures.
>
> Thanks,
> Paul.
>
More information about the core-libs-dev
mailing list