Return-Path: Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: (qmail 69839 invoked from network); 10 Jul 2008 16:59:02 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 10 Jul 2008 16:59:02 -0000 Received: (qmail 98061 invoked by uid 500); 10 Jul 2008 16:59:00 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 98020 invoked by uid 500); 10 Jul 2008 16:59:00 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 97977 invoked by uid 99); 10 Jul 2008 16:59:00 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 10 Jul 2008 09:59:00 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 10 Jul 2008 16:58:15 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 840FE23889F7; Thu, 10 Jul 2008 09:58:38 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r675648 - in /db/derby/code/branches/10.3/java: engine/org/apache/derby/iapi/util/ engine/org/apache/derby/impl/services/monitor/ engine/org/apache/derby/impl/services/timer/ testing/org/apache/derbyTesting/functionTests/util/ Date: Thu, 10 Jul 2008 16:58:37 -0000 To: derby-commits@db.apache.org From: kmarsden@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080710165838.840FE23889F7@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: kmarsden Date: Thu Jul 10 09:58:36 2008 New Revision: 675648 URL: http://svn.apache.org/viewvc?rev=675648&view=rev Log: DERBY-3745 Derby can leak classloaders in an app server environment Added: db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/util/PrivilegedThreadOps.java (with props) Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/services/monitor/BaseMonitor.java db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/services/timer/SingletonTimerFactory.java db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/util/derby_tests.policy Added: db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/util/PrivilegedThreadOps.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/util/PrivilegedThreadOps.java?rev=675648&view=auto ============================================================================== --- db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/util/PrivilegedThreadOps.java (added) +++ db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/util/PrivilegedThreadOps.java Thu Jul 10 09:58:36 2008 @@ -0,0 +1,97 @@ +/* + + Derby - Class org.apache.derby.iapi.util.PrivilegedThreadOps + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + */ + +package org.apache.derby.iapi.util; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +/** + * A collection of operations on {@link java.lang.Thread} that wraps the + * operations in privileged block of code. + *

+ * Derby needs to use privileged blocks in some places to avoid + * {@link SecurityException}s being thrown, as the required privileges are + * often granted to Derby itself, but not the higher level application code. + *

