aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsundar <none@none>2014-01-30 19:45:20 +0530
committersundar <none@none>2014-01-30 19:45:20 +0530
commitf49f5e1db8fb56d4fb78dcca0115cdfce77d2831 (patch)
treee52d5263d3c6e3396f05036d0907903065154df4
parent070d7c55d4e2b53ed533bd5f5af37076c7599032 (diff)
downloadnashorn-f49f5e1db8fb56d4fb78dcca0115cdfce77d2831.tar.gz
8032949: Nashorn linkages awry
Reviewed-by: jlaskey, attila, ahgross
-rw-r--r--src/jdk/nashorn/internal/objects/NativeObject.java4
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/Bootstrap.java5
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java23
-rw-r--r--test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java97
-rw-r--r--test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java25
7 files changed, 150 insertions, 8 deletions
diff --git a/src/jdk/nashorn/internal/objects/NativeObject.java b/src/jdk/nashorn/internal/objects/NativeObject.java
index 74d56ba6..d102c0fb 100644
--- a/src/jdk/nashorn/internal/objects/NativeObject.java
+++ b/src/jdk/nashorn/internal/objects/NativeObject.java
@@ -645,12 +645,12 @@ public final class NativeObject {
targetObj.addBoundProperties(source, props);
} else if (source instanceof StaticClass) {
final Class<?> clazz = ((StaticClass)source).getRepresentedClass();
- Bootstrap.checkReflectionAccess(clazz);
+ Bootstrap.checkReflectionAccess(clazz, true);
bindBeanProperties(targetObj, source, BeansLinker.getReadableStaticPropertyNames(clazz),
BeansLinker.getWritableStaticPropertyNames(clazz), BeansLinker.getStaticMethodNames(clazz));
} else {
final Class<?> clazz = source.getClass();
- Bootstrap.checkReflectionAccess(clazz);
+ Bootstrap.checkReflectionAccess(clazz, false);
bindBeanProperties(targetObj, source, BeansLinker.getReadableInstancePropertyNames(clazz),
BeansLinker.getWritableInstancePropertyNames(clazz), BeansLinker.getInstanceMethodNames(clazz));
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
index 0d5f68a1..c8f39fcf 100644
--- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
+++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
@@ -278,9 +278,10 @@ public final class Bootstrap {
* {@code java.lang.invoke} package, as well a {@link Class} and any subclass of {@link ClassLoader}) and there is
* a security manager in the system, then it checks the {@code nashorn.JavaReflection} {@code RuntimePermission}.
* @param clazz the class being tested
+ * @param isStatic is access checked for static members (or instance members)
*/
- public static void checkReflectionAccess(Class<?> clazz) {
- ReflectionCheckLinker.checkReflectionAccess(clazz);
+ public static void checkReflectionAccess(Class<?> clazz, boolean isStatic) {
+ ReflectionCheckLinker.checkReflectionAccess(clazz, isStatic);
}
/**
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
index 878c0058..ccb2c879 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
@@ -111,7 +111,7 @@ public final class JavaAdapterFactory {
// check for restricted package access
Context.checkPackageAccess(type);
// check for classes, interfaces in reflection
- ReflectionCheckLinker.checkReflectionAccess(type);
+ ReflectionCheckLinker.checkReflectionAccess(type, true);
}
}
return getAdapterInfo(types).getAdapterClassFor(classOverrides);
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
index 72ed9766..21e2d14e 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
@@ -65,7 +65,7 @@ final class NashornStaticClassLinker implements TypeBasedGuardingDynamicLinker {
return null;
}
final Class<?> receiverClass = ((StaticClass) self).getRepresentedClass();
- Bootstrap.checkReflectionAccess(receiverClass);
+ Bootstrap.checkReflectionAccess(receiverClass, true);
final CallSiteDescriptor desc = request.getCallSiteDescriptor();
// We intercept "new" on StaticClass instances to provide additional capabilities
if ("new".equals(desc.getNameToken(CallSiteDescriptor.OPERATOR))) {
diff --git a/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java b/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
index 39f93642..32f30764 100644
--- a/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime.linker;
import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
@@ -47,6 +48,7 @@ final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{
if (type == Class.class || ClassLoader.class.isAssignableFrom(type)) {
return true;
}
+
final String name = type.getName();
return name.startsWith("java.lang.reflect.") || name.startsWith("java.lang.invoke.");
}
@@ -59,9 +61,25 @@ final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{
return null;
}
- static void checkReflectionAccess(Class<?> clazz) {
+ private static boolean isReflectiveCheckNeeded(final Class<?> type, final boolean isStatic) {
+ // special handling for Proxy subclasses
+ if (Proxy.class.isAssignableFrom(type)) {
+ if (Proxy.isProxyClass(type)) {
+ // real Proxy class - filter only static access
+ return isStatic;
+ }
+
+ // fake Proxy subclass - filter it always!
+ return true;
+ }
+
+ // check for any other reflective Class
+ return isReflectionClass(type);
+ }
+
+ static void checkReflectionAccess(final Class<?> clazz, final boolean isStatic) {
final SecurityManager sm = System.getSecurityManager();
- if (sm != null && isReflectionClass(clazz)) {
+ if (sm != null && isReflectiveCheckNeeded(clazz, isStatic)) {
checkReflectionPermission(sm);
}
}
@@ -77,6 +95,7 @@ final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{
if(CallSiteDescriptorFactory.tokenizeOperators(desc).contains("getProp")) {
if ("static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
if (Context.isAccessibleClass((Class<?>)self) && !isReflectionClass((Class<?>)self)) {
+
// If "getProp:static" passes access checks, allow access.
return;
}
diff --git a/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java b/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
index 4f036101..9cea21ba 100644
--- a/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
+++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
@@ -27,6 +27,9 @@ package jdk.nashorn.api.scripting;
import static org.testng.Assert.fail;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
import java.util.Objects;
import javax.script.Invocable;
import javax.script.ScriptEngine;
@@ -183,4 +186,98 @@ public class ScriptEngineSecurityTest {
}
}
}
+
+ // @bug 8032948: Nashorn linkages awry
+ public static class FakeProxy extends Proxy {
+ public FakeProxy(InvocationHandler ih) {
+ super(ih);
+ }
+
+ public static Class<?> makeProxyClass(ClassLoader cl, Class<?>... ifaces) {
+ return Proxy.getProxyClass(cl, ifaces);
+ }
+ }
+
+ @Test
+ public void fakeProxySubclassAccessCheckTest() throws ScriptException {
+ if (System.getSecurityManager() == null) {
+ // pass vacuously
+ return;
+ }
+
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+
+ e.put("name", ScriptEngineSecurityTest.class.getName());
+ e.put("cl", ScriptEngineSecurityTest.class.getClassLoader());
+ e.put("intfs", new Class[] { Runnable.class });
+
+ String getClass = "Java.type(name + '$FakeProxy').getProxyClass(cl, intfs);";
+
+ // Should not be able to call static methods of Proxy via fake subclass
+ try {
+ Class c = (Class)e.eval(getClass);
+ fail("should have thrown SecurityException");
+ } catch (final Exception exp) {
+ if (! (exp instanceof SecurityException)) {
+ fail("SecurityException expected, got " + exp);
+ }
+ }
+ }
+
+ @Test
+ public void fakeProxySubclassAccessCheckTest2() throws ScriptException {
+ if (System.getSecurityManager() == null) {
+ // pass vacuously
+ return;
+ }
+
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+
+ e.put("name", ScriptEngineSecurityTest.class.getName());
+ e.put("cl", ScriptEngineSecurityTest.class.getClassLoader());
+ e.put("intfs", new Class[] { Runnable.class });
+
+ String getClass = "Java.type(name + '$FakeProxy').makeProxyClass(cl, intfs);";
+
+ // Should not be able to call static methods of Proxy via fake subclass
+ try {
+ Class c = (Class)e.eval(getClass);
+ fail("should have thrown SecurityException");
+ } catch (final Exception exp) {
+ if (! (exp instanceof SecurityException)) {
+ fail("SecurityException expected, got " + exp);
+ }
+ }
+ }
+
+ @Test
+ public static void proxyStaticAccessCheckTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Runnable r = (Runnable)Proxy.newProxyInstance(
+ ScriptEngineTest.class.getClassLoader(),
+ new Class[] { Runnable.class },
+ new InvocationHandler() {
+ @Override
+ public Object invoke(Object p, Method m, Object[] a) {
+ return null;
+ }
+ });
+
+ e.put("rc", r.getClass());
+ e.put("cl", ScriptEngineSecurityTest.class.getClassLoader());
+ e.put("intfs", new Class[] { Runnable.class });
+
+ // make sure static methods of Proxy is not accessible via subclass
+ try {
+ e.eval("rc.static.getProxyClass(cl, intfs)");
+ fail("Should have thrown SecurityException");
+ } catch (final Exception exp) {
+ if (! (exp instanceof SecurityException)) {
+ fail("SecurityException expected, got " + exp);
+ }
+ }
+ }
}
diff --git a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
index 2c7df64d..df8696d8 100644
--- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
+++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
@@ -33,7 +33,9 @@ import static org.testng.Assert.fail;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
+import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.util.concurrent.Callable;
import javax.script.Compilable;
import javax.script.CompiledScript;
@@ -535,6 +537,29 @@ public class ScriptEngineTest {
assertEquals(e.eval("Window.funcJSObject(obj)"), "hello");
}
+ // @bug 8032948: Nashorn linkages awry
+ @Test
+ public void checkProxyAccess() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final boolean[] reached = new boolean[1];
+ final Runnable r = (Runnable)Proxy.newProxyInstance(
+ ScriptEngineTest.class.getClassLoader(),
+ new Class[] { Runnable.class },
+ new InvocationHandler() {
+ @Override
+ public Object invoke(Object p, Method m, Object[] a) {
+ reached[0] = true;
+ return null;
+ }
+ });
+
+ e.put("r", r);
+ e.eval("r.run()");
+
+ assertTrue(reached[0]);
+ }
+
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
// Returns String that would be the result of calling PrintWriter.println