Make sure to call service hooks in privileged blocks. (FELIX-3056)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1153170 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index 0d6e7fa..c879761 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -3098,7 +3098,7 @@
{
try
{
- lh.removed(removed);
+ m_secureAction.invokeServiceListenerHookRemoved(lh, removed);
}
catch (Throwable th)
{
@@ -3124,7 +3124,7 @@
{
try
{
- lh.added(added);
+ m_secureAction.invokeServiceListenerHookAdded(lh, added);
}
catch (Throwable th)
{
@@ -3165,7 +3165,7 @@
{
try
{
- lh.removed(removed);
+ m_secureAction.invokeServiceListenerHookRemoved(lh, removed);
}
catch (Throwable th)
{
@@ -3291,7 +3291,8 @@
{
try
{
- lh.added(m_dispatcher.getAllServiceListeners());
+ m_secureAction.invokeServiceListenerHookAdded(
+ lh, m_dispatcher.getAllServiceListeners());
}
catch (Throwable th)
{
@@ -3374,7 +3375,9 @@
{
try
{
- fh.find(bundle._getBundleContext(),
+ m_secureAction.invokeServiceFindHook(
+ fh,
+ bundle._getBundleContext(),
className,
expr,
!checkAssignable,
diff --git a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
index 05e01cb..a3403a0 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
@@ -587,7 +587,8 @@
{
try
{
- elh.event(event, shrinkableMap);
+ m_secureAction.invokeServiceEventListenerHook(
+ elh, event, shrinkableMap);
}
catch (Throwable th)
{
@@ -665,8 +666,9 @@
{
if (eh instanceof org.osgi.framework.hooks.service.EventHook)
{
- ((org.osgi.framework.hooks.service.EventHook)
- eh).event((ServiceEvent) event, shrinkable);
+ m_secureAction.invokeServiceEventHook(
+ (org.osgi.framework.hooks.service.EventHook) eh,
+ (ServiceEvent) event, shrinkable);
}
else if (eh instanceof org.osgi.framework.hooks.bundle.EventHook)
{
diff --git a/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java b/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
index 4a27c47..191879f 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
@@ -25,11 +25,15 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
+import java.util.Map;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.hooks.service.ListenerHook;
/**
* <p>
@@ -1115,6 +1119,130 @@
}
}
+ public void invokeServiceEventHook(
+ org.osgi.framework.hooks.service.EventHook eh,
+ ServiceEvent event, Collection<BundleContext> contexts)
+ throws Exception
+ {
+ if (System.getSecurityManager() != null)
+ {
+ Actions actions = (Actions) m_actions.get();
+ actions.set(Actions.INVOKE_SERVICE_EVENT_HOOK, eh, contexts);
+ try
+ {
+ AccessController.doPrivileged(actions, m_acc);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw e.getException();
+ }
+ }
+ else
+ {
+ eh.event(event, contexts);
+ }
+ }
+
+ public void invokeServiceFindHook(
+ org.osgi.framework.hooks.service.FindHook fh,
+ BundleContext context, String name, String filter,
+ boolean allServices, Collection<ServiceReference<?>> references)
+ throws Exception
+ {
+ if (System.getSecurityManager() != null)
+ {
+ Actions actions = (Actions) m_actions.get();
+ actions.set(
+ Actions.INVOKE_SERVICE_EVENT_HOOK, fh, context, name, filter,
+ (allServices) ? Boolean.TRUE : Boolean.FALSE, references);
+ try
+ {
+ AccessController.doPrivileged(actions, m_acc);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw e.getException();
+ }
+ }
+ else
+ {
+ fh.find(context, name, filter, allServices, references);
+ }
+ }
+
+ public void invokeServiceListenerHookAdded(
+ org.osgi.framework.hooks.service.ListenerHook lh,
+ Collection<ListenerHook.ListenerInfo> listeners)
+ throws Exception
+ {
+ if (System.getSecurityManager() != null)
+ {
+ Actions actions = (Actions) m_actions.get();
+ actions.set(Actions.INVOKE_SERVICE_LISTENER_HOOK_ADDED, lh, listeners);
+ try
+ {
+ AccessController.doPrivileged(actions, m_acc);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw e.getException();
+ }
+ }
+ else
+ {
+ lh.added(listeners);
+ }
+ }
+
+ public void invokeServiceListenerHookRemoved(
+ org.osgi.framework.hooks.service.ListenerHook lh,
+ Collection<ListenerHook.ListenerInfo> listeners)
+ throws Exception
+ {
+ if (System.getSecurityManager() != null)
+ {
+ Actions actions = (Actions) m_actions.get();
+ actions.set(Actions.INVOKE_SERVICE_LISTENER_HOOK_REMOVED, lh, listeners);
+ try
+ {
+ AccessController.doPrivileged(actions, m_acc);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw e.getException();
+ }
+ }
+ else
+ {
+ lh.removed(listeners);
+ }
+ }
+
+ public void invokeServiceEventListenerHook(
+ org.osgi.framework.hooks.service.EventListenerHook elh,
+ ServiceEvent event,
+ Map<BundleContext, Collection<ListenerHook.ListenerInfo>> listeners)
+ throws Exception
+ {
+ if (System.getSecurityManager() != null)
+ {
+ Actions actions = (Actions) m_actions.get();
+ actions.set(Actions.INVOKE_SERVICE_EVENT_LISTENER_HOOK, elh, listeners);
+ try
+ {
+ AccessController.doPrivileged(actions, m_acc);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw e.getException();
+ }
+ }
+ else
+ {
+ elh.event(event, listeners);
+ }
+ }
+
private static class Actions implements PrivilegedExceptionAction
{
public static final int INITIALIZE_CONTEXT_ACTION = 0;
@@ -1160,6 +1288,11 @@
public static final int INVOKE_BUNDLE_FIND_HOOK = 40;
public static final int INVOKE_BUNDLE_EVENT_HOOK = 41;
public static final int INVOKE_WEAVING_HOOK = 42;
+ public static final int INVOKE_SERVICE_EVENT_HOOK = 43;
+ public static final int INVOKE_SERVICE_FIND_HOOK = 44;
+ public static final int INVOKE_SERVICE_LISTENER_HOOK_ADDED = 45;
+ public static final int INVOKE_SERVICE_LISTENER_HOOK_REMOVED = 46;
+ public static final int INVOKE_SERVICE_EVENT_LISTENER_HOOK = 47;
private int m_action = -1;
private Object m_arg1 = null;
@@ -1167,6 +1300,7 @@
private Object m_arg3 = null;
private Object m_arg4 = null;
private Object m_arg5 = null;
+ private Object m_arg6 = null;
public void set(int action)
{
@@ -1215,6 +1349,18 @@
m_arg5 = arg5;
}
+ public void set(int action, Object arg1, Object arg2, Object arg3,
+ Object arg4, Object arg5, Object arg6)
+ {
+ m_action = action;
+ m_arg1 = arg1;
+ m_arg2 = arg2;
+ m_arg3 = arg3;
+ m_arg4 = arg4;
+ m_arg5 = arg5;
+ m_arg6 = arg6;
+ }
+
private void unset()
{
m_action = -1;
@@ -1223,6 +1369,7 @@
m_arg3 = null;
m_arg4 = null;
m_arg5 = null;
+ m_arg6 = null;
}
public Object run() throws Exception
@@ -1233,6 +1380,7 @@
Object arg3 = m_arg3;
Object arg4 = m_arg4;
Object arg5 = m_arg5;
+ Object arg6 = m_arg6;
unset();
@@ -1345,6 +1493,29 @@
((org.osgi.framework.hooks.weaving.WeavingHook) arg1).weave(
(org.osgi.framework.hooks.weaving.WovenClass) arg2);
return null;
+ case INVOKE_SERVICE_EVENT_HOOK:
+ ((org.osgi.framework.hooks.service.EventHook) arg1).event(
+ (ServiceEvent) arg2, (Collection<BundleContext>) arg3);
+ return null;
+ case INVOKE_SERVICE_FIND_HOOK:
+ ((org.osgi.framework.hooks.service.FindHook) arg1).find(
+ (BundleContext) arg2, (String) arg3, (String) arg4,
+ ((Boolean) arg5).booleanValue(),
+ (Collection<ServiceReference<?>>) arg6);
+ return null;
+ case INVOKE_SERVICE_LISTENER_HOOK_ADDED:
+ ((org.osgi.framework.hooks.service.ListenerHook) arg1).added(
+ (Collection<ListenerHook.ListenerInfo>) arg2);
+ return null;
+ case INVOKE_SERVICE_LISTENER_HOOK_REMOVED:
+ ((org.osgi.framework.hooks.service.ListenerHook) arg1).removed(
+ (Collection<ListenerHook.ListenerInfo>) arg2);
+ return null;
+ case INVOKE_SERVICE_EVENT_LISTENER_HOOK:
+ ((org.osgi.framework.hooks.service.EventListenerHook) arg1).event(
+ (ServiceEvent) arg2,
+ (Map<BundleContext, Collection<ListenerHook.ListenerInfo>>) arg3);
+ return null;
}
return null;