Bug 60683

Summary: Using the IBM JDK with the security manager results in a NullPointerException for requests to some JSPs
Product: Tomcat 8 Reporter: Coty Sutherland <csutherl>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 8.0.x-trunk   
Target Milestone: ----   
Hardware: PC   
OS: Linux   

Description Coty Sutherland 2017-02-02 18:31:39 UTC
When using the IBM JDK (version 7) and the security manager requests to some JSPs return a 500 status and an NPE is logged. The odd thing is that you can make numerous requests to / and get a 500 every time, but after you make a request to /examples/jsp/dates/date.jsp, everything works fine. I'm not exactly sure what's causing that, but IBM JDK is weird so...

Steps to reproduce:

1. ./catalina.sh start -security

2. Make a request:

$ curl -I http://localhost:8080/ | head -n1
HTTP/1.1 500 Internal Server Error

3. Check the catalina.out log for the following:

java.lang.NullPointerException
	at org.apache.catalina.connector.OutputBuffer.realWriteChars(OutputBuffer.java:464)
	at org.apache.tomcat.util.buf.CharChunk.flushBuffer(CharChunk.java:393)
	at org.apache.catalina.connector.OutputBuffer.close(OutputBuffer.java:279)
        ....

Additional information:

I narrowed down the problem to an unexpected access denial exception being returned from OutputBuffer:583:

583        conv = encoders.get(enc);
584        if (conv == null) {
585            if (Globals.IS_SECURITY_ENABLED){

I added a try/catch and e.printStackTrace() and found the following exception happens within the encoders.get() call on line 583 ONLY when using IBM JDK:

java.security.AccessControlException: Access denied ("java.lang.RuntimePermission" "accessClassInPackage.org.apache.tomcat.util.buf")
        at java.security.AccessController.throwACE(AccessController.java:121)
        at java.security.AccessController.checkPermission(AccessController.java:230)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:563)
        at java.lang.SecurityManager.checkPackageAccess(SecurityManager.java:1617)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:323)
        at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:778)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:760)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:741)
        at org.apache.catalina.connector.OutputBuffer.setConverter(OutputBuffer.java:586)
        ....

Knowing the exception it was pretty easy to fix with a policy update, but I'm opening this bug because I don't know if this is feasible or not (I don't know the security policy well enough). Changing the catalina.policy's RuntimePermissions on the org.apache.tomcat package from:

    permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat";

to either:

    permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.*";

or (and more targeted to the issue):

    permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.util.buf";

works well. Are either of these suggestions a feasible solution?
Comment 1 Coty Sutherland 2017-02-02 18:32:30 UTC
I meant to add accessClassInPackage.org.apache.tomcat.util.buf in addition to the accessClassInPackage.org.apache.tomcat permission, not replace it.
Comment 2 Remy Maucherat 2017-02-02 21:27:41 UTC
(In reply to Coty Sutherland from comment #0)
> When using the IBM JDK (version 7) and the security manager requests to some
> JSPs return a 500 status and an NPE is logged. The odd thing is that you can
> make numerous requests to / and get a 500 every time, but after you make a
> request to /examples/jsp/dates/date.jsp, everything works fine. I'm not
> exactly sure what's causing that, but IBM JDK is weird so...

It's probably a buffering issue, / is a bigger page most likely, so it is flushing from the JSP and the classloading is then more likely to fail with weird JDKs (if Tomcat flushes itself, no problem !). Once the class is loaded, the error should go away. For this sort of issue, I often prefer preloading over adding to the policy, but both have been done.
Comment 3 Coty Sutherland 2017-02-02 22:09:03 UTC
Ha, a buffering problem makes sense given the package the problem is in :)

Preloading the C2BConverter class solves the problem.
Comment 4 Remy Maucherat 2017-02-03 16:07:18 UTC
I added preloading of the class, also including B2CConverter since it's possible reader use in a webapp might cause the same issue on that JVM. Since it's using a PA, it means the class is being loaded before running it due to the PrivilegedExceptionAction<C2BConverter>, while other JVMs don't do that.

It will be in 9M18, 8.5.12, 8.0.42, 7.0.76, but I didn't port it to 6.0.x.