Secure Coding mailing list archives
By default, the Verifier is disabled on .Net and Java
From: cradle at umd.edu (David Eisner)
Date: Thu, 04 May 2006 13:38:35 -0400
Dinis Cruz wrote:
Ok, I just did some further tests and I think I can say that Java (version 1.5.0_06) has similar verification issues to the ones I discovered on the .Net Framework (see links in my previous post).
[...]
This should prove that the verifier is not enabled by default on java files loaded from the local computer.
First, apologies to Dinis and Kevin for the mis-attribution. I agree, based on the various experiments, it looks like the bytecode verifier is still not enabled by default for locally loaded class files. I'm not sure why my randomly modified HelloWorld.class file behaved differently in the -verify / -noverify cases. If I have more time, I'll dig into it. As mentioned, the source code for the jdk is available under the Sun Community Source License. [1] Unfortunately, this license doesn't permit redistribution of code to non-licensees, so I'll just describe what I found when I took a (non-exhaustive) look. j2se/src/share/bin/java.c: java {-verify, -verifyremote, -noverify} are aliases for options passed to the Java Hotspot Virtual Machine. The options are aliased to -Xverify:all, -Xverify:remote, and -Xverify:none, respectively. These options, in turn, don't seem to be documented, at least not in the VM options documentation. [2] Ah, but they are documented elsewhere. [3] From that document: ----8<-------------- So, why all this verification? When class files are loaded (possibly over the network or from an untrusted source) into a virtual machine, there is no way of telling how its byte codes were generated. Basically, in most cases, you can't trust the source of the Java class files. In fact, the default verification setting in JRE 1.1 is to only verify classes loaded from over the network. So, anything installed locally, via CLASSPATH, is not verified. In JRE 1.1, if you have installed something locally from a third-party and want to even verify that, too, you can do that. Or, you can completely disable verification. The three settings are all options to the java and jre commands: * -verifyremote - only perform verification process on classes loaded over network (default) * -verify - verify everything * -noverify - verify nothing In JDK 1.2, the default setting for verification is the same only verify classes loaded over the network. However, the system classes are specified from something other than the CLASSPATH environment variable, and the command line options for verification differ. The system classes are specified by either the System property sun.boot.class.path or the command line option -Xbootclasspath:directories and jar files. This is automatically set for you by the JRE and should never need to be set manually. If you set it to add something yourself be sure to include the original defaults, too. With regards to verification, if you wish to manually control the level of verification, the options to the java command with the V1.2 JRE are as follows: * -Xverify:remote - only perform verification process on classes loaded over network (default) * -Xverify:all - verify everything * -Xverify:none - verify nothing If a verification error is encountered, instead of the JRE reporting a verification error or throwing an exception, it reports a can't find error, like: Can't find class MyClass. ----8<-------------- On the other hand, this message from the java-security mailing list archives [4] (from July 2001) seems to say something else: ----8<-------------- The "system classes" such as those in java.* that are contained in rt.jar are loaded by the bootstrap class loader built-in to the Java Virtual Machine. In Jave 2, the next class loader searched for classes is the extension class loader which looks for classes in the jar files in the lib/ext directory where the Java Runtime Environment is installed. The so-called "system class loader" actually loads the application classes found from the -classpath command line argument or the CLASSPATH environment variable. Yes, the name "system class loader" is confusing. It is named that way for historical reasons when both core system classes as well as application classes were all loaded by the bootstrap class loader in JDK 1.1.
I thought that, by default, the Java API classes (rt.jar) are the only
ones
that dont go thru the ByteCode Verifier?
You are correct again. By default, all classes go through the bytecode verifier except for those loaded by the bootstrap class loader. You can change this behavior through the use of command line arguments. This is because all classes except for those loaded by the bootstrap class loader can by granted fine-grained security permissions. In order to prevent those classes from cheating and trying to get more permissions than they have been granted we need to verify them. Classes loaded by the bootstrap class loader are always granted "AllPermission" and cannot be granted fewer permissions. These classes are trusted as part of the core Java runtime. Therefore there is no need to verify them at runtime. ----8<-------------- This seems to jibe with what's in the Hotspot VM source code: If you're curious, take a look at jdk-1_5_0_scsl/hotspot/src/share/vm/runtime/arguments.cpp and jdk-1_5_0_scsl/hotspot/src/share/vm/runtime/globals.hpp jdk-1_5_0_scsl/hotspot/src/share/vm/runtime/verifier.cpp (start with Verifier::verify_byte_codes) paying attention to the BytecodeVerificationRemote and BytecodeVerificationRemote booleans. Semantically, "Local" seems to mean the class loader for the class is null, and "Remote" means it isn't. Consulting the Classs.getClassLoader() public api documentation [5]: "Returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader. This method will return null in such implementations if this class was loaded by the bootstrap class loader." So this would seem to suggest that non-bootstrap classes *are* bytecode verified. Here's another experiment: ----8<------------------ $ cat HelloWorld.java public class HelloWorld { public static void main( String[] args ) { System.out.println( "HelloWorld class loader: " + HelloWorld.class.getClassLoader() ); System.out.println( "Math class loader: " + Math.class.getClassLoader() ); System.exit(0); } } $ java -cp . HelloWorld HelloWorld class loader: sun.misc.Launcher$AppClassLoader at e39a3e Math class loader: null ----8<------------------ What determines when access to a private member is illegal? Is it, in fact, the bytecode verifier? -David [1] http://www.sun.com/software/communitysource/j2se/java2/download.xml [2] http://java.sun.com/docs/hotspot/VMOptions.html [3] http://java.sun.com/developer/onlineTraining/Security/Fundamentals/Security.html [4] http://archives.java.sun.com/cgi-bin/wa?A2=ind0107&L=java-security&D=0&P=1305 [5] http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getClassLoader()
Current thread:
- By default, the Verifier is disabled on .Net and Java, (continued)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 12)
- By default, the Verifier is disabled on .Net and Java Stephen de Vries (May 13)
- By default, the Verifier is disabled on .Net and Java Wall, Kevin (May 02)
- By default, the Verifier is disabled on .Net and Java David Eisner (May 03)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 03)
- By default, the Verifier is disabled on .Net and Java Tim Hollebeek (May 04)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 12)
- By default, the Verifier is disabled on .Net and Java David Eisner (May 03)
- By default, the Verifier is disabled on .Net and Java Michael Silk (May 03)
- By default, the Verifier is disabled on .Net and Java Dinis Cruz (May 03)
- By default, the Verifier is disabled on .Net and Java David Eisner (May 04)
- By default, the Verifier is disabled on .Net and Java Stephen de Vries (May 04)
- By default, the Verifier is disabled on .Net and Java Michael Silk (May 04)