+ * Feel free to add new operations as they are needed. This class is not + * intended to implement the full set of operations defined by + * {@link java.lang.Thread}. + */ + +public class PrivilegedThreadOps { + + /** + * Sets the context ClassLoader for this Thread. The context ClassLoader + * can be set when a thread is created, and allows the creator of the + * thread to provide the appropriate class loader to code running in + * the thread when loading classes + * and resources. + * + * First, if there is a security manager, its checkPermission + * method is called with a + * RuntimePermission("setContextClassLoader") permission + * to see if it's ok to set the context ClassLoader.. + * @param t Thread for which we are setting the context class loader + * @param cl the context class loader for t + */ + public static void setContextClassLoader(final Thread t, final ClassLoader cl) { + AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + t.setContextClassLoader(cl); + return null; + } + }); + } + + /** + * Set the thread's context class loader if privileged. If not ignore + * security exception and continue. + * @param t Thread for which we are setting the context class loader + * @param cl the context class loader for t + */ + public static void setContextClassLoaderIfPrivileged(Thread t, ClassLoader cl) { + try { + setContextClassLoader(t,cl); + } catch (SecurityException se) { + // ignore security exception. Earlier versions of Derby, before the + // DERBY-3745 fix did not require setContextClassloader permissions. + // We may leak class loaders if we are not able to set this, but + // cannot just fail. + } + } + + public static ClassLoader getContextClassLoader(final Thread t) { + return (ClassLoader)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return t.getContextClassLoader(); + } + }); + + } + + + +} Propchange: db/derby/code/branches/10.3/java/engine/org/apache/derby/iapi/util/PrivilegedThreadOps.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/services/monitor/BaseMonitor.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/services/monitor/BaseMonitor.java?rev=675648&r1=675647&r2=675648&view=diff ============================================================================== --- db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/services/monitor/BaseMonitor.java (original) +++ db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/services/monitor/BaseMonitor.java Thu Jul 10 09:58:36 2008 @@ -54,6 +54,7 @@ import org.apache.derby.iapi.services.loader.InstanceGetter; import org.apache.derby.iapi.services.io.FormatableInstanceGetter; import org.apache.derby.iapi.error.ExceptionSeverity; +import org.apache.derby.iapi.util.PrivilegedThreadOps; import org.apache.derby.io.StorageFactory; @@ -2071,8 +2072,30 @@ } public Thread getDaemonThread(Runnable task, String name, boolean setMinPriority) { + // DERBY-3745 We want to avoid the thread leaking class loaders, + // so we make the context class loader null before we create the + // thread. + ClassLoader savecl = null; + boolean hasGetClassLoaderPerms = false; + try { + savecl = PrivilegedThreadOps.getContextClassLoader(Thread.currentThread()); + hasGetClassLoaderPerms = true; + } catch (SecurityException se) { + // ignore security exception. Earlier versions of Derby, before + // the DERBY-3745 fix did not require getClassLoader permissions. + // We may leak class loaders if we are not able to get the + // class loader, but we cannot just fail. + } + if (hasGetClassLoaderPerms) + PrivilegedThreadOps.setContextClassLoaderIfPrivileged( + Thread.currentThread(), null); Thread t = new Thread(daemonGroup, task, "derby.".concat(name)); + if (hasGetClassLoaderPerms) + PrivilegedThreadOps.setContextClassLoaderIfPrivileged( + Thread.currentThread(), savecl); + t.setDaemon(true); + if (setMinPriority) { t.setPriority(Thread.MIN_PRIORITY); } Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/services/timer/SingletonTimerFactory.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/services/timer/SingletonTimerFactory.java?rev=675648&r1=675647&r2=675648&view=diff ============================================================================== --- db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/services/timer/SingletonTimerFactory.java (original) +++ db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/services/timer/SingletonTimerFactory.java Thu Jul 10 09:58:36 2008 @@ -23,7 +23,7 @@ import org.apache.derby.iapi.services.timer.TimerFactory; import org.apache.derby.iapi.services.monitor.ModuleControl; - +import org.apache.derby.iapi.util.PrivilegedThreadOps; import org.apache.derby.iapi.error.StandardException; import java.util.Timer; @@ -61,7 +61,28 @@ * a) We avoid synchronizing access to singletonTimer later * b) We don't need any properties */ + // DERBY-3745 We want to avoid leaking class loaders, so + // we make sure the context class loader is null before + // creating the thread + ClassLoader savecl = null; + boolean hasGetClassLoaderPerms = false; + try { + savecl = PrivilegedThreadOps.getContextClassLoader( + Thread.currentThread()); + hasGetClassLoaderPerms = true; + } catch (SecurityException se) { + // Ignore security exception. Versions of Derby before + // the DERBY-3745 fix did not require getClassLoader + // privs. We may leak class loaders if we are not + // able to do this but we can't just fail. + } + if (hasGetClassLoaderPerms) + PrivilegedThreadOps.setContextClassLoaderIfPrivileged( + Thread.currentThread(), null); singletonTimer = new Timer(true); // Run as daemon + if (hasGetClassLoaderPerms) + PrivilegedThreadOps.setContextClassLoaderIfPrivileged( + Thread.currentThread(), savecl); } /** Modified: db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/util/derby_tests.policy URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/util/derby_tests.policy?rev=675648&r1=675647&r2=675648&view=diff ============================================================================== --- db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/util/derby_tests.policy (original) +++ db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/util/derby_tests.policy Thu Jul 10 09:58:36 2008 @@ -56,6 +56,13 @@ permission java.util.PropertyPermission "derbyTesting.unittest.*", "write"; permission java.lang.RuntimePermission "createClassLoader"; + + // permissions so that we can set the context class loader to + // null for daemon threads to avoid class loader leak. + // DERBY-3745 + permission java.lang.RuntimePermission "getClassLoader"; + permission java.lang.RuntimePermission "setContextClassLoader"; + permission java.security.SecurityPermission "getPolicy"; permission java.io.FilePermission "${derby.system.home}${/}derby.properties", "read"; @@ -175,6 +182,13 @@ permission java.util.PropertyPermission "derby.*", "read"; permission java.lang.RuntimePermission "createClassLoader"; + + // permissions so that we can set the context class loader to + // null for daemon threads to avoid class loader leak. + // DERBY-3745 + permission java.lang.RuntimePermission "getClassLoader"; + permission java.lang.RuntimePermission "setContextClassLoader"; + permission java.security.SecurityPermission "getPolicy"; permission java.io.FilePermission "${derby.system.home}${/}derby.properties", "read";