You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pa...@apache.org on 2018/11/08 21:23:52 UTC
svn commit: r1846198 - in /felix/trunk/framework/src:
main/java/org/apache/felix/framework/
main/java/org/apache/felix/framework/util/
test/java/org/apache/felix/framework/
Author: pauls
Date: Thu Nov 8 21:23:52 2018
New Revision: 1846198
URL: http://svn.apache.org/viewvc?rev=1846198&view=rev
Log:
FELIX-5978: Ensure getClassLoader() is called in a safe way when security is enabled - patched provided by Tim Ward - thanks! (This closes #160)
Modified:
felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
felix/trunk/framework/src/test/java/org/apache/felix/framework/URLHandlersTest.java
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java?rev=1846198&r1=1846197&r2=1846198&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java Thu Nov 8 21:23:52 2018
@@ -26,6 +26,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationTargetException;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
@@ -53,6 +54,7 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.PackagePermission;
import org.osgi.framework.wiring.BundleRevision;
+import sun.net.www.protocol.file.FileURLConnection;
public class BundleProtectionDomain extends ProtectionDomain
{
@@ -210,8 +212,6 @@ public class BundleProtectionDomain exte
}
m_output.closeEntry();
-
- m_output.flush();
}
}
@@ -238,100 +238,91 @@ public class BundleProtectionDomain exte
private static final class RevisionAsJarURL extends URLStreamHandler
{
private final WeakReference m_revision;
+ private volatile URL url;
private RevisionAsJarURL(BundleRevisionImpl revision)
{
m_revision = new WeakReference(revision);
}
-
@Override
protected URLConnection openConnection(URL u) throws IOException
{
- return new JarURLConnection(u)
+ if (url != null) {
+ return url.openConnection();
+ }
+ BundleRevisionImpl revision = (BundleRevisionImpl) m_revision.get();
+
+ if (revision != null)
{
- @Override
- public JarFile getJarFile() throws IOException
+ File target;
+ Content content = revision.getContent();
+ if (content instanceof JarContent)
{
- BundleRevisionImpl revision = (BundleRevisionImpl) m_revision.get();
-
- if (revision != null)
+ target = ((JarContent) content).getFile();
+ }
+ else
+ {
+ target = Felix.m_secureAction.createTempFile("jar", null, null);
+ Felix.m_secureAction.deleteFileOnExit(target);
+ FileOutputStream output = null;
+ InputStream input = null;
+ IOException rethrow = null;
+ try
{
- Content content = revision.getContent();
- if (content instanceof JarContent)
+ output = new FileOutputStream(target);
+ input = new BundleInputStream(content);
+ byte[] buffer = new byte[64 * 1024];
+ for (int i = input.read(buffer);i != -1; i = input.read(buffer))
{
- return Felix.m_secureAction.openJarFile(((JarContent) content).getFile());
+ output.write(buffer,0, i);
}
- else
+ }
+ catch (IOException ex)
+ {
+ rethrow = ex;
+ }
+ finally
+ {
+ if (output != null)
{
- File target = Felix.m_secureAction.createTempFile("jar", null, null);
- Felix.m_secureAction.deleteFileOnExit(target);
- FileOutputStream output = null;
- InputStream input = null;
- IOException rethrow = null;
try
{
- output = new FileOutputStream(target);
- input = new BundleInputStream(content);
- byte[] buffer = new byte[64 * 1024];
- for (int i = input.read(buffer);i != -1; i = input.read(buffer))
- {
- output.write(buffer,0, i);
- }
+ output.close();
}
catch (IOException ex)
{
- rethrow = ex;
- }
- finally
- {
- if (output != null)
+ if (rethrow == null)
{
- try
- {
- output.close();
- }
- catch (IOException ex)
- {
- if (rethrow == null)
- {
- rethrow = ex;
- }
- }
- }
-
- if (input != null)
- {
- try
- {
- input.close();
- }
- catch (IOException ex)
- {
- if (rethrow == null)
- {
- rethrow = ex;
- }
- }
+ rethrow = ex;
}
+ }
+ }
- if (rethrow != null)
+ if (input != null)
+ {
+ try
+ {
+ input.close();
+ }
+ catch (IOException ex)
+ {
+ if (rethrow == null)
{
- throw rethrow;
+ rethrow = ex;
}
}
- return Felix.m_secureAction.openJarFile(target);
}
- }
- throw new IOException("Unable to access bundle revision.");
- }
-
- @Override
- public void connect() throws IOException
- {
+ if (rethrow != null)
+ {
+ throw rethrow;
+ }
+ }
}
- };
+ return (url = new URL("jar:" + target.toURI().toURL() + "!/")).openConnection();
+ }
+ throw new IOException("Unable to access bundle revision.");
}
private static boolean getUseCachedURL(final BundleRevisionImpl revision)
@@ -382,31 +373,25 @@ public class BundleProtectionDomain exte
{
location = location.substring("reference:".length());
}
- URL url;
+
try
{
- url = Felix.m_secureAction.createURL(
- Felix.m_secureAction.createURL(null, "jar:", handler), location, null);
+ return Felix.m_secureAction.createURL(
+ Felix.m_secureAction.createURL(null, "jar:", handler),
+ location,
+ handler
+ );
}
catch (MalformedURLException ex)
{
- url = null;
- }
+ location = "jar:" + revision.getEntry("/") + "!/";
- if (url != null && !url.getProtocol().equalsIgnoreCase("jar"))
- {
- return url;
- }
- else if (url == null)
- {
- location = "jar:" + revision.getEntry("/") + "!/";
+ return Felix.m_secureAction.createURL(
+ Felix.m_secureAction.createURL(null, "jar:", handler),
+ location,
+ handler
+ );
}
-
- return Felix.m_secureAction.createURL(
- Felix.m_secureAction.createURL(null, "jar:", handler),
- location,
- handler
- );
}
}
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=1846198&r1=1846197&r2=1846198&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Thu Nov 8 21:23:52 2018
@@ -4023,10 +4023,12 @@ public class Felix extends BundleImpl im
{
// If the class comes from bundle class loader, then return
// associated bundle if it is from this framework instance.
- if (clazz.getClassLoader() instanceof BundleReference)
+ ClassLoader classLoader = m_secureAction.getClassLoader(clazz);
+
+ if (classLoader instanceof BundleReference)
{
// Only return the bundle if it is from this framework.
- BundleReference br = (BundleReference) clazz.getClassLoader();
+ BundleReference br = (BundleReference) classLoader;
return ((br.getBundle() instanceof BundleImpl)
&& (((BundleImpl) br.getBundle()).getFramework() == this))
? br.getBundle() : null;
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java?rev=1846198&r1=1846197&r2=1846198&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java Thu Nov 8 21:23:52 2018
@@ -685,16 +685,19 @@ class URLHandlers implements URLStreamHa
Class[] stack = m_sm.getClassContext();
// Find the first class that is loaded from a bundle.
Class targetClass = null;
+ ClassLoader targetClassLoader = null;
for (int i = 0; i < stack.length; i++)
{
- if (stack[i].getClassLoader() != null)
+ ClassLoader classLoader = m_secureAction.getClassLoader(stack[i]);
+ if (classLoader != null)
{
- String name = stack[i].getClassLoader().getClass().getName();
+ String name = classLoader.getClass().getName();
if (name.startsWith("org.apache.felix.framework.ModuleImpl$ModuleClassLoader")
|| name.equals("org.apache.felix.framework.searchpolicy.ContentClassLoader")
|| name.startsWith("org.apache.felix.framework.BundleWiringImpl$BundleClassLoader"))
{
targetClass = stack[i];
+ targetClassLoader = classLoader;
break;
}
}
@@ -705,7 +708,7 @@ class URLHandlers implements URLStreamHa
// the bundle that loaded the class.
if (targetClass != null)
{
- ClassLoader index = targetClass.getClassLoader().getClass().getClassLoader();
+ ClassLoader index = m_secureAction.getClassLoader(targetClassLoader.getClass());
List frameworks = (List) m_classloaderToFrameworkLists.get(index);
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java?rev=1846198&r1=1846197&r2=1846198&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java Thu Nov 8 21:23:52 2018
@@ -28,6 +28,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
+import java.security.PrivilegedAction;
import org.apache.felix.framework.util.SecureAction;
import org.osgi.service.url.URLStreamHandlerService;
@@ -599,10 +600,11 @@ public class URLHandlersStreamHandlerPro
{
return (URLStreamHandlerService) service;
}
- return (URLStreamHandlerService) Proxy.newProxyInstance(
- URLStreamHandlerService.class.getClassLoader(),
- new Class[]{URLStreamHandlerService.class},
- new URLHandlersStreamHandlerProxy(service, m_action));
+
+ return m_action.createProxy(
+ m_action.getClassLoader(URLStreamHandlerService.class),
+ new Class[]{URLStreamHandlerService.class},
+ new URLHandlersStreamHandlerProxy(service, m_action));
}
catch (ThreadDeath td)
{
@@ -631,11 +633,10 @@ public class URLHandlersStreamHandlerPro
}
if ("parseURL".equals(method.getName()))
{
- types[0] = m_service.getClass().getClassLoader().loadClass(
- URLStreamHandlerSetter.class.getName());
- params[0] = Proxy.newProxyInstance(
- m_service.getClass().getClassLoader(), new Class[]{types[0]},
- (URLHandlersStreamHandlerProxy) params[0]);
+ ClassLoader loader = m_action.getClassLoader(m_service.getClass());
+ types[0] = loader.loadClass(URLStreamHandlerSetter.class.getName());
+ params[0] = m_action.createProxy(loader, new Class[]{types[0]},
+ (URLHandlersStreamHandlerProxy) params[0]);
}
return m_action.invokeDirect(m_action.getDeclaredMethod(m_service.getClass(),
method.getName(), types), m_service, params);
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java?rev=1846198&r1=1846197&r2=1846198&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java Thu Nov 8 21:23:52 2018
@@ -20,6 +20,7 @@ package org.apache.felix.framework.util;
import java.io.*;
import java.lang.reflect.*;
+import java.lang.reflect.Proxy;
import java.net.*;
import java.security.*;
import java.util.Collection;
@@ -1525,6 +1526,28 @@ public class SecureAction
}
}
+ public Object createProxy(ClassLoader classLoader,
+ Class<?>[] interfaces, InvocationHandler handler)
+ {
+ if (System.getSecurityManager() != null)
+ {
+ Actions actions = (Actions) m_actions.get();
+ actions.set(Actions.CREATE_PROXY, classLoader, interfaces, handler);
+ try
+ {
+ return AccessController.doPrivileged(actions, m_acc);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw (RuntimeException) e.getException();
+ }
+ }
+ else
+ {
+ return Proxy.newProxyInstance(classLoader, interfaces, handler);
+ }
+ }
+
private static class Actions implements PrivilegedExceptionAction
{
public static final int INITIALIZE_CONTEXT_ACTION = 0;
@@ -1585,6 +1608,7 @@ public class SecureAction
public static final int DELETE_FILEONEXIT_ACTION = 55;
public static final int INVOKE_WOVEN_CLASS_LISTENER = 56;
public static final int GET_CANONICAL_PATH = 57;
+ public static final int CREATE_PROXY = 58;
private int m_action = -1;
private Object m_arg1 = null;
@@ -1845,6 +1869,9 @@ public class SecureAction
return null;
case GET_CANONICAL_PATH:
return ((File) arg1).getCanonicalPath();
+ case CREATE_PROXY:
+ return Proxy.newProxyInstance((ClassLoader)arg1, (Class<?>[])arg2,
+ (InvocationHandler) arg3);
}
return null;
Modified: felix/trunk/framework/src/test/java/org/apache/felix/framework/URLHandlersTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/test/java/org/apache/felix/framework/URLHandlersTest.java?rev=1846198&r1=1846197&r2=1846198&view=diff
==============================================================================
--- felix/trunk/framework/src/test/java/org/apache/felix/framework/URLHandlersTest.java (original)
+++ felix/trunk/framework/src/test/java/org/apache/felix/framework/URLHandlersTest.java Thu Nov 8 21:23:52 2018
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.ContentHandler;
import java.net.InetAddress;
+import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
@@ -300,7 +301,9 @@ public class URLHandlersTest extends Tes
new URL("test" + System.identityHashCode(TestURLHandlersActivator.this) + ":").openConnection();
-
+ if (!(getClass().getProtectionDomain().getCodeSource().getLocation().openConnection() instanceof JarURLConnection)) {
+ throw new Exception("Unexpted Code Source");
+ }
try
{
@@ -349,14 +352,19 @@ public class URLHandlersTest extends Tes
reg.unregister();
}
+ boolean fail;
try
{
new URL("test" + System.identityHashCode(TestURLHandlersActivator.this) + ":").openConnection();
- throw new Exception("Unexpected url resolve");
+ fail = true;
}
catch (Exception ex)
{
// pass
+ fail = false;
+ }
+ if (fail) {
+ throw new Exception("Unexpected url resolve");
}
Bundle bundle2 = null;
@@ -376,36 +384,48 @@ public class URLHandlersTest extends Tes
}
if (bundle2 != null)
{
+ fail = false;
try
{
new URL("test" + System.identityHashCode(bundle2) + ":").openConnection();
- throw new Exception("Unexpected url2 resolve");
+ fail = true;
}
catch (Exception ex)
{
}
+ if (fail) {
+ throw new Exception("Unexpected url resolve");
+ }
bundle2.start();
new URL("test" + System.identityHashCode(bundle2) + ":").openConnection();
bundle2.stop();
+ fail = false;
try
{
new URL("test" + System.identityHashCode(bundle2) + ":").openConnection();
- throw new Exception("Unexpected url2 resolve");
+ fail = true;
}
catch (Exception ex)
{
}
+ if (fail) {
+ throw new Exception("Unexpected url resolve");
+ }
}
else
{
+ fail = false;
try
{
new URL("test" + System.identityHashCode(context.getBundle()) + ":").openConnection();
- throw new Exception("Unexpected url2 resolve");
+ fail = true;
}
catch (Exception ex)
{
}
+ if (fail) {
+ throw new Exception("Unexpected url2 resolve");
+ }
props = new Hashtable();
props.put(URLConstants.URL_HANDLER_PROTOCOL, "test" + System.identityHashCode(context.getBundle()));
m_reg = context.registerService(URLStreamHandlerService.class, this, props);