JDK-6332120 : File.deleteOnExit() with long file name causes buffer overflow
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 1.4.2
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2005-10-04
  • Updated: 2014-02-27
  • Resolved: 2006-08-03
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.2_13Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
Java HotSpot(TM) Client VM (build 1.5.0_05-b05, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Linux 2.6.12-1-K7 (on Debian Sarge)

EXTRA RELEVANT SYSTEM CONFIGURATION :
(none)

A DESCRIPTION OF THE PROBLEM :
Summary:

A deleteOnFile() invocation against the java.io.File object that stores a file name that could be longer than 4096 bytes (equal to PATH_MAX ??) when it gets decoded to the filesystem's encoding, causes severe memory corruption on Java VM termination, which leads to a bus error, or a segmentation fault. You can reproduce the exact problem with the attached code.

Technical Detail:

As far as I can tell from the result of reverse-engineering (I did not ever access to the source code), deleteOnExit() internally allocates the following structure by malloc() C-library function, fills the content of "buf" field with strcpy() ing the file name, and builds a linked list to use it in "onExit" handler:

struct OnExitHandler {
    struct OnExitHandler *nextHandler;
    void(*callback)(void *param);
    char buf[4096];
}

If this is the case, a buffer overflow that eventually induces a heap corruption can occur if the name of the file being associated to the structure is long enough to exceed the size of buf[] field. Since the structure is allocated in its exact size and the implementation of malloc() used here is publicly available, this flaw is easily exploitable to gain a shell, etc.

IMPACT:

Any program that takes an arbitrary file name from the user input to finally destroy it with deleteOnExit() is extremely vulnerable. For instance, an attacker can submit a malicious request to  a web application that stores uploaded files to a temporary directory with the same file names given in the request.




STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile & run the attached code.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
(None happens)
ACTUAL -
(Received SIGABRT signal)


ERROR MESSAGES/STACK TRACES THAT OCCUR :
*** glibc detected *** free(): invalid next size (normal): 0x080c8038 ***
Aborted


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.File;

public class J2SEVulnerabilityTest
{
	private static final int PATH_MAX = 4096;

	private static String generateArbitraryLengthOfString(int n) {
		StringBuffer buf = new StringBuffer(n);
		while (--n >= 0) {
			buf.append('#');
		}
		return buf.toString();
	}

	public static void main(String[] args) {
		File f = new File(generateArbitraryLengthOfString(PATH_MAX + 512));
		f.deleteOnExit();
	}
}

---------- END SOURCE ----------

Comments
EVALUATION DeleteOnExitTest.java can still crash JVMs on 1.4.2_11 and 1.5.0_u6, on Solaris and Linux.
2006-05-12

EVALUATION This is a 1.4.2 only issue now.
2005-10-07