blob: ebe9d10c472770fb41e360283c40ae0eeab0887a [file] [log] [blame]
David Brazdil11b67b22018-01-18 16:41:40 +00001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
David Brazdil2bb2fbd2018-11-13 18:24:26 +000017#include "base/sdk_version.h"
David Brazdil11b67b22018-01-18 16:41:40 +000018#include "class_linker.h"
19#include "dex/art_dex_file_loader.h"
Mathew Inwood597d7f62018-03-22 11:36:47 +000020#include "hidden_api.h"
David Brazdil11b67b22018-01-18 16:41:40 +000021#include "jni.h"
22#include "runtime.h"
23#include "scoped_thread_state_change-inl.h"
24#include "thread.h"
25#include "ti-agent/scoped_utf_chars.h"
26
27namespace art {
28namespace Test674HiddenApi {
29
Andrei Onea79924672020-07-30 14:23:00 +010030// Should be the same as dalvik.system.VMRuntime.PREVENT_META_REFLECTION_BLOCKLIST_ACCESS
31static constexpr uint64_t kPreventMetaReflectionBlocklistAccess = 142365358;
Andrei Onea6442eaf2020-01-08 16:55:56 +000032
David Brazdile7681822018-12-14 16:25:33 +000033std::vector<std::vector<std::unique_ptr<const DexFile>>> opened_dex_files;
34
David Brazdil5a61bb72018-01-19 16:59:46 +000035extern "C" JNIEXPORT void JNICALL Java_Main_init(JNIEnv*, jclass) {
David Brazdil92265222018-02-02 11:21:40 +000036 Runtime* runtime = Runtime::Current();
David Brazdilf50ac102018-10-17 18:00:06 +010037 runtime->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
David Brazdile7681822018-12-14 16:25:33 +000038 runtime->SetCorePlatformApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
David Brazdildcfa89b2018-10-31 11:04:10 +000039 runtime->SetTargetSdkVersion(
Andrei Oneafc12a6c2020-07-29 19:52:34 +010040 static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetO().GetMaxAllowedSdkVersion()));
David Brazdil92265222018-02-02 11:21:40 +000041 runtime->SetDedupeHiddenApiWarnings(false);
David Brazdil5a61bb72018-01-19 16:59:46 +000042}
43
David Brazdile7681822018-12-14 16:25:33 +000044extern "C" JNIEXPORT void JNICALL Java_Main_setDexDomain(
45 JNIEnv*, jclass, jint int_index, jboolean is_core_platform) {
46 size_t index = static_cast<size_t>(int_index);
47 CHECK_LT(index, opened_dex_files.size());
48 for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files[index]) {
49 const_cast<DexFile*>(dex_file.get())->SetHiddenapiDomain(
50 (is_core_platform == JNI_FALSE) ? hiddenapi::Domain::kPlatform
51 : hiddenapi::Domain::kCorePlatform);
52 }
53}
54
55extern "C" JNIEXPORT jint JNICALL Java_Main_appendToBootClassLoader(
56 JNIEnv* env, jclass klass, jstring jpath, jboolean is_core_platform) {
David Brazdil11b67b22018-01-18 16:41:40 +000057 ScopedUtfChars utf(env, jpath);
58 const char* path = utf.c_str();
David Brazdile7681822018-12-14 16:25:33 +000059 CHECK(path != nullptr);
60
61 const size_t index = opened_dex_files.size();
62 const jint int_index = static_cast<jint>(index);
63 opened_dex_files.push_back(std::vector<std::unique_ptr<const DexFile>>());
David Brazdil11b67b22018-01-18 16:41:40 +000064
65 ArtDexFileLoader dex_loader;
66 std::string error_msg;
David Brazdile7681822018-12-14 16:25:33 +000067
David Brazdil11b67b22018-01-18 16:41:40 +000068 if (!dex_loader.Open(path,
69 path,
70 /* verify */ false,
71 /* verify_checksum */ true,
72 &error_msg,
David Brazdile7681822018-12-14 16:25:33 +000073 &opened_dex_files[index])) {
David Brazdil11b67b22018-01-18 16:41:40 +000074 LOG(FATAL) << "Could not open " << path << " for boot classpath extension: " << error_msg;
75 UNREACHABLE();
76 }
77
David Brazdile7681822018-12-14 16:25:33 +000078 Java_Main_setDexDomain(env, klass, int_index, is_core_platform);
79
David Brazdil11b67b22018-01-18 16:41:40 +000080 ScopedObjectAccess soa(Thread::Current());
David Brazdile7681822018-12-14 16:25:33 +000081 for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files[index]) {
Mathieu Chartier0a19e212019-11-27 14:35:24 -080082 Runtime::Current()->GetClassLinker()->AppendToBootClassPath(Thread::Current(), dex_file.get());
David Brazdil11b67b22018-01-18 16:41:40 +000083 }
David Brazdile7681822018-12-14 16:25:33 +000084
85 return int_index;
David Brazdil11b67b22018-01-18 16:41:40 +000086}
87
Andrei Oneafc12a6c2020-07-29 19:52:34 +010088extern "C" JNIEXPORT void JNICALL Java_Main_setSdkAll(JNIEnv*, jclass, jboolean value) {
David Brazdil74d48842019-01-22 16:06:25 +000089 std::vector<std::string> exemptions;
90 if (value != JNI_FALSE) {
91 exemptions.push_back("L");
92 }
93 Runtime::Current()->SetHiddenApiExemptions(exemptions);
94}
95
David Brazdil11b67b22018-01-18 16:41:40 +000096static jobject NewInstance(JNIEnv* env, jclass klass) {
97 jmethodID constructor = env->GetMethodID(klass, "<init>", "()V");
Yi Kong4b22b342018-08-02 14:43:21 -070098 if (constructor == nullptr) {
99 return nullptr;
David Brazdil11b67b22018-01-18 16:41:40 +0000100 }
101 return env->NewObject(klass, constructor);
102}
103
104extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canDiscoverField(
105 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
106 ScopedUtfChars utf_name(env, name);
107 jfieldID field = is_static ? env->GetStaticFieldID(klass, utf_name.c_str(), "I")
108 : env->GetFieldID(klass, utf_name.c_str(), "I");
Yi Kong4b22b342018-08-02 14:43:21 -0700109 if (field == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000110 env->ExceptionClear();
111 return JNI_FALSE;
112 }
113
114 return JNI_TRUE;
115}
116
117extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canGetField(
118 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
119 ScopedUtfChars utf_name(env, name);
120 jfieldID field = is_static ? env->GetStaticFieldID(klass, utf_name.c_str(), "I")
121 : env->GetFieldID(klass, utf_name.c_str(), "I");
Yi Kong4b22b342018-08-02 14:43:21 -0700122 if (field == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000123 env->ExceptionClear();
124 return JNI_FALSE;
125 }
126 if (is_static) {
127 env->GetStaticIntField(klass, field);
128 } else {
129 jobject obj = NewInstance(env, klass);
Yi Kong4b22b342018-08-02 14:43:21 -0700130 if (obj == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000131 env->ExceptionDescribe();
132 env->ExceptionClear();
133 return JNI_FALSE;
134 }
135 env->GetIntField(obj, field);
136 }
137
138 if (env->ExceptionOccurred()) {
139 env->ExceptionDescribe();
140 env->ExceptionClear();
141 return JNI_FALSE;
142 }
143
144 return JNI_TRUE;
145}
146
147extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canSetField(
148 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
149 ScopedUtfChars utf_name(env, name);
150 jfieldID field = is_static ? env->GetStaticFieldID(klass, utf_name.c_str(), "I")
151 : env->GetFieldID(klass, utf_name.c_str(), "I");
Yi Kong4b22b342018-08-02 14:43:21 -0700152 if (field == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000153 env->ExceptionClear();
154 return JNI_FALSE;
155 }
156 if (is_static) {
157 env->SetStaticIntField(klass, field, 42);
158 } else {
159 jobject obj = NewInstance(env, klass);
Yi Kong4b22b342018-08-02 14:43:21 -0700160 if (obj == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000161 env->ExceptionDescribe();
162 env->ExceptionClear();
163 return JNI_FALSE;
164 }
165 env->SetIntField(obj, field, 42);
166 }
167
168 if (env->ExceptionOccurred()) {
169 env->ExceptionDescribe();
170 env->ExceptionClear();
171 return JNI_FALSE;
172 }
173
174 return JNI_TRUE;
175}
176
177extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canDiscoverMethod(
178 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
179 ScopedUtfChars utf_name(env, name);
180 jmethodID method = is_static ? env->GetStaticMethodID(klass, utf_name.c_str(), "()I")
181 : env->GetMethodID(klass, utf_name.c_str(), "()I");
Yi Kong4b22b342018-08-02 14:43:21 -0700182 if (method == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000183 env->ExceptionClear();
184 return JNI_FALSE;
185 }
186
187 return JNI_TRUE;
188}
189
190extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeMethodA(
191 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
192 ScopedUtfChars utf_name(env, name);
193 jmethodID method = is_static ? env->GetStaticMethodID(klass, utf_name.c_str(), "()I")
194 : env->GetMethodID(klass, utf_name.c_str(), "()I");
Yi Kong4b22b342018-08-02 14:43:21 -0700195 if (method == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000196 env->ExceptionClear();
197 return JNI_FALSE;
198 }
199
200 if (is_static) {
201 env->CallStaticIntMethodA(klass, method, nullptr);
202 } else {
203 jobject obj = NewInstance(env, klass);
Yi Kong4b22b342018-08-02 14:43:21 -0700204 if (obj == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000205 env->ExceptionDescribe();
206 env->ExceptionClear();
207 return JNI_FALSE;
208 }
209 env->CallIntMethodA(obj, method, nullptr);
210 }
211
212 if (env->ExceptionOccurred()) {
213 env->ExceptionDescribe();
214 env->ExceptionClear();
215 return JNI_FALSE;
216 }
217
218 return JNI_TRUE;
219}
220
221extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeMethodV(
222 JNIEnv* env, jclass, jclass klass, jstring name, jboolean is_static) {
223 ScopedUtfChars utf_name(env, name);
224 jmethodID method = is_static ? env->GetStaticMethodID(klass, utf_name.c_str(), "()I")
225 : env->GetMethodID(klass, utf_name.c_str(), "()I");
Yi Kong4b22b342018-08-02 14:43:21 -0700226 if (method == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000227 env->ExceptionClear();
228 return JNI_FALSE;
229 }
230
231 if (is_static) {
232 env->CallStaticIntMethod(klass, method);
233 } else {
234 jobject obj = NewInstance(env, klass);
Yi Kong4b22b342018-08-02 14:43:21 -0700235 if (obj == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000236 env->ExceptionDescribe();
237 env->ExceptionClear();
238 return JNI_FALSE;
239 }
240 env->CallIntMethod(obj, method);
241 }
242
243 if (env->ExceptionOccurred()) {
244 env->ExceptionDescribe();
245 env->ExceptionClear();
246 return JNI_FALSE;
247 }
248
249 return JNI_TRUE;
250}
251
252static constexpr size_t kConstructorSignatureLength = 5; // e.g. (IZ)V
253static constexpr size_t kNumConstructorArgs = kConstructorSignatureLength - 3;
254
255extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canDiscoverConstructor(
256 JNIEnv* env, jclass, jclass klass, jstring args) {
257 ScopedUtfChars utf_args(env, args);
258 jmethodID constructor = env->GetMethodID(klass, "<init>", utf_args.c_str());
Yi Kong4b22b342018-08-02 14:43:21 -0700259 if (constructor == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000260 env->ExceptionClear();
261 return JNI_FALSE;
262 }
263
264 return JNI_TRUE;
265}
266
267extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeConstructorA(
268 JNIEnv* env, jclass, jclass klass, jstring args) {
269 ScopedUtfChars utf_args(env, args);
270 jmethodID constructor = env->GetMethodID(klass, "<init>", utf_args.c_str());
Yi Kong4b22b342018-08-02 14:43:21 -0700271 if (constructor == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000272 env->ExceptionClear();
273 return JNI_FALSE;
274 }
275
276 // CheckJNI won't allow out-of-range values, so just zero everything.
277 CHECK_EQ(strlen(utf_args.c_str()), kConstructorSignatureLength);
278 size_t initargs_size = sizeof(jvalue) * kNumConstructorArgs;
279 jvalue *initargs = reinterpret_cast<jvalue*>(alloca(initargs_size));
280 memset(initargs, 0, initargs_size);
281
282 env->NewObjectA(klass, constructor, initargs);
283 if (env->ExceptionOccurred()) {
284 env->ExceptionDescribe();
285 env->ExceptionClear();
286 return JNI_FALSE;
287 }
288
289 return JNI_TRUE;
290}
291
292extern "C" JNIEXPORT jboolean JNICALL Java_JNI_canInvokeConstructorV(
293 JNIEnv* env, jclass, jclass klass, jstring args) {
294 ScopedUtfChars utf_args(env, args);
295 jmethodID constructor = env->GetMethodID(klass, "<init>", utf_args.c_str());
Yi Kong4b22b342018-08-02 14:43:21 -0700296 if (constructor == nullptr) {
David Brazdil11b67b22018-01-18 16:41:40 +0000297 env->ExceptionClear();
298 return JNI_FALSE;
299 }
300
301 // CheckJNI won't allow out-of-range values, so just zero everything.
302 CHECK_EQ(strlen(utf_args.c_str()), kConstructorSignatureLength);
303 size_t initargs_size = sizeof(jvalue) * kNumConstructorArgs;
304 jvalue *initargs = reinterpret_cast<jvalue*>(alloca(initargs_size));
305 memset(initargs, 0, initargs_size);
306
307 static_assert(kNumConstructorArgs == 2, "Change the varargs below if you change the constant");
308 env->NewObject(klass, constructor, initargs[0], initargs[1]);
309 if (env->ExceptionOccurred()) {
310 env->ExceptionDescribe();
311 env->ExceptionClear();
312 return JNI_FALSE;
313 }
314
315 return JNI_TRUE;
316}
317
318extern "C" JNIEXPORT jint JNICALL Java_Reflection_getHiddenApiAccessFlags(JNIEnv*, jclass) {
David Brazdil85865692018-10-30 17:26:20 +0000319 return static_cast<jint>(kAccHiddenapiBits);
David Brazdil11b67b22018-01-18 16:41:40 +0000320}
321
Andrei Onea6442eaf2020-01-08 16:55:56 +0000322extern "C" JNIEXPORT void JNICALL Java_Reflection_setHiddenApiCheckHardening(JNIEnv*, jclass,
323 jboolean value) {
Andrei Onea037d2822020-11-19 00:20:04 +0000324 CompatFramework& compat_framework = Runtime::Current()->GetCompatFramework();
325 std::set<uint64_t> disabled_changes = compat_framework.GetDisabledCompatChanges();
Andrei Onea6442eaf2020-01-08 16:55:56 +0000326 if (value == JNI_TRUE) {
327 // If hidden api check hardening is enabled, remove it from the set of disabled changes.
Andrei Onea79924672020-07-30 14:23:00 +0100328 disabled_changes.erase(kPreventMetaReflectionBlocklistAccess);
Andrei Onea6442eaf2020-01-08 16:55:56 +0000329 } else {
330 // If hidden api check hardening is disabled, add it to the set of disabled changes.
Andrei Onea79924672020-07-30 14:23:00 +0100331 disabled_changes.insert(kPreventMetaReflectionBlocklistAccess);
Andrei Onea6442eaf2020-01-08 16:55:56 +0000332 }
Andrei Onea037d2822020-11-19 00:20:04 +0000333 compat_framework.SetDisabledCompatChanges(disabled_changes);
Andrei Onea6442eaf2020-01-08 16:55:56 +0000334}
335
David Brazdil11b67b22018-01-18 16:41:40 +0000336} // namespace Test674HiddenApi
337} // namespace art