[logback-user] SecurityManager issue using logback

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


Correct. getClassLoaderAsPrivileged  is not even used anywhere. That's 
the result of a compromise: http://jira.qos.ch/browse/LBCLASSIC-263

On 11/6/2011 2:47 AM, Ralph Goers wrote:
> What I find interesting is that IntelliJ says getClassLoaderAsPrivileged isn't even used by anything in Logback.
>
> Ralph
>
> On Nov 5, 2011, at 5:32 PM, 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