[logback-user] SecurityManager issue using logback

ceki ceki at qos.ch
Sun Nov 6 07:42:45 CET 2011



Keep in mind that the SecurityManager is usually installed by the
container very early in the container life cycle and one usually does
not change security managers on the fly, but your point is a good one
nonetheless.

On 11/6/2011 1:32 AM, Joern Huxhorn wrote:
> There is one issue with the code in http://goo.gl/zASBm, though:
> It checks for getClassLoader permission in a static code block only, i.e. when the class is initially loaded by the classloader,  and saves that information for later reference.
>
> I don't think that this is a valid optimization for precisely the reason that this permission can change during runtime (according to http://download.oracle.com/javase/1.4.2/docs/api/java/security/AccessController.html even per thread), for example if a different SecurityManager is installed.
>
> The method using the statically initialized boolean should probably look like this instead:
>
> public static ClassLoader getClassLoaderAsPrivileged(final Class clazz) {
>    try {
>      AccessController.checkPermission(new RuntimePermission("getClassLoader"));
>      return AccessController.doPrivileged(
>          new PrivilegedAction<ClassLoader>() {
>            public ClassLoader run() {
>              return clazz.getClassLoader();
>            }
>          });
>    } catch (AccessControlException e) {
>      return null;
>    }
> }
>
> Not sure if this would solve the problem at hand...
>
> Joern.
>
> On 05.11.2011, at 16:25, ceki wrote:
>
>>
>> Thanks for the sample project. I can confirm that I observe a
>> AccessControlException when logback is present. The
>> AccessControlException is not thrown if slf4j-nop, slf4j-simple or
>> slf4j-log4j are used as the slf4j binding.
>>
>> Although logback does not install its own SecurityManager or modify
>> the security configuration, it does attempt to determine whether it
>> has "getClassLoader" permission. See http://goo.gl/zASBm
>>
>> Here is the code in question:
>>
>>   AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
>>      public Boolean run() {
>>        try {
>>          AccessController.checkPermission(
>>                      new RuntimePermission("getClassLoader"));
>>          return true;
>>        } catch (AccessControlException e) {
>>          return false;
>>        }
>>      }
>>   });
>>
>>
>> If the privileged block above code is removed, then the
>> AccessControlException goes away. The privileged block looks quite
>> legitimate to me so I don't think it's a bug in logback.
>>
>> To convince yourself the the privileged block is key, you can remove
>> all logging related calls and all logging related dependencies, add
>> the privileged block at the beginning of the test. You should observe
>> an AccessControlException being thrown.
>>
>> --
>> Ceki
>> http://twitter.com/#!/ceki
>>
>>
>>
>> On 11/5/2011 1:42 PM, Andrew Bourgeois wrote:
>>> Ceki,
>>>
>>> I redid the test in a clean Maven project. I don't know if attachments
>>> will pass through, so:
>>>
>>> 1) pom.xml:
>>>
>>> <project xmlns="http://maven.apache.org/POM/4.0.0"
>>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>>> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
>>> http://maven.apache.org/maven-v4_0_0.xsd">
>>> <modelVersion>4.0.0</modelVersion>
>>> <name>test</name>
>>> <groupId>be.test.fun</groupId>
>>> <artifactId>test</artifactId>
>>> <version>0.1.0-RC1</version>
>>> <dependencies>
>>> <dependency>
>>> <groupId>org.slf4j</groupId>
>>> <artifactId>slf4j-api</artifactId>
>>> <version>1.6.0</version>
>>> </dependency>
>>>
>>> <dependency>
>>> <groupId>log4j</groupId>
>>> <artifactId>log4j</artifactId>
>>> <version>1.2.16</version>
>>> </dependency>
>>> <dependency>
>>> <groupId>org.slf4j</groupId>
>>> <artifactId>slf4j-log4j12</artifactId>
>>> <version>1.6.0</version>
>>> </dependency>
>>>
>>> <!--dependency>
>>> <groupId>ch.qos.logback</groupId>
>>> <artifactId>logback-core</artifactId>
>>> <version>1.0.0</version>
>>> </dependency>
>>> <dependency>
>>> <groupId>ch.qos.logback</groupId>
>>> <artifactId>logback-classic</artifactId>
>>> <version>1.0.0</version>
>>> </dependency-->
>>>
>>> <dependency>
>>> <groupId>junit</groupId>
>>> <artifactId>junit</artifactId>
>>> <version>4.4</version>
>>> <scope>test</scope>
>>> </dependency>
>>> </dependencies>
>>> <build>
>>> <resources>
>>> </resources>
>>> <plugins>
>>> <plugin>
>>> <artifactId>maven-compiler-plugin</artifactId>
>>> <configuration>
>>> <source>1.6</source>
>>> <target>1.6</target>
>>> <verbose>true</verbose>
>>> </configuration>
>>> </plugin>
>>> </plugins>
>>> </build>
>>> </project>
>>>
>>> 2) The JUnit test:
>>>
>>> package be.test.fun;
>>>
>>> import org.junit.Test;
>>> import java.rmi.RMISecurityManager;
>>> import org.slf4j.Logger;
>>> import org.slf4j.LoggerFactory;
>>>
>>> public class SecurityManagerTest {
>>>
>>> @Test
>>> public void securityManagerWithLogs() {
>>> Logger logger = LoggerFactory.getLogger(SecurityManagerTest.class);
>>>
>>> System.setProperty("java.security.policy",
>>> "./src/test/resources/java.policy");
>>> logger.debug("Policy location: {}",
>>> System.getProperty("java.security.policy"));
>>> if (System.getSecurityManager() == null) {
>>> System.setSecurityManager(new RMISecurityManager());
>>> }
>>> System.setProperty("java.security.policy",
>>> "./src/test/resources/java.policy");
>>> }
>>>
>>> // @Test
>>> // public void securityManagerWithoutLogs() {
>>> // System.setProperty("java.security.policy",
>>> "./src/test/resources/java.policy");
>>> // if (System.getSecurityManager() == null) {
>>> // System.setSecurityManager(new RMISecurityManager());
>>> // }
>>> // System.setProperty("java.security.policy",
>>> "./src/test/resources/java.policy");
>>> // }
>>> }
>>>
>>> 3) java.policy that you put into src/test.resources:
>>>
>>> grant {
>>> permission java.security.AllPermission;
>>> };
>>>
>>> So.... if you run this:
>>> -------------------------------------------------------
>>> T E S T S
>>> -------------------------------------------------------
>>> Running be.test.fun.SecurityManagerTest
>>> 2011-11-05 13:36:33,828 [main] DEBUG - (be.test.fun.SecurityManagerTest)
>>> - Policy location: ./src/test/resources/java.policy
>>> Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.201 sec
>>>
>>> Results :
>>>
>>> Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
>>>
>>> Now, comment the 2 LOG4J-related dependencies inside the POM, and
>>> uncomment the logback ones:
>>> -------------------------------------------------------
>>> T E S T S
>>> -------------------------------------------------------
>>> Running be.test.fun.SecurityManagerTest
>>> 13:38:04.222 [main] DEBUG be.test.fun.SecurityManagerTest - Policy
>>> location: ./src/test/resources/java.policy
>>> java.security.AccessControlException: access denied
>>> (java.lang.RuntimePermission setContextClassLoader)
>>> at
>>> java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
>>>
>>> at
>>> java.security.AccessController.checkPermission(AccessController.java:546)
>>> at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
>>> at java.lang.Thread.setContextClassLoader(Thread.java:1394)
>>> at
>>> org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:366)
>>>
>>> at
>>> org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021)
>>>
>>> [INFO]
>>> ------------------------------------------------------------------------
>>> [INFO] BUILD FAILURE
>>> [INFO]
>>> ------------------------------------------------------------------------
>>> [INFO] Total time: 2.202s
>>>
>>> And now comment the "securityManagerWithLogs" test method, and uncomment
>>> the "securityManagerWithoutLogs" one:
>>> -------------------------------------------------------
>>> T E S T S
>>> -------------------------------------------------------
>>> Running be.test.fun.SecurityManagerTest
>>> Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.105 sec
>>>
>>> Results :
>>>
>>> Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
>>>
>>> Do you have the same output?
>>>
>>> FYI:
>>>
>>> [xvepak at localhost test]$ mvn -version
>>> Apache Maven 3.0.1 (r1038046; 2010-11-23 11:58:32+0100)
>>> Java version: 1.6.0_23
>>> Java home: /home/xvepak/software/jdk1.6.0_23/jre
>>> Default locale: en_US, platform encoding: UTF-8
>>> OS name: "linux" version: "2.6.18-238.12.1.el5" arch: "i386" Family: "unix"
>>>
>>> Thank you for trying to help out!!
>>>
>>> Best regards
>>>
>>> Andrew Bourgeois
>>>
>>> -----Original Message----- From: ceki
>>> Sent: Saturday, November 05, 2011 1:03 AM
>>> To: logback users list
>>> Subject: Re: [logback-user] SecurityManager issue using logback
>>>
>>> On 05/11/2011 12:47 PM, Andrew Bourgeois wrote:
>>>
>>>> So to reformulate:
>>>> The exception IS thrown when we have SLF4J code
>>>> The exception ISN'T thrown when we remove the SLF4J.
>>>
>>> That's not what I observe. An exception is thrown in both cases.
>


-- 
Ceki
http://twitter.com/#!/ceki


More information about the Logback-user mailing list