Bug 57281 - Tomcat fails to call method of non-public filter class configured via Servlet 3.0 API when running with SecurityManager
Tomcat fails to call method of non-public filter class configured via Servlet...
Status: RESOLVED FIXED
Product: Tomcat 7
Classification: Unclassified
Component: Catalina
7.0.52
PC All
: P2 normal (vote)
: ---
Assigned To: Tomcat Developers Mailing List
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2014-11-28 23:55 UTC by Konstantin Kolinko
Modified: 2015-07-09 07:56 UTC (History)
1 user (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Konstantin Kolinko 2014-11-28 23:55:12 UTC
There is a report on StackOverflow that Spring Boot (1.1.6) application fails on Tomcat 7.0.52 when running with SecurityManager enabled.

https://stackoverflow.com/questions/27189047/springboot-webapp-under-java-securitymanager-throws-exceptions-when-granted-allp

The error is
[[[
java.lang.IllegalAccessException: Class org.apache.catalina.security.SecurityUtil$1 can not access a member of class org.springframework.boot.context.web.ErrorPageFilter with modifiers "public"
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:109) ~[na:1.7.0_65]
    at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:261) ~[na:1.7.0_65]
    at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:253) ~[na:1.7.0_65]
    at java.lang.reflect.Method.invoke(Method.java:599) ~[na:1.7.0_65]
    at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:277) ~[catalina.jar:7.0.52]
    at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:274) ~[catalina.jar:7.0.52]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_65]
    at javax.security.auth.Subject.doAsPrivileged(Subject.java:536) ~[na:1.7.0_65]
    at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:309) ~[catalina.jar:7.0.52]
    at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:249) ~[catalina.jar:7.0.52]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237) ~[catalina.jar:7.0.52]
    at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:55) ~[catalina.jar:7.0.52]
    at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:191) ~[catalina.jar:7.0.52]
    at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:187) ~[catalina.jar:7.0.52]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_65]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:186) ~[catalina.jar:7.0.52]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) ~[catalina.jar:7.0.52]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.52]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [catalina.jar:7.0.52]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) [catalina.jar:7.0.52]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) [catalina.jar:7.0.52]
    at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683) [catalina.jar:7.0.52]
    at ch.qos.logback.access.tomcat.LogbackValve.invoke(LogbackValve.java:178) [logback-access-1.0.13.jar:na]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.52]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [catalina.jar:7.0.52]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) [tomcat-coyote.jar:7.0.52]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) [tomcat-coyote.jar:7.0.52]
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313) [tomcat-coyote.jar:7.0.52]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_65]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_65]
    at java.lang.Thread.run(Thread.java:745) [na:1.7.0_65]
]]]

Looking at the current sources of Spring Boot, the org.springframework.boot.context.web.ErrorPageFilter class is not public, but package-visible. Reflection call fails, as Java Language rules prohibit access to that class.

Such filter cannot be configured via web.xml (as its constructor is not accessible), but can be configured programmatically via ServletContext.addFilter(String, Filter). It is a rare situation, but I think that it is a valid one.

My idea of the fix is that method lookup in catalina SecurityUtil shall not use targetObject.getClass().getMethod(..), but Filter.class.getMethod(). My expectation is that it will be allowed to invoke java.lang.reflect.Method declared by javax.servlet.Filter class on the targetObject object regardless of accessibility of targetObject class, but testing is needed.

A bonus point is that the method cache shall become smaller.
Comment 1 Mark Thomas 2014-12-03 21:34:35 UTC
Trivial test case to reproduce:
https://github.com/markt-asf/tomcat-bug57281

I'm moving on to testing the proposed fix.
Comment 2 Mark Thomas 2014-12-03 22:16:12 UTC
I can confirm that the proposed fix works. I'll commit it once the svn server comes back to life.
Comment 4 Mark Thomas 2014-12-05 14:07:04 UTC
Fixed in trunk, 8.0.x (for 8.0.16 onwards) and 7.0.x (for 7.0.38 onwards).
Comment 5 Johno Crawford 2015-07-09 07:56:36 UTC
Unfortunately the fix for this issue caused a regression with Comet servlets, I opened a new bug with all the details and proposed patch https://bz.apache.org/bugzilla/show_bug.cgi?id=58116