javaapiosgispoof

How to spoof a java package (and thus a part of the API) in OSGi?


Is it possible to spoof a part of the standard Java API, by exporting your own bundle that replaces this API? Of course with the same interfaces.

Would it then be possible for other bundles, not to notice that actually they aren't using the java package, but your own package.


Solution

  • In principle this is possible. Only catch is that if you specify a class in the 'java' package, the sun classloader will forbid it:

    Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.io
        at java.lang.ClassLoader.preDefineClass(ClassLoader.java:480)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
        at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
    

    In order to circumvent the problem, you need to provide your extra classes on the boot classpath:

    $ java -Xbootclasspath:/home/user/Desktop/:/home/user/Desktop/rt.jar java.io.Hack
    hacked
    

    You can then also override system files, for instance java.io.File:

    $ java -Xbootclasspath:/home/user/Desktop/:/home/user/Desktop/rt.jar java.io.File
    Error occurred during initialization of VM
    java.lang.NoSuchFieldError: separatorChar
        at java.lang.Runtime.loadLibrary0(Runtime.java:819)
        at java.lang.System.loadLibrary(System.java:1030)
        at java.lang.System.initializeSystemClass(System.java:1077)
    

    (showing that we just overrode java.io.File)

    So you can override system classes, the trick is that you must have access to the virtual machine. You can't do it on the fly, which of course is due to security restrictions.