RFR(S): 8160564: TEST: Add a test to check the implementation of VersionProps.versionNumbers()

Martin Buchholz martinrb at google.com
Thu Jul 7 18:05:20 UTC 2016


When jdk9 is released, an army of white, black, grey, and red hats will try
to keep their old Unsafe hacks alive and maybe get their hands on a
jdk.internal.misc.Unsafe.  Here's some code that tries to do that. The call
to setAccessible succeeds! And the code succeeds in getting hold
of jdk.internal.misc.Unsafe.class and of its instance before finally
failing with IllegalAccessError.  So this may actually be safe, in that
user code may not be able to actually invoke methods on their ill-gotten
Unsafe object, but the intent is probably that they shouldn't be able to
get this far:

/**
 * javac -Xmodule:java.base GetUnsafe9.java && java GetUnsafe9
 */
public class GetUnsafe9 {
    public static void main(String[] args) throws Throwable {
        Class<?> klazz = java.util.concurrent.ConcurrentHashMap.class;
        for (java.lang.reflect.Field field : klazz.getDeclaredFields()) {
            if (field.getName().equals("U")) {
                field.setAccessible(true);
                System.out.println(field);
                Object theUnsafe = field.get(null);
                System.out.println(theUnsafe);
                Class<jdk.internal.misc.Unsafe> unsafeClass =
                    (Class<jdk.internal.misc.Unsafe>) theUnsafe.getClass();
                System.out.println(unsafeClass);
                jdk.internal.misc.Unsafe U = unsafeClass.cast(theUnsafe);
            }
        }
    }
}

private static final jdk.internal.misc.Unsafe
java.util.concurrent.ConcurrentHashMap.U
jdk.internal.misc.Unsafe at 35851384
class jdk.internal.misc.Unsafe
Exception in thread "main" java.lang.IllegalAccessError: class GetUnsafe9
(in unnamed module @0x649d209a) cannot access class
jdk.internal.misc.Unsafe (in module java.base) because module java.base
does not export jdk.internal.misc to unnamed module @0x649d209a
at GetUnsafe9.main(GetUnsafe9.java:16)



On Thu, Jul 7, 2016 at 7:54 AM, Andrew Dinn <adinn at redhat.com> wrote:

> On 07/07/16 14:59, Volker Simonis wrote:
> > - I was a little bit surprised that I could reflectively access and
> > execute java.lang.VersionProps.parseVersionNumbers() where both the
> > class and the method are package private. Maybe this is related to
> > Jigsaw issue #ReflectiveAccessToNonExportedTypes [3]? As I'm not a
> > Jigsaw expert, I'd be graceful to anybody explaining me why this is
> > still so easily possible with Jigsaw?
>
> Reflective access to non-public classes/members of exported packages is
> unchanged with Jigsaw -- it is subject to the security checks in place
> in previous JDKs but not to a module access check.  So, in this case
> java.lang is an exported package which means you can obtain a handle on
> java.lang.VersionProps.parseVersionNumbers(), call setEnabled(true) and
> then invoke it.
>
> It is only when you try to reflectively access non-public
> classes/members of packages that are not exported by their owning module
> that the check comes into play. So, if your (non-module) code obtains a
> reflective Member for jdk.internal.misc.Unsafe.theUnsafe and calls
> setEnabled(true) you will find that the latter call will not succeed in
> rendering it an accessible handle and an access via that handle will
> fail. That is because java.base does not export package
> jdk.internal.misc so the module check under setEnabled detects that the
> caller is in a different module and refuses to make it accessible.
>
> regards,
>
>
> Andrew Dinn
> -----------
> Senior Principal Software Engineer
> Red Hat UK Ltd
> Registered in England and Wales under Company Registration No. 03798903
> Directors: Michael Cunningham, Michael ("Mike") O'Neill, Eric Shander
>


More information about the core-libs-dev mailing list