https://bz.apache.org/bugzilla/show_bug.cgi?id=64582

            Bug ID: 64582
           Summary: SecurityClassLoad - CoyoteOutputStream
           Product: Tomcat 9
           Version: 9.0.36
          Hardware: Macintosh
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Catalina
          Assignee: dev@tomcat.apache.org
          Reporter: johnathan.gil...@contrastsecurity.com
  Target Milestone: -----

Created attachment 37351
  --> https://bz.apache.org/bugzilla/attachment.cgi?id=37351&action=edit
patch

A basic servlet application that prints a message to the ServletOutputStream
may fail unexpectedly with an AccessControlException when Tomcat is configured
to use a Java security policy and circumstances in the JVM defer loading the
CoyoteOutputStream class until org.apache.catalina.Response.getOutputStream()
is called.

I was able to reproduce this behavior on Tomcat 9.0.26, but not with 7.0.94 nor
8.5.43. The environment in testing is

openjdk version "1.8.0_222"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.222-b10, mixed mode)

Under normal circumstances, verbose:class logs indicate that HotSpot loads the
CoyoteOutputStream class during application initialization before handling any
requests; however, this class is not resolved until the application handles a
request and the servlet calls `Response.getOutputStream()` wherein the
CoyoteOutputStream is lazily initialized. Based on the JVM specification for
class loading and resolution, I don't believe there is anything compelling
HotSpot to load the `CoyoteOutputStream` class when it does; rather, this
appears to be an eager class load at HotSpot's discretion. This timing is
fortunate, because the application needs `CoyoteOutputStream` to be pre-loaded
prior to resolving it in the call to `Response.getOutputStream()`, since the
application does not have permissions to load classes in the
org.apache.catalina.connector package. In order to guarantee that HotSpot loads
CoyoteOutputStream before the user's application needs it, Tomcat should
include this class in its `SecurityClassLoad` utility (patch attached) which I
understand is built to handle these cases.

Without the proposed change to `SecurityClassLoad`, circumstances which affect
HotSpot's class loading could defer loading the `CoyoteOutputStream` until the
application calls `Response.getOutputStream()` thus causing an
AccessControlException. The only example I have of such a circumstance is the
inclusion of the Contrast Security Java agent. When the Contrast Security Java
agent (see
https://docs.contrastsecurity.com/installation-java.html#java-overview) is
added to the JVM via `CATALINA_OPTS`, the CoyoteOutputStream class is not
loaded during application initialization; rather, the class is loaded just
prior to resolving it when the CoyoteOutputStream field in Response is lazily
instantiated in `Response.getOutputStream()`.

```
> The server encountered an unexpected condition that prevented it from 
> fulfilling the 
> request.</p><p><b>Exception</b></p><pre>java.security.AccessControlException: 
> access denied (&quot;java.lang.RuntimePermission&quot; 
> &quot;accessClassInPackage.org.apache.catalina.connector&quot;)
       
java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
       
java.security.AccessController.checkPermission(AccessController.java:886)
        java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
        java.lang.SecurityManager.checkPackageAccess(SecurityManager.java:1564)
        sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:329)
        java.lang.ClassLoader.loadClass(ClassLoader.java:411)
        java.lang.ClassLoader.loadClass(ClassLoader.java:357)
       
org.apache.catalina.connector.Response.getOutputStream(Response.java:552)
       
org.apache.catalina.connector.ResponseFacade.getOutputStream(ResponseFacade.java:210)
       
com.contrastsecurity.testapp.servlet25.servletoutputstream.PrintServlet.doGet(PrintServlet.java:30)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
```

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to