Bug 59247

Summary: Using the IBM JDK with the security manager results in java.lang.RuntimePermission warning
Product: Tomcat 8 Reporter: Coty Sutherland <csutherl>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: minor    
Priority: P2    
Version: 8.0.32   
Target Milestone: ----   
Hardware: PC   
OS: Linux   
Attachments: policy patch proposal
More files from testing
java.security.debug stack trace
stack trace for tomcat6 denial
patch proposal to resolve the tomcat6 denial
Other patch

Description Coty Sutherland 2016-03-29 14:58:42 UTC
Created attachment 33707 [details]
policy patch proposal

When using the IBM JDK and the security manager the following warnings are logged:

WARNING [localhost-startStop-1] org.apache.juli.ClassLoaderLogManager.readConfiguration Reading logging.properties is not permitted in some context. See "per context logging" in the default catalina.policy file.
WARNING [localhost-startStop-1] org.apache.juli.ClassLoaderLogManager.readConfiguration Original error was: Access denied ("java.lang.RuntimePermission" "accessClassInPackage.org.apache.catalina.loader")

I do not observe any negative effects of this warning, however I am only doing minimal testing and would like someone to review it to validate whether or not it is an issue. I assume that something not being able to load the logging.properties means that it isn't logging either.

It looks like adding the permission to the catalina.policy resolves the warning. I am attaching the patch which seems to work for me along with a few other files for review. Note that this does not seem to occur on trunk (though it does throw some warnings also), but it does on tomcat8 and previous versions. Also note that the added permission in the patch proposal does not exist in trunk, so I'm not sure if it is the way to go or not.
Comment 1 Coty Sutherland 2016-03-29 15:01:17 UTC
Created attachment 33708 [details]
More files from testing

In this attachment I've included the catalina.out logs from the tomcat8 tests using IBM Java 7 and 8, tomcat9 catalina.out from IBM Java 8, and the java -version output from each java version.
Comment 2 Coty Sutherland 2016-03-29 15:11:22 UTC
Created attachment 33709 [details]
java.security.debug stack trace

I forgot to include the stack trace in the previous tarball.
Comment 3 Remy Maucherat 2016-03-30 18:32:08 UTC
There's nothing about the webapp in the stacktrace, so it shouldn't be added in that section, which is the most sensitive.

The permission can be added to the following section instead:
grant codeBase "file:${catalina.home}/bin/tomcat-juli.jar" {

Can you verify it works ?
Comment 4 Coty Sutherland 2016-03-30 18:50:08 UTC
Yes, testing confirms that adding the permission to the tomcat-juli.jar section resolves the issue as well.
Comment 5 Remy Maucherat 2016-03-30 19:18:42 UTC
Ok, so it will be in 9M5, 8.5.1, 8.0.34, 7.0.69 and 6.0.46, since it likely applies to all the branches.
Comment 6 Coty Sutherland 2016-03-30 19:47:37 UTC
Created attachment 33712 [details]
stack trace for tomcat6 denial

I accidentally neglected to test tomcat6 earlier, but the addition to the policy isn't quite enough for it. Tomcat7+ works with the addition. Here is the stack trace from the additional exception.
Comment 7 Coty Sutherland 2016-03-30 19:48:54 UTC
Created attachment 33713 [details]
patch proposal to resolve the tomcat6 denial

And here is a patch that seemingly resolves the issue for review. It looks like the examples webapp wants to use a class in o.a.catalina and it's getting denied. I added a section for the examples webapp much like the manager and host-manager section and put the permission there. Hopefully I did it correctly :)
Comment 8 Konstantin Kolinko 2016-03-30 20:02:14 UTC
From "java.security.debug stack trace" attachment,

[[[
java.lang.Exception: Stack trace
	at java.security.AccessController.throwACE(AccessController.java:144)
	at java.security.AccessController.checkPermissionHelper(AccessController.java:217)
	at java.security.AccessController.checkPermission(AccessController.java:349)
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:562)
	at java.lang.SecurityManager.checkPackageAccess(SecurityManager.java:1655)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:322)
	at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:836)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:823)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:803)
	at org.apache.catalina.loader.WebappClassLoaderBase.findResource(WebappClassLoaderBase.java:903)
	at org.apache.juli.ClassLoaderLogManager.readConfiguration(ClassLoaderLogManager.java:429)
	at org.apache.juli.ClassLoaderLogManager$2.run(ClassLoaderLogManager.java:402)
	at org.apache.juli.ClassLoaderLogManager$2.run(ClassLoaderLogManager.java:398)
	at java.security.AccessController.doPrivileged(AccessController.java:594)
	at org.apache.juli.ClassLoaderLogManager.getClassLoaderInfo(ClassLoaderLogManager.java:398)
	at org.apache.juli.ClassLoaderLogManager.getLogger(ClassLoaderLogManager.java:230)
	at java.util.logging.LogManager.demandLogger(LogManager.java:562)
	at java.util.logging.Logger.demandLogger(Logger.java:466)
	at java.util.logging.Logger.getLogger(Logger.java:513)
	at org.apache.juli.logging.DirectJDKLog.<init>(DirectJDKLog.java:68)
	at org.apache.juli.logging.DirectJDKLog.getInstance(DirectJDKLog.java:188)
	at org.apache.juli.logging.LogFactory.getInstance(LogFactory.java:115)
	at org.apache.juli.logging.LogFactory.getLog(LogFactory.java:206)
	at org.apache.catalina.core.ContainerBase.getLogger(ContainerBase.java:363)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5143)
]]]

