1 /*
2  * Copyright (C) 2018 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 
17 #include "hidden_api.h"
18 
19 #include <fstream>
20 #include <sstream>
21 
22 #include "base/file_utils.h"
23 #include "base/sdk_version.h"
24 #include "base/stl_util.h"
25 #include "common_runtime_test.h"
26 #include "jni/jni_internal.h"
27 #include "proxy_test.h"
28 #include "well_known_classes.h"
29 
30 namespace art {
31 
32 using hiddenapi::detail::MemberSignature;
33 using hiddenapi::detail::ShouldDenyAccessToMemberImpl;
34 
35 // Should be the same as dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_P_HIDDEN_APIS and
36 // dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_Q_HIDDEN_APIS.
37 static constexpr uint64_t kHideMaxtargetsdkPHiddenApis = 149997251;
38 static constexpr uint64_t kHideMaxtargetsdkQHiddenApis = 149994052;
39 
40 class HiddenApiTest : public CommonRuntimeTest {
41  protected:
SetUp()42   void SetUp() override {
43     // Do the normal setup.
44     CommonRuntimeTest::SetUp();
45     self_ = Thread::Current();
46     self_->TransitionFromSuspendedToRunnable();
47     jclass_loader_ = LoadDex("HiddenApiSignatures");
48     bool started = runtime_->Start();
49     CHECK(started);
50 
51     class1_field1_ = getArtField("mypackage/packagea/Class1", "field1", "I");
52     class1_field12_ = getArtField("mypackage/packagea/Class1", "field12", "I");
53     class1_init_ = getArtMethod("mypackage/packagea/Class1", "<init>", "()V");
54     class1_method1_ = getArtMethod("mypackage/packagea/Class1", "method1", "()V");
55     class1_method1_i_ = getArtMethod("mypackage/packagea/Class1", "method1", "(I)V");
56     class1_method12_ = getArtMethod("mypackage/packagea/Class1", "method12", "()V");
57     class12_field1_ = getArtField("mypackage/packagea/Class12", "field1", "I");
58     class12_method1_ = getArtMethod("mypackage/packagea/Class12", "method1", "()V");
59     class2_field1_ = getArtField("mypackage/packagea/Class2", "field1", "I");
60     class2_method1_ = getArtMethod("mypackage/packagea/Class2", "method1", "()V");
61     class2_method1_i_ = getArtMethod("mypackage/packagea/Class2", "method1", "(I)V");
62     class3_field1_ = getArtField("mypackage/packageb/Class3", "field1", "I");
63     class3_method1_ = getArtMethod("mypackage/packageb/Class3", "method1", "()V");
64     class3_method1_i_ = getArtMethod("mypackage/packageb/Class3", "method1", "(I)V");
65   }
66 
getArtMethod(const char * class_name,const char * name,const char * signature)67   ArtMethod* getArtMethod(const char* class_name, const char* name, const char* signature) {
68     JNIEnv* env = Thread::Current()->GetJniEnv();
69     jclass klass = env->FindClass(class_name);
70     jmethodID method_id = env->GetMethodID(klass, name, signature);
71     ArtMethod* art_method = jni::DecodeArtMethod(method_id);
72     return art_method;
73   }
74 
getArtField(const char * class_name,const char * name,const char * signature)75   ArtField* getArtField(const char* class_name, const char* name, const char* signature) {
76     JNIEnv* env = Thread::Current()->GetJniEnv();
77     jclass klass = env->FindClass(class_name);
78     jfieldID field_id = env->GetFieldID(klass, name, signature);
79     ArtField* art_field = jni::DecodeArtField(field_id);
80     return art_field;
81   }
82 
setChangeIdState(uint64_t change,bool enabled)83   void setChangeIdState(uint64_t change, bool enabled) {
84     std::set<uint64_t> disabled_changes = runtime_->GetDisabledCompatChanges();
85     if (enabled) {
86       disabled_changes.erase(change);
87     } else {
88       disabled_changes.insert(change);
89     }
90     runtime_->SetDisabledCompatChanges(disabled_changes);
91   }
92 
ShouldDenyAccess(hiddenapi::ApiList list)93   bool ShouldDenyAccess(hiddenapi::ApiList list) REQUIRES_SHARED(Locks::mutator_lock_) {
94     // Choose parameters such that there are no side effects (AccessMethod::kNone)
95     // and that the member is not on the exemptions list (here we choose one which
96     // is not even in boot class path).
97     return ShouldDenyAccessToMemberImpl(/* member= */ class1_field1_,
98                                         list,
99                                         /* access_method= */ hiddenapi::AccessMethod::kNone);
100   }
101 
102  protected:
103   Thread* self_;
104   jobject jclass_loader_;
105   ArtField* class1_field1_;
106   ArtField* class1_field12_;
107   ArtMethod* class1_init_;
108   ArtMethod* class1_method1_;
109   ArtMethod* class1_method1_i_;
110   ArtMethod* class1_method12_;
111   ArtField* class12_field1_;
112   ArtMethod* class12_method1_;
113   ArtField* class2_field1_;
114   ArtMethod* class2_method1_;
115   ArtMethod* class2_method1_i_;
116   ArtField* class3_field1_;
117   ArtMethod* class3_method1_;
118   ArtMethod* class3_method1_i_;
119 };
120 
TEST_F(HiddenApiTest,CheckGetActionFromRuntimeFlags)121 TEST_F(HiddenApiTest, CheckGetActionFromRuntimeFlags) {
122   ScopedObjectAccess soa(self_);
123 
124   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kJustWarn);
125   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
126   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
127   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), false);
128   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), false);
129   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), false);
130   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), false);
131 
132   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
133   runtime_->SetTargetSdkVersion(
134       static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxO().GetMaxAllowedSdkVersion()));
135   setChangeIdState(kHideMaxtargetsdkPHiddenApis, false);
136   setChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
137   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
138   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
139   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), false);
140   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), false);
141   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), false);
142   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
143 
144   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
145   runtime_->SetTargetSdkVersion(
146       static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxO().GetMaxAllowedSdkVersion()) + 1);
147   setChangeIdState(kHideMaxtargetsdkPHiddenApis, false);
148   setChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
149   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
150   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
151   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), false);
152   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), false);
153   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), true);
154   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
155   setChangeIdState(kHideMaxtargetsdkQHiddenApis, true);
156   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
157   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
158   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), true);
159   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), false);
160   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), true);
161   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
162 
163   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
164   runtime_->SetTargetSdkVersion(
165       static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxP().GetMaxAllowedSdkVersion()) + 1);
166   setChangeIdState(kHideMaxtargetsdkPHiddenApis, true);
167   setChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
168   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
169   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
170   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), false);
171   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), true);
172   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), true);
173   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
174 
175   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
176   runtime_->SetTargetSdkVersion(
177       static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxQ().GetMaxAllowedSdkVersion()) + 1);
178   setChangeIdState(kHideMaxtargetsdkPHiddenApis, true);
179   setChangeIdState(kHideMaxtargetsdkQHiddenApis, true);
180   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Whitelist()), false);
181   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Greylist()), false);
182   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxQ()), true);
183   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxP()), true);
184   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::GreylistMaxO()), true);
185   ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
186 }
187 
TEST_F(HiddenApiTest,CheckTestApiEnforcement)188 TEST_F(HiddenApiTest, CheckTestApiEnforcement) {
189   ScopedObjectAccess soa(self_);
190 
191   runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
192   runtime_->SetTargetSdkVersion(
193       static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxQ().GetMaxAllowedSdkVersion()) + 1);
194 
195   // Default case where all TestApis are treated like non-TestApi.
196   runtime_->SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
197   ASSERT_EQ(
198       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Whitelist()), false);
199   ASSERT_EQ(
200       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Greylist()), false);
201   ASSERT_EQ(
202       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxQ()), true);
203   ASSERT_EQ(
204       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxP()), true);
205   ASSERT_EQ(
206       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxO()), true);
207   ASSERT_EQ(
208       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blacklist()), true);
209 
210   // A case where we want to allow access to TestApis.
211   runtime_->SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kDisabled);
212   ASSERT_EQ(
213       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Whitelist()), false);
214   ASSERT_EQ(
215       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Greylist()), false);
216   ASSERT_EQ(
217       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxQ()), false);
218   ASSERT_EQ(
219       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxP()), false);
220   ASSERT_EQ(
221       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxO()), false);
222   ASSERT_EQ(
223       ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blacklist()), false);
224 }
225 
TEST_F(HiddenApiTest,CheckMembersRead)226 TEST_F(HiddenApiTest, CheckMembersRead) {
227   ASSERT_NE(nullptr, class1_field1_);
228   ASSERT_NE(nullptr, class1_field12_);
229   ASSERT_NE(nullptr, class1_init_);
230   ASSERT_NE(nullptr, class1_method1_);
231   ASSERT_NE(nullptr, class1_method1_i_);
232   ASSERT_NE(nullptr, class1_method12_);
233   ASSERT_NE(nullptr, class12_field1_);
234   ASSERT_NE(nullptr, class12_method1_);
235   ASSERT_NE(nullptr, class2_field1_);
236   ASSERT_NE(nullptr, class2_method1_);
237   ASSERT_NE(nullptr, class2_method1_i_);
238   ASSERT_NE(nullptr, class3_field1_);
239   ASSERT_NE(nullptr, class3_method1_);
240   ASSERT_NE(nullptr, class3_method1_i_);
241 }
242 
TEST_F(HiddenApiTest,CheckEverythingMatchesL)243 TEST_F(HiddenApiTest, CheckEverythingMatchesL) {
244   ScopedObjectAccess soa(self_);
245   std::string prefix("L");
246   ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
247   ASSERT_TRUE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
248   ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
249   ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
250   ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
251   ASSERT_TRUE(MemberSignature(class12_field1_).DoesPrefixMatch(prefix));
252   ASSERT_TRUE(MemberSignature(class12_method1_).DoesPrefixMatch(prefix));
253   ASSERT_TRUE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
254   ASSERT_TRUE(MemberSignature(class2_field1_).DoesPrefixMatch(prefix));
255   ASSERT_TRUE(MemberSignature(class2_method1_).DoesPrefixMatch(prefix));
256   ASSERT_TRUE(MemberSignature(class2_method1_i_).DoesPrefixMatch(prefix));
257   ASSERT_TRUE(MemberSignature(class3_field1_).DoesPrefixMatch(prefix));
258   ASSERT_TRUE(MemberSignature(class3_method1_).DoesPrefixMatch(prefix));
259   ASSERT_TRUE(MemberSignature(class3_method1_i_).DoesPrefixMatch(prefix));
260 }
261 
TEST_F(HiddenApiTest,CheckPackageMatch)262 TEST_F(HiddenApiTest, CheckPackageMatch) {
263   ScopedObjectAccess soa(self_);
264   std::string prefix("Lmypackage/packagea/");
265   ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
266   ASSERT_TRUE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
267   ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
268   ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
269   ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
270   ASSERT_TRUE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
271   ASSERT_TRUE(MemberSignature(class12_field1_).DoesPrefixMatch(prefix));
272   ASSERT_TRUE(MemberSignature(class12_method1_).DoesPrefixMatch(prefix));
273   ASSERT_TRUE(MemberSignature(class2_field1_).DoesPrefixMatch(prefix));
274   ASSERT_TRUE(MemberSignature(class2_method1_).DoesPrefixMatch(prefix));
275   ASSERT_TRUE(MemberSignature(class2_method1_i_).DoesPrefixMatch(prefix));
276   ASSERT_FALSE(MemberSignature(class3_field1_).DoesPrefixMatch(prefix));
277   ASSERT_FALSE(MemberSignature(class3_method1_).DoesPrefixMatch(prefix));
278   ASSERT_FALSE(MemberSignature(class3_method1_i_).DoesPrefixMatch(prefix));
279 }
280 
TEST_F(HiddenApiTest,CheckClassMatch)281 TEST_F(HiddenApiTest, CheckClassMatch) {
282   ScopedObjectAccess soa(self_);
283   std::string prefix("Lmypackage/packagea/Class1");
284   ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
285   ASSERT_TRUE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
286   ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
287   ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
288   ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
289   ASSERT_TRUE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
290   ASSERT_TRUE(MemberSignature(class12_field1_).DoesPrefixMatch(prefix));
291   ASSERT_TRUE(MemberSignature(class12_method1_).DoesPrefixMatch(prefix));
292   ASSERT_FALSE(MemberSignature(class2_field1_).DoesPrefixMatch(prefix));
293   ASSERT_FALSE(MemberSignature(class2_method1_).DoesPrefixMatch(prefix));
294   ASSERT_FALSE(MemberSignature(class2_method1_i_).DoesPrefixMatch(prefix));
295 }
296 
TEST_F(HiddenApiTest,CheckClassExactMatch)297 TEST_F(HiddenApiTest, CheckClassExactMatch) {
298   ScopedObjectAccess soa(self_);
299   std::string prefix("Lmypackage/packagea/Class1;");
300   ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
301   ASSERT_TRUE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
302   ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
303   ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
304   ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
305   ASSERT_FALSE(MemberSignature(class12_field1_).DoesPrefixMatch(prefix));
306   ASSERT_FALSE(MemberSignature(class12_method1_).DoesPrefixMatch(prefix));
307   ASSERT_FALSE(MemberSignature(class2_field1_).DoesPrefixMatch(prefix));
308   ASSERT_FALSE(MemberSignature(class2_method1_).DoesPrefixMatch(prefix));
309   ASSERT_FALSE(MemberSignature(class2_method1_i_).DoesPrefixMatch(prefix));
310 }
311 
TEST_F(HiddenApiTest,CheckMethodMatch)312 TEST_F(HiddenApiTest, CheckMethodMatch) {
313   ScopedObjectAccess soa(self_);
314   std::string prefix("Lmypackage/packagea/Class1;->method1");
315   ASSERT_FALSE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
316   ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
317   ASSERT_FALSE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
318   ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
319   ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
320   ASSERT_TRUE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
321   ASSERT_FALSE(MemberSignature(class12_field1_).DoesPrefixMatch(prefix));
322   ASSERT_FALSE(MemberSignature(class12_method1_).DoesPrefixMatch(prefix));
323 }
324 
TEST_F(HiddenApiTest,CheckMethodExactMatch)325 TEST_F(HiddenApiTest, CheckMethodExactMatch) {
326   ScopedObjectAccess soa(self_);
327   std::string prefix("Lmypackage/packagea/Class1;->method1(");
328   ASSERT_FALSE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
329   ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
330   ASSERT_FALSE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
331   ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
332   ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
333   ASSERT_FALSE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
334 }
335 
TEST_F(HiddenApiTest,CheckMethodSignatureMatch)336 TEST_F(HiddenApiTest, CheckMethodSignatureMatch) {
337   ScopedObjectAccess soa(self_);
338   std::string prefix("Lmypackage/packagea/Class1;->method1(I)");
339   ASSERT_FALSE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
340   ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
341   ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
342   ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
343   ASSERT_FALSE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
344 }
345 
TEST_F(HiddenApiTest,CheckMethodSignatureAndReturnMatch)346 TEST_F(HiddenApiTest, CheckMethodSignatureAndReturnMatch) {
347   ScopedObjectAccess soa(self_);
348   std::string prefix("Lmypackage/packagea/Class1;->method1()V");
349   ASSERT_FALSE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
350   ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
351   ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
352   ASSERT_FALSE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
353   ASSERT_FALSE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
354 }
355 
TEST_F(HiddenApiTest,CheckFieldMatch)356 TEST_F(HiddenApiTest, CheckFieldMatch) {
357   ScopedObjectAccess soa(self_);
358   std::string prefix("Lmypackage/packagea/Class1;->field1");
359   ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
360   ASSERT_TRUE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
361   ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
362   ASSERT_FALSE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
363   ASSERT_FALSE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
364 }
365 
TEST_F(HiddenApiTest,CheckFieldExactMatch)366 TEST_F(HiddenApiTest, CheckFieldExactMatch) {
367   ScopedObjectAccess soa(self_);
368   std::string prefix("Lmypackage/packagea/Class1;->field1:");
369   ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
370   ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
371   ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
372 }
373 
TEST_F(HiddenApiTest,CheckFieldTypeMatch)374 TEST_F(HiddenApiTest, CheckFieldTypeMatch) {
375   ScopedObjectAccess soa(self_);
376   std::string prefix("Lmypackage/packagea/Class1;->field1:I");
377   ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
378   ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
379   ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
380 }
381 
TEST_F(HiddenApiTest,CheckConstructorMatch)382 TEST_F(HiddenApiTest, CheckConstructorMatch) {
383   ScopedObjectAccess soa(self_);
384   std::string prefix("Lmypackage/packagea/Class1;-><init>");
385   ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
386   ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
387 }
388 
TEST_F(HiddenApiTest,CheckConstructorExactMatch)389 TEST_F(HiddenApiTest, CheckConstructorExactMatch) {
390   ScopedObjectAccess soa(self_);
391   std::string prefix("Lmypackage/packagea/Class1;-><init>()V");
392   ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
393   ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
394 }
395 
TEST_F(HiddenApiTest,CheckMethodSignatureTrailingCharsNoMatch)396 TEST_F(HiddenApiTest, CheckMethodSignatureTrailingCharsNoMatch) {
397   ScopedObjectAccess soa(self_);
398   std::string prefix("Lmypackage/packagea/Class1;->method1()Vfoo");
399   ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
400 }
401 
TEST_F(HiddenApiTest,CheckConstructorTrailingCharsNoMatch)402 TEST_F(HiddenApiTest, CheckConstructorTrailingCharsNoMatch) {
403   ScopedObjectAccess soa(self_);
404   std::string prefix("Lmypackage/packagea/Class1;-><init>()Vfoo");
405   ASSERT_FALSE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
406 }
407 
TEST_F(HiddenApiTest,CheckFieldTrailingCharsNoMatch)408 TEST_F(HiddenApiTest, CheckFieldTrailingCharsNoMatch) {
409   ScopedObjectAccess soa(self_);
410   std::string prefix("Lmypackage/packagea/Class1;->field1:Ifoo");
411   ASSERT_FALSE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
412 }
413 
TEST_F(HiddenApiTest,CheckMemberSignatureForProxyClass)414 TEST_F(HiddenApiTest, CheckMemberSignatureForProxyClass) {
415   ScopedObjectAccess soa(self_);
416   StackHandleScope<4> hs(soa.Self());
417   Handle<mirror::ClassLoader> class_loader(
418       hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader_)));
419 
420   // Find interface we will create a proxy for.
421   Handle<mirror::Class> h_iface(hs.NewHandle(
422       class_linker_->FindClass(soa.Self(), "Lmypackage/packagea/Interface;", class_loader)));
423   ASSERT_TRUE(h_iface != nullptr);
424 
425   // Create the proxy class.
426   std::vector<Handle<mirror::Class>> interfaces;
427   interfaces.push_back(h_iface);
428   Handle<mirror::Class> proxyClass = hs.NewHandle(proxy_test::GenerateProxyClass(
429       soa, jclass_loader_, runtime_->GetClassLinker(), "$Proxy1234", interfaces));
430   ASSERT_TRUE(proxyClass != nullptr);
431   ASSERT_TRUE(proxyClass->IsProxyClass());
432   ASSERT_TRUE(proxyClass->IsInitialized());
433 
434   // Find the "method" virtual method.
435   ArtMethod* method = nullptr;
436   for (auto& m : proxyClass->GetDeclaredVirtualMethods(kRuntimePointerSize)) {
437     if (strcmp("method", m.GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetName()) == 0) {
438       method = &m;
439       break;
440     }
441   }
442   ASSERT_TRUE(method != nullptr);
443 
444   // Find the "interfaces" static field. This is generated for all proxies.
445   ArtField* field = nullptr;
446   for (size_t i = 0; i < proxyClass->NumStaticFields(); ++i) {
447     ArtField* f = proxyClass->GetStaticField(i);
448     if (strcmp("interfaces", f->GetName()) == 0) {
449       field = f;
450       break;
451     }
452   }
453   ASSERT_TRUE(field != nullptr);
454 
455   // Test the signature. We expect the signature from the interface class.
456   std::ostringstream ss_method;
457   MemberSignature(method->GetInterfaceMethodIfProxy(kRuntimePointerSize)).Dump(ss_method);
458   ASSERT_EQ("Lmypackage/packagea/Interface;->method()V", ss_method.str());
459 
460   // Test the signature. We expect the signature of the proxy class.
461   std::ostringstream ss_field;
462   MemberSignature(field).Dump(ss_field);
463   ASSERT_EQ("L$Proxy1234;->interfaces:[Ljava/lang/Class;", ss_field.str());
464 }
465 
Copy(const std::string & src,const std::string & dst,std::string * error_msg)466 static bool Copy(const std::string& src, const std::string& dst, /*out*/ std::string* error_msg) {
467   std::ifstream  src_stream(src, std::ios::binary);
468   std::ofstream  dst_stream(dst, std::ios::binary);
469   dst_stream << src_stream.rdbuf();
470   src_stream.close();
471   dst_stream.close();
472   if (src_stream.good() && dst_stream.good()) {
473     return true;
474   } else {
475     *error_msg = "Copy " + src + " => " + dst + " (src_good="
476         + (src_stream.good() ? "true" : "false") + ", dst_good="
477         + (dst_stream.good() ? "true" : "false") + ")";
478     return false;
479   }
480 }
481 
LoadDexFiles(const std::string & path,ScopedObjectAccess & soa,std::vector<std::unique_ptr<const DexFile>> * dex_files,ObjPtr<mirror::ClassLoader> * class_loader,std::string * error_msg)482 static bool LoadDexFiles(const std::string& path,
483                          ScopedObjectAccess& soa,
484                          /* out */ std::vector<std::unique_ptr<const DexFile>>* dex_files,
485                          /* out */ ObjPtr<mirror::ClassLoader>* class_loader,
486                          /* out */ std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
487   if (!ArtDexFileLoader().Open(path.c_str(),
488                                path,
489                                /* verify= */ true,
490                                /* verify_checksum= */ true,
491                                error_msg,
492                                dex_files)) {
493     return false;
494   }
495 
496   ClassLinker* const linker = Runtime::Current()->GetClassLinker();
497 
498   StackHandleScope<2> hs(soa.Self());
499   Handle<mirror::Class> h_class = hs.NewHandle(soa.Decode<mirror::Class>(
500       WellKnownClasses::dalvik_system_PathClassLoader));
501   Handle<mirror::ClassLoader> h_loader = hs.NewHandle(linker->CreateWellKnownClassLoader(
502       soa.Self(),
503       MakeNonOwningPointerVector(*dex_files),
504       h_class,
505       /* parent_loader= */ ScopedNullHandle<mirror::ClassLoader>(),
506       /* shared_libraries= */ ScopedNullHandle<mirror::ObjectArray<mirror::ClassLoader>>()));
507   for (const auto& dex_file : *dex_files) {
508     linker->RegisterDexFile(*dex_file.get(), h_loader.Get());
509   }
510 
511   *class_loader = h_loader.Get();
512   return true;
513 }
514 
CheckAllDexFilesInDomain(ObjPtr<mirror::ClassLoader> loader,const std::vector<std::unique_ptr<const DexFile>> & dex_files,hiddenapi::Domain expected_domain,std::string * error_msg)515 static bool CheckAllDexFilesInDomain(ObjPtr<mirror::ClassLoader> loader,
516                                      const std::vector<std::unique_ptr<const DexFile>>& dex_files,
517                                      hiddenapi::Domain expected_domain,
518                                      /* out */ std::string* error_msg)
519     REQUIRES_SHARED(Locks::mutator_lock_) {
520   for (const auto& dex_file : dex_files) {
521     hiddenapi::AccessContext context(loader, dex_file.get());
522     if (context.GetDomain() != expected_domain) {
523       std::stringstream ss;
524       ss << dex_file->GetLocation() << ": access context domain does not match "
525           << "(expected=" << static_cast<uint32_t>(expected_domain)
526           << ", actual=" << static_cast<uint32_t>(context.GetDomain()) << ")";
527       *error_msg = ss.str();
528       return false;
529     }
530     if (dex_file->GetHiddenapiDomain() != expected_domain) {
531       std::stringstream ss;
532       ss << dex_file->GetLocation() << ": dex file domain does not match "
533           << "(expected=" << static_cast<uint32_t>(expected_domain)
534           << ", actual=" << static_cast<uint32_t>(dex_file->GetHiddenapiDomain()) << ")";
535       *error_msg = ss.str();
536       return false;
537     }
538   }
539 
540   return true;
541 }
542 
TEST_F(HiddenApiTest,DexDomain_DataDir)543 TEST_F(HiddenApiTest, DexDomain_DataDir) {
544   // Load file from a non-system directory and check that it is not flagged as framework.
545   std::string data_location_path = android_data_ + "/foo.jar";
546   ASSERT_FALSE(LocationIsOnSystemFramework(data_location_path.c_str()));
547 
548   ScopedObjectAccess soa(Thread::Current());
549   std::vector<std::unique_ptr<const DexFile>> dex_files;
550   std::string error_msg;
551   ObjPtr<mirror::ClassLoader> class_loader;
552 
553   ASSERT_TRUE(Copy(GetTestDexFileName("Main"), data_location_path, &error_msg)) << error_msg;
554   ASSERT_TRUE(LoadDexFiles(data_location_path, soa, &dex_files, &class_loader, &error_msg))
555       << error_msg;
556   ASSERT_GE(dex_files.size(), 1u);
557   ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
558                                        dex_files,
559                                        hiddenapi::Domain::kApplication,
560                                        &error_msg)) << error_msg;
561 
562   dex_files.clear();
563   ASSERT_EQ(0, remove(data_location_path.c_str()));
564 }
565 
TEST_F(HiddenApiTest,DexDomain_SystemDir)566 TEST_F(HiddenApiTest, DexDomain_SystemDir) {
567   // Load file from a system, non-framework directory and check that it is not flagged as framework.
568   std::string system_location_path = GetAndroidRoot() + "/foo.jar";
569   ASSERT_FALSE(LocationIsOnSystemFramework(system_location_path.c_str()));
570 
571   ScopedObjectAccess soa(Thread::Current());
572   std::vector<std::unique_ptr<const DexFile>> dex_files;
573   std::string error_msg;
574   ObjPtr<mirror::ClassLoader> class_loader;
575 
576   ASSERT_TRUE(Copy(GetTestDexFileName("Main"), system_location_path, &error_msg)) << error_msg;
577   ASSERT_TRUE(LoadDexFiles(system_location_path, soa, &dex_files, &class_loader, &error_msg))
578       << error_msg;
579   ASSERT_GE(dex_files.size(), 1u);
580   ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
581                                        dex_files,
582                                        hiddenapi::Domain::kApplication,
583                                        &error_msg)) << error_msg;
584 
585   dex_files.clear();
586   ASSERT_EQ(0, remove(system_location_path.c_str()));
587 }
588 
TEST_F(HiddenApiTest,DexDomain_SystemFrameworkDir)589 TEST_F(HiddenApiTest, DexDomain_SystemFrameworkDir) {
590   // Load file from a system/framework directory and check that it is flagged as a framework dex.
591   std::string system_framework_location_path = GetAndroidRoot() + "/framework/foo.jar";
592   ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_location_path.c_str()));
593 
594   ScopedObjectAccess soa(Thread::Current());
595   std::vector<std::unique_ptr<const DexFile>> dex_files;
596   std::string error_msg;
597   ObjPtr<mirror::ClassLoader> class_loader;
598 
599   ASSERT_TRUE(Copy(GetTestDexFileName("Main"), system_framework_location_path, &error_msg))
600       << error_msg;
601   ASSERT_TRUE(LoadDexFiles(system_framework_location_path,
602                            soa,
603                            &dex_files,
604                            &class_loader,
605                            &error_msg)) << error_msg;
606   ASSERT_GE(dex_files.size(), 1u);
607   ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
608                                        dex_files,
609                                        hiddenapi::Domain::kPlatform,
610                                        &error_msg)) << error_msg;
611 
612   dex_files.clear();
613   ASSERT_EQ(0, remove(system_framework_location_path.c_str()));
614 }
615 
TEST_F(HiddenApiTest,DexDomain_DataDir_MultiDex)616 TEST_F(HiddenApiTest, DexDomain_DataDir_MultiDex) {
617   // Load multidex file from a non-system directory and check that it is not flagged as framework.
618   std::string data_multi_location_path = android_data_ + "/multifoo.jar";
619   ASSERT_FALSE(LocationIsOnSystemFramework(data_multi_location_path.c_str()));
620 
621   ScopedObjectAccess soa(Thread::Current());
622   std::vector<std::unique_ptr<const DexFile>> dex_files;
623   std::string error_msg;
624   ObjPtr<mirror::ClassLoader> class_loader;
625 
626   ASSERT_TRUE(Copy(GetTestDexFileName("MultiDex"), data_multi_location_path, &error_msg))
627       << error_msg;
628   ASSERT_TRUE(LoadDexFiles(data_multi_location_path, soa, &dex_files, &class_loader, &error_msg))
629       << error_msg;
630   ASSERT_GE(dex_files.size(), 1u);
631   ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
632                                        dex_files,
633                                        hiddenapi::Domain::kApplication,
634                                        &error_msg)) << error_msg;
635 
636   dex_files.clear();
637   ASSERT_EQ(0, remove(data_multi_location_path.c_str()));
638 }
639 
TEST_F(HiddenApiTest,DexDomain_SystemDir_MultiDex)640 TEST_F(HiddenApiTest, DexDomain_SystemDir_MultiDex) {
641   // Load multidex file from a system, non-framework directory and check that it is not flagged
642   // as framework.
643   std::string system_multi_location_path = GetAndroidRoot() + "/multifoo.jar";
644   ASSERT_FALSE(LocationIsOnSystemFramework(system_multi_location_path.c_str()));
645 
646   ScopedObjectAccess soa(Thread::Current());
647   std::vector<std::unique_ptr<const DexFile>> dex_files;
648   std::string error_msg;
649   ObjPtr<mirror::ClassLoader> class_loader;
650 
651   ASSERT_TRUE(Copy(GetTestDexFileName("MultiDex"), system_multi_location_path, &error_msg))
652       << error_msg;
653   ASSERT_TRUE(LoadDexFiles(system_multi_location_path, soa, &dex_files, &class_loader, &error_msg))
654       << error_msg;
655   ASSERT_GT(dex_files.size(), 1u);
656   ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
657                                        dex_files,
658                                        hiddenapi::Domain::kApplication,
659                                        &error_msg)) << error_msg;
660 
661   dex_files.clear();
662   ASSERT_EQ(0, remove(system_multi_location_path.c_str()));
663 }
664 
TEST_F(HiddenApiTest,DexDomain_SystemFrameworkDir_MultiDex)665 TEST_F(HiddenApiTest, DexDomain_SystemFrameworkDir_MultiDex) {
666   // Load multidex file from a system/framework directory and check that it is flagged as a
667   // framework dex.
668   std::string system_framework_multi_location_path = GetAndroidRoot() + "/framework/multifoo.jar";
669   ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_multi_location_path.c_str()));
670 
671   ScopedObjectAccess soa(Thread::Current());
672   std::vector<std::unique_ptr<const DexFile>> dex_files;
673   std::string error_msg;
674   ObjPtr<mirror::ClassLoader> class_loader;
675 
676   ASSERT_TRUE(Copy(GetTestDexFileName("MultiDex"),
677                    system_framework_multi_location_path,
678                    &error_msg)) << error_msg;
679   ASSERT_TRUE(LoadDexFiles(system_framework_multi_location_path,
680                            soa,
681                            &dex_files,
682                            &class_loader,
683                            &error_msg)) << error_msg;
684   ASSERT_GT(dex_files.size(), 1u);
685   ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
686                                        dex_files,
687                                        hiddenapi::Domain::kPlatform,
688                                        &error_msg)) << error_msg;
689 
690   dex_files.clear();
691   ASSERT_EQ(0, remove(system_framework_multi_location_path.c_str()));
692 }
693 
694 }  // namespace art
695