|
37 | 37 | import static com.oracle.svm.jvmtiagentbase.Support.getClassNameOr; |
38 | 38 | import static com.oracle.svm.jvmtiagentbase.Support.getClassNameOrNull; |
39 | 39 | import static com.oracle.svm.jvmtiagentbase.Support.getDirectCallerClass; |
| 40 | +import static com.oracle.svm.jvmtiagentbase.Support.getIntArgument; |
40 | 41 | import static com.oracle.svm.jvmtiagentbase.Support.getMethodDeclaringClass; |
41 | 42 | import static com.oracle.svm.jvmtiagentbase.Support.getObjectArgument; |
42 | 43 | import static com.oracle.svm.jvmtiagentbase.Support.jniFunctions; |
|
49 | 50 | import static com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEvent.JVMTI_EVENT_NATIVE_METHOD_BIND; |
50 | 51 | import static org.graalvm.word.WordFactory.nullPointer; |
51 | 52 |
|
| 53 | +import java.lang.reflect.Modifier; |
52 | 54 | import java.nio.ByteBuffer; |
53 | 55 | import java.nio.ByteOrder; |
54 | 56 | import java.util.ArrayList; |
|
81 | 83 | import com.oracle.svm.agent.restrict.ProxyAccessVerifier; |
82 | 84 | import com.oracle.svm.agent.restrict.ReflectAccessVerifier; |
83 | 85 | import com.oracle.svm.agent.restrict.ResourceAccessVerifier; |
| 86 | +import com.oracle.svm.agent.restrict.SerializationAccessVerifier; |
84 | 87 | import com.oracle.svm.configure.config.ConfigurationMethod; |
85 | 88 | import com.oracle.svm.core.c.function.CEntryPointOptions; |
86 | 89 | import com.oracle.svm.core.util.VMError; |
87 | 90 | import com.oracle.svm.jni.nativeapi.JNIEnvironment; |
| 91 | +import com.oracle.svm.jni.nativeapi.JNIFunctionPointerTypes; |
88 | 92 | import com.oracle.svm.jni.nativeapi.JNIMethodId; |
89 | 93 | import com.oracle.svm.jni.nativeapi.JNINativeMethod; |
90 | 94 | import com.oracle.svm.jni.nativeapi.JNIObjectHandle; |
@@ -129,6 +133,7 @@ final class BreakpointInterceptor { |
129 | 133 | private static ReflectAccessVerifier accessVerifier; |
130 | 134 | private static ProxyAccessVerifier proxyVerifier; |
131 | 135 | private static ResourceAccessVerifier resourceVerifier; |
| 136 | + private static SerializationAccessVerifier serializationAccessVerifier; |
132 | 137 | private static NativeImageAgent agent; |
133 | 138 |
|
134 | 139 | private static Map<Long, Breakpoint> installedBreakpoints; |
@@ -913,6 +918,59 @@ private static String asInternalSignature(Object paramTypesArray) { |
913 | 918 | return null; |
914 | 919 | } |
915 | 920 |
|
| 921 | + @SuppressWarnings("unused") |
| 922 | + private static boolean generateSerializationConstructor(JNIEnvironment jni, Breakpoint bp) { |
| 923 | + JNIObjectHandle callerClass = getDirectCallerClass(); |
| 924 | + JNIObjectHandle self = getObjectArgument(0); |
| 925 | + JNIObjectHandle serializeTargetClass = getObjectArgument(1); |
| 926 | + String serializeTargetClassName = getClassNameOrNull(jni, serializeTargetClass); |
| 927 | + JNIObjectHandle parameterTypes = getObjectArgument(2); |
| 928 | + Object parameterTypeNames = getClassArrayNames(jni, parameterTypes); |
| 929 | + JNIObjectHandle checkedExceptions = getObjectArgument(3); |
| 930 | + Object checkedExceptionNames = getClassArrayNames(jni, checkedExceptions); |
| 931 | + int modifiers = getIntArgument(4); |
| 932 | + JNIObjectHandle targetConstructorClass = getObjectArgument(5); |
| 933 | + String targetConstructorClassName = getClassNameOrNull(jni, targetConstructorClass); |
| 934 | + boolean allowed = (serializationAccessVerifier == null || (parameterTypeNames instanceof String[] && checkedExceptionNames instanceof String[] && |
| 935 | + serializationAccessVerifier.verifyGenerateSerializationConstructor(jni, serializeTargetClassName, (String[]) parameterTypeNames, |
| 936 | + (String[]) checkedExceptionNames, modifiers, targetConstructorClassName, self, callerClass))); |
| 937 | + Object result = false; |
| 938 | + if (allowed) { |
| 939 | + JNIValue args = StackValue.get(6, JNIValue.class); |
| 940 | + args.addressOf(0).setObject(self); |
| 941 | + args.addressOf(1).setObject(serializeTargetClass); |
| 942 | + args.addressOf(2).setObject(parameterTypes); |
| 943 | + args.addressOf(3).setObject(checkedExceptions); |
| 944 | + args.addressOf(4).setInt(modifiers); |
| 945 | + args.addressOf(5).setObject(targetConstructorClass); |
| 946 | + result = nullHandle().notEqual(jniFunctions().getCallObjectMethodA().invoke(jni, bp.clazz, bp.method, args)); |
| 947 | + if (clearException(jni)) { |
| 948 | + result = false; |
| 949 | + } |
| 950 | + } |
| 951 | + |
| 952 | + if (traceWriter != null) { |
| 953 | + traceWriter.traceCall("serialization", |
| 954 | + "generateSerializationConstructor", |
| 955 | + null, |
| 956 | + null, |
| 957 | + null, |
| 958 | + result, |
| 959 | + serializeTargetClassName, parameterTypeNames, |
| 960 | + checkedExceptionNames, modifiers, targetConstructorClassName); |
| 961 | + guarantee(!testException(jni)); |
| 962 | + } |
| 963 | + |
| 964 | + if (!allowed) { |
| 965 | + try (CCharPointerHolder message = toCString( |
| 966 | + NativeImageAgent.MESSAGE_PREFIX + "configuration does not permit SerializationConstructorAccessor class for class: " + serializeTargetClassName + |
| 967 | + " with first unserializable super class " + targetConstructorClassName)) { |
| 968 | + jniFunctions().getThrowNew().invoke(jni, agent.handles().javaLangSecurityException, message.get()); |
| 969 | + } |
| 970 | + } |
| 971 | + return allowed; |
| 972 | + } |
| 973 | + |
916 | 974 | @CEntryPoint |
917 | 975 | @CEntryPointOptions(prologue = AgentIsolate.Prologue.class) |
918 | 976 | private static void onBreakpoint(@SuppressWarnings("unused") JvmtiEnv jvmti, JNIEnvironment jni, |
@@ -991,12 +1049,14 @@ private static void installBreakpointIfClassLoader(JNIEnvironment jni, JNIObject |
991 | 1049 | JvmtiEnv.class, JNIEnvironment.class, JNIObjectHandle.class, JNIObjectHandle.class); |
992 | 1050 |
|
993 | 1051 | public static void onLoad(JvmtiEnv jvmti, JvmtiEventCallbacks callbacks, TraceWriter writer, ReflectAccessVerifier verifier, |
994 | | - ProxyAccessVerifier prverifier, ResourceAccessVerifier resverifier, NativeImageAgent nativeImageTracingAgent, boolean exptlClassLoaderSupport) { |
| 1052 | + ProxyAccessVerifier prverifier, ResourceAccessVerifier resverifier, SerializationAccessVerifier serializationAccessVerifier, NativeImageAgent nativeImageTracingAgent, |
| 1053 | + boolean exptlClassLoaderSupport) { |
995 | 1054 |
|
996 | 1055 | BreakpointInterceptor.traceWriter = writer; |
997 | 1056 | BreakpointInterceptor.accessVerifier = verifier; |
998 | 1057 | BreakpointInterceptor.proxyVerifier = prverifier; |
999 | 1058 | BreakpointInterceptor.resourceVerifier = resverifier; |
| 1059 | + BreakpointInterceptor.serializationAccessVerifier = serializationAccessVerifier; |
1000 | 1060 | BreakpointInterceptor.agent = nativeImageTracingAgent; |
1001 | 1061 | BreakpointInterceptor.experimentalClassLoaderSupport = exptlClassLoaderSupport; |
1002 | 1062 |
|
@@ -1218,6 +1278,13 @@ private interface BreakpointHandler { |
1218 | 1278 | brk("java/lang/reflect/Proxy", "newProxyInstance", |
1219 | 1279 | "(Ljava/lang/ClassLoader;[Ljava/lang/Class;Ljava/lang/reflect/InvocationHandler;)Ljava/lang/Object;", BreakpointInterceptor::newProxyInstance), |
1220 | 1280 |
|
| 1281 | + optionalBrk("sun/reflect/MethodAccessorGenerator", "generateSerializationConstructor", |
| 1282 | + "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;ILjava/lang/Class;)Lsun/reflect/SerializationConstructorAccessorImpl;", |
| 1283 | + BreakpointInterceptor::generateSerializationConstructor), |
| 1284 | + // MethodAccessorGenerator has been moved to jdk/internal/reflect since JDK9 |
| 1285 | + optionalBrk("jdk/internal/reflect/MethodAccessorGenerator", "generateSerializationConstructor", |
| 1286 | + "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;ILjava/lang/Class;)Ljdk/internal/reflect/SerializationConstructorAccessorImpl;", |
| 1287 | + BreakpointInterceptor::generateSerializationConstructor), |
1221 | 1288 | optionalBrk("java/util/ResourceBundle", |
1222 | 1289 | "getBundleImpl", |
1223 | 1290 | "(Ljava/lang/String;Ljava/util/Locale;Ljava/lang/ClassLoader;Ljava/util/ResourceBundle$Control;)Ljava/util/ResourceBundle;", |
|
0 commit comments