The line WebappClassLoaderBase.java:903 where it happens is

>         ResourceEntry entry = resourceEntries.get(path);

so IBM JDK refuses WebappClassLoaderBase's right to load class from the same package and from the same classloader.

This is rather odd behaviour. Isn't it a bug in IBM JDK?

Another thing is that I do not understand is why stacktrace goes into sun.misc.Launcher$AppClassLoader. The ResourceEntry class shall be loaded by URLClassLoader() -- the one that loads classes from ${catalina.home}/lib/*.jar -- created by o.a.c.startup.ClassLoaderFactory during bootstrap time.

Maybe it tries to load something else besides that class, or this is a call to a parent classloader,


I think that while allowing "accessClassInPackage.org.apache.catalina.loader" permit to tomcat-juli.jar is rather safe, this permit does not have enough grounds. (Formally: -1)

I think that this can be solved by preloading the org.apache.catalina.loader.ResourceEntry class.

a. In an existing version of Tomcat the class can be preloaded by adding its name to "classesToInitialize" attribute of a JreMemoryLeakPreventionListener configured in server.xml

b. Permanent solution is to preload the class via org.apache.catalina.security.SecurityClassLoad class, like many others.


[1] http://tomcat.apache.org/tomcat-8.0-doc/config/listeners.html#JRE_Memory_Leak_Prevention_Listener_-_org.apache.catalina.core.JreMemoryLeakPreventionListener
Comment 9 Remy Maucherat 2016-03-30 20:50:21 UTC
Evidently there's a "bug" somewhere if only the IBM JDK does this. However, since this is only added to JULI, adding it is probably not a big issue [which is why I did it], so having a workaround sounds acceptable to me.

I will challenge your veto on the grounds that it doesn't cause any harm. Let's see if someone seconds it.
Comment 10 Coty Sutherland 2016-04-06 12:00:57 UTC
It looks like I should also note that this issue does affect tomcat6, tomcat7, and tomcat8 on IBM Java 7 and IBM Java 8. 

There are multiple warnings in tomcat6 (the RuntimePermission denial for accessClassInPackage.org.apache.catalina in the examples webapp, which I provided another patch suggestion for after this was fixed initially, and accessClassInPackage.org.apache.catalina.loader) plus messages regarding the deprecation of Manager.setMaxInactiveInterval()), tomcat7 and tomcat8 have the same warning regarding the RuntimePermission denial of accessClassInPackage.org.apache.catalina.loader, and tomcat9 seems unaffected (doesn't log the warning other than warnings about logging.properties in the webapps).
Comment 11 Konstantin Kolinko 2016-04-06 12:10:21 UTC
(In reply to Coty Sutherland from comment #7)
> Created attachment 33713 [details]
> patch proposal to resolve the tomcat6 denial
> 
> And here is a patch that seemingly resolves the issue for review. It looks
> like the examples webapp wants to use a class in o.a.catalina and it's
> getting denied. I added a section for the examples webapp much like the
> manager and host-manager section and put the permission there. Hopefully I
> did it correctly :)

Comment on this Tomcat 6 patch:

The issue:

> WARNING: WebappClassLoader.findClassInternal(chat.ChatServlet) security exception: Access denied ("java.lang.RuntimePermission" "accessClassInPackage.org.apache.catalina")

1. I am -1 on adding this permission by default. If you are security conscious, you should not have the examples webapp installed. This is mentioned in "Security Considerations" page (available in Tomcat 7 and later documentation). [1]

This issue is originally known as bug 48218 and was resolved by package name change in Tomcat 7.



2. It is worth adding this configuration fragment as commented-out example in catalina.policy.

[1] https://tomcat.apache.org/tomcat-7.0-doc/security-howto.html#Examples
Comment 12 Coty Sutherland 2016-04-06 12:20:31 UTC
That makes perfect sense to me. You already have to do some configuration things to use the security manager, so adding it as a comment in the policy (like the ones for the manager and host-manager apps) and then noting that in docs is a good solution I think. I only offered it because it seemingly resolved the issue and wanted feedback from you folks on whether or not it made sense.
Comment 13 Remy Maucherat 2016-04-06 12:22:44 UTC
(In reply to Konstantin Kolinko from comment #11)

Can you demonstrate that no actual webapps besides the example could be affected by the issue ? This would effectively make the workaround rather useless.
Comment 14 Konstantin Kolinko 2016-04-06 12:32:14 UTC
(In reply to Remy Maucherat from comment #13)
> (In reply to Konstantin Kolinko from comment #11)
> 
> Can you demonstrate that no actual webapps besides the example could be
> affected by the issue ? This would effectively make the workaround rather
> useless.

This is originally known as bug 48218. It affects the web applications using Comet API.

In the examples webapp it affects the ChatServlet servlet only -- the servlet fails to load, but the rest of web application functions correctly.

It was solved by moving the Comet API classes into a separate package in Tomcat 7 and adding permission for that separate package - r833510.
Comment 15 Konstantin Kolinko 2016-04-06 12:58:42 UTC
(In reply to Remy Maucherat from comment #9)
> Evidently there's a "bug" somewhere if only the IBM JDK does this. However,
> since this is only added to JULI, adding it is probably not a big issue
> [which is why I did it], so having a workaround sounds acceptable to me.
> 
> I will challenge your veto on the grounds that it doesn't cause any harm.
> Let's see if someone seconds it.

Regarding the tomcat 9 patch (juli issue):

1. Allowing "accessClassInPackage.org.apache.catalina.loader" to any web application, as proposed by original patch, is not good.

A web application should not have reflective access to WebappClassLoader.

2. Adding this permission for tomcat-juli.jar, as implemented by r1737149, implies that the call chain does not have web application code in it.

If it has only Tomcat code in it, it means that this solves this specific use case. It is not some generic feature available to web applications.

3. Preloading a class is how we solved similar issues in the past.

Personally, I think that preloading a class provides better life cycle for the Class. The class is explicitly loaded by System classloader. The WebappClassLoader is not involved.

If the class uses logging, it will use configuration provided by System classloader, not one provided by TCCL.


The trick with preloading is that you need to know what class needs to be loaded. Adding a permission is easier, as this is what java.security.debug logging shows you, but it is harder to evaluate the consequences.

From 2. I do not see much consequences (as web application code is not in the call chain), but I do not see much benefits either.


Preloading the class can be tested by adding the class name to the "classesToInitialize" attribute of a JreMemoryLeakPreventionListener in server.xml [2]

[2] http://tomcat.apache.org/tomcat-6.0-doc/config/listeners.html
Comment 16 Remy Maucherat 2016-04-06 13:04:20 UTC
For starters, I will revert the workaround from trunk and 8.5 since it doesn't apply.

About preloading, ok, but it's a code change for a workaround. I don't see why classloading access by JULI is bad, after all it is toying with the classloader as is.
Comment 17 Konstantin Kolinko 2016-04-06 13:30:27 UTC
(In reply to Remy Maucherat from comment #16)
> For starters, I will revert the workaround from trunk and 8.5 since it
> doesn't apply.
> 
> About preloading, ok, but it's a code change for a workaround. I don't see
> why classloading access by JULI is bad, after all it is toying with the
> classloader as is.

Regarding this particular accessClassInPackage permission - I guess that I am still under impression of CVE-2010-1622 [3] that used to manipulate the classloader. Though that particular attack vector was closed by r966292 / r966750.

[3] http://www.securityfocus.com/archive/1/511877
Comment 18 Remy Maucherat 2016-04-06 21:59:23 UTC
Created attachment 33735 [details]
Other patch

Based on preloading ResourceEntry

Coty, can you check that this patch actually works as well with Tomcat 8 ?
Comment 19 Coty Sutherland 2016-04-07 13:05:09 UTC
Remy,

I just tested that patch with tomcat-8.0.x/trunk (and tomcat-7.0.x/trunk) and it looks good to me.