Uploaded image for project: 'Undertow'
  1. Undertow
  2. UNDERTOW-1558

security-manager and reflection permissions in DirectByteBufferDeallocator/undertow

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • 2.0.22.Final
    • 2.0.21.Final
    • Core
    • None
    • Hide

      I have reproduced the issue with a modified version of the helloworld-ssl that contains the following doPost method in the HelloWorldServlet:

        public void doPost(HttpServletRequest request, HttpServletResponse response)
          throws IOException
        {
          int bytesRead = 0;
          
          BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
          int b = br.read();
          while (b != -1)
          {
            bytesRead++;
            b = br.read();
          }
          System.out.println("Bytes read: " + bytesRead);
        }
      

      Configure the buffers to be very restricted:

      /subsystem=undertow/byte-buffer-pool=pool:add(max-pool-size=2, buffer-size=256)
      /subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=buffer-pool, value=newpool)
      

      Then just launch at least two threads with the following curl:

      while [ true ]
      do
      curl -s -o /dev/null -w "%{http_code}\n" -k -d "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" https://localhost:8443//helloworld-ssl/HelloWorld
      done
      

      The two threads triggers the free of a buffer and the exception is thrown. Look the server.log for the "Permission check failed".

      Show
      I have reproduced the issue with a modified version of the helloworld-ssl that contains the following doPost method in the HelloWorldServlet: public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { int bytesRead = 0; BufferedReader br = new BufferedReader( new InputStreamReader(request.getInputStream())); int b = br.read(); while (b != -1) { bytesRead++; b = br.read(); } System .out.println( "Bytes read: " + bytesRead); } Configure the buffers to be very restricted: /subsystem=undertow/byte-buffer-pool=pool:add(max-pool-size=2, buffer-size=256) /subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=buffer-pool, value=newpool) Then just launch at least two threads with the following curl: while [ true ] do curl -s -o /dev/null -w "%{http_code}\n" -k -d "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" https://localhost:8443//helloworld-ssl/HelloWorld done The two threads triggers the free of a buffer and the exception is thrown. Look the server.log for the "Permission check failed".

      When using an application that uses SSL, the class DirectByteBufferDeallocator is wrongly initialized if the security manager is enabled. That class is only used when a buffer should be freed so it's complicated to trigger the error. The exception generated is like the following:

      2019-06-13 09:21:47,862 ERROR [io.undertow] (default task-1) UT005091: Failed to initialize DirectByteBufferDeallocator: java.security.AccessControlException: WFSM000001: Permission check failed (permission "("java.lang.reflect.ReflectPermission" "suppressAccessChecks")" in code source "(vfs:/content/helloworld-ssl.war/WEB-INF/classes <no signer certificates>)" of "ModuleClassLoader for Module "deployment.helloworld-ssl.war" from Service Module Loader")
              at org.wildfly.security.manager.WildFlySecurityManager.checkPermission(WildFlySecurityManager.java:295)
              at org.wildfly.security.manager.WildFlySecurityManager.checkPermission(WildFlySecurityManager.java:192)
              at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:128)
              at io.undertow.server.DirectByteBufferDeallocator.<clinit>(DirectByteBufferDeallocator.java:37)
              at io.undertow.server.DefaultByteBufferPool.queueIfUnderMax(DefaultByteBufferPool.java:209)
              at io.undertow.server.DefaultByteBufferPool.freeInternal(DefaultByteBufferPool.java:201)
              at io.undertow.server.DefaultByteBufferPool.access$200(DefaultByteBufferPool.java:40)
              at io.undertow.server.DefaultByteBufferPool$DefaultPooledBuffer.close(DefaultByteBufferPool.java:271)
              at io.undertow.servlet.spec.ServletInputStreamImpl.read(ServletInputStreamImpl.java:179)
              at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
              at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
              at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
              at java.io.InputStreamReader.read(InputStreamReader.java:184)
              at java.io.BufferedReader.fill(BufferedReader.java:161)
              at java.io.BufferedReader.read(BufferedReader.java:182)
              at org.jboss.as.quickstarts.helloworld.HelloWorldServlet.doPost(HelloWorldServlet.java:68)
              at javax.servlet.http.HttpServlet.service(HttpServlet.java:706)
              at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
              ...
      

            rhn-support-tmiyargi Teresa Miyar Gil (Inactive)
            rhn-support-tmiyargi Teresa Miyar Gil (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: