1 /*
2 * Copyright (C) 2011 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 "class_verifier.h"
18
19 #include <android-base/logging.h>
20 #include <android-base/stringprintf.h>
21
22 #include "art_method-inl.h"
23 #include "base/enums.h"
24 #include "base/locks.h"
25 #include "base/logging.h"
26 #include "base/systrace.h"
27 #include "base/utils.h"
28 #include "class_linker.h"
29 #include "compiler_callbacks.h"
30 #include "dex/class_accessor-inl.h"
31 #include "dex/class_reference.h"
32 #include "dex/descriptors_names.h"
33 #include "dex/dex_file-inl.h"
34 #include "handle.h"
35 #include "handle_scope-inl.h"
36 #include "method_verifier-inl.h"
37 #include "mirror/class-inl.h"
38 #include "mirror/dex_cache.h"
39 #include "runtime.h"
40 #include "thread.h"
41 #include "verifier/method_verifier.h"
42 #include "verifier/reg_type_cache.h"
43
44 namespace art {
45 namespace verifier {
46
47 using android::base::StringPrintf;
48
49 // We print a warning blurb about "dx --no-optimize" when we find monitor-locking issues. Make
50 // sure we only print this once.
51 static bool gPrintedDxMonitorText = false;
52
53 class StandardVerifyCallback : public VerifierCallback {
54 public:
SetDontCompile(ArtMethod * m,bool value)55 void SetDontCompile(ArtMethod* m, bool value) override REQUIRES_SHARED(Locks::mutator_lock_) {
56 if (value) {
57 m->SetDontCompile();
58 }
59 }
SetMustCountLocks(ArtMethod * m,bool value)60 void SetMustCountLocks(ArtMethod* m, bool value) override REQUIRES_SHARED(Locks::mutator_lock_) {
61 if (value) {
62 m->SetMustCountLocks();
63 }
64 }
65 };
66
ReverifyClass(Thread * self,ObjPtr<mirror::Class> klass,HardFailLogMode log_level,uint32_t api_level,std::string * error)67 FailureKind ClassVerifier::ReverifyClass(Thread* self,
68 ObjPtr<mirror::Class> klass,
69 HardFailLogMode log_level,
70 uint32_t api_level,
71 std::string* error) {
72 DCHECK(!Runtime::Current()->IsAotCompiler());
73 StackHandleScope<1> hs(self);
74 Handle<mirror::Class> h_klass(hs.NewHandle(klass));
75 // We don't want to mess with these while other mutators are possibly looking at them. Instead we
76 // will wait until we can update them while everything is suspended.
77 class DelayedVerifyCallback : public VerifierCallback {
78 public:
79 void SetDontCompile(ArtMethod* m, bool value) override REQUIRES_SHARED(Locks::mutator_lock_) {
80 dont_compiles_.push_back({ m, value });
81 }
82 void SetMustCountLocks(ArtMethod* m, bool value) override
83 REQUIRES_SHARED(Locks::mutator_lock_) {
84 count_locks_.push_back({ m, value });
85 }
86 void UpdateFlags(bool skip_access_checks) REQUIRES(Locks::mutator_lock_) {
87 for (auto it : count_locks_) {
88 VLOG(verifier_debug) << "Setting " << it.first->PrettyMethod() << " count locks to "
89 << it.second;
90 if (it.second) {
91 it.first->SetMustCountLocks();
92 } else {
93 it.first->ClearMustCountLocks();
94 }
95 if (skip_access_checks && it.first->IsInvokable() && !it.first->IsNative()) {
96 it.first->SetSkipAccessChecks();
97 }
98 }
99 for (auto it : dont_compiles_) {
100 VLOG(verifier_debug) << "Setting " << it.first->PrettyMethod() << " dont-compile to "
101 << it.second;
102 if (it.second) {
103 it.first->SetDontCompile();
104 } else {
105 it.first->ClearDontCompile();
106 }
107 }
108 }
109
110 private:
111 std::vector<std::pair<ArtMethod*, bool>> dont_compiles_;
112 std::vector<std::pair<ArtMethod*, bool>> count_locks_;
113 };
114 DelayedVerifyCallback dvc;
115 FailureKind res = CommonVerifyClass(self,
116 /*verifier_deps=*/nullptr,
117 h_klass.Get(),
118 /*callbacks=*/nullptr,
119 &dvc,
120 /*allow_soft_failures=*/false,
121 log_level,
122 api_level,
123 error);
124 DCHECK_NE(res, FailureKind::kHardFailure);
125 ScopedThreadSuspension sts(Thread::Current(), ThreadState::kSuspended);
126 ScopedSuspendAll ssa("Update method flags for reverify");
127 dvc.UpdateFlags(res == FailureKind::kNoFailure);
128 return res;
129 }
130
VerifyClass(Thread * self,VerifierDeps * verifier_deps,ObjPtr<mirror::Class> klass,CompilerCallbacks * callbacks,bool allow_soft_failures,HardFailLogMode log_level,uint32_t api_level,std::string * error)131 FailureKind ClassVerifier::VerifyClass(Thread* self,
132 VerifierDeps* verifier_deps,
133 ObjPtr<mirror::Class> klass,
134 CompilerCallbacks* callbacks,
135 bool allow_soft_failures,
136 HardFailLogMode log_level,
137 uint32_t api_level,
138 std::string* error) {
139 if (klass->IsVerified()) {
140 return FailureKind::kNoFailure;
141 }
142 StandardVerifyCallback svc;
143 return CommonVerifyClass(self,
144 verifier_deps,
145 klass,
146 callbacks,
147 &svc,
148 allow_soft_failures,
149 log_level,
150 api_level,
151 error);
152 }
153
CommonVerifyClass(Thread * self,VerifierDeps * verifier_deps,ObjPtr<mirror::Class> klass,CompilerCallbacks * callbacks,VerifierCallback * verifier_callback,bool allow_soft_failures,HardFailLogMode log_level,uint32_t api_level,std::string * error)154 FailureKind ClassVerifier::CommonVerifyClass(Thread* self,
155 VerifierDeps* verifier_deps,
156 ObjPtr<mirror::Class> klass,
157 CompilerCallbacks* callbacks,
158 VerifierCallback* verifier_callback,
159 bool allow_soft_failures,
160 HardFailLogMode log_level,
161 uint32_t api_level,
162 std::string* error) {
163 bool early_failure = false;
164 std::string failure_message;
165 const DexFile& dex_file = klass->GetDexFile();
166 const dex::ClassDef* class_def = klass->GetClassDef();
167 ObjPtr<mirror::Class> super = klass->GetSuperClass();
168 std::string temp;
169 if (super == nullptr && strcmp("Ljava/lang/Object;", klass->GetDescriptor(&temp)) != 0) {
170 early_failure = true;
171 failure_message = " that has no super class";
172 } else if (super != nullptr && super->IsFinal()) {
173 early_failure = true;
174 failure_message = " that attempts to sub-class final class " + super->PrettyDescriptor();
175 } else if (class_def == nullptr) {
176 early_failure = true;
177 failure_message = " that isn't present in dex file " + dex_file.GetLocation();
178 }
179 if (early_failure) {
180 *error = "Verifier rejected class " + klass->PrettyDescriptor() + failure_message;
181 if (callbacks != nullptr) {
182 ClassReference ref(&dex_file, klass->GetDexClassDefIndex());
183 callbacks->ClassRejected(ref);
184 }
185 return FailureKind::kHardFailure;
186 }
187 StackHandleScope<2> hs(self);
188 Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
189 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
190 return VerifyClass(self,
191 verifier_deps,
192 &dex_file,
193 dex_cache,
194 class_loader,
195 *class_def,
196 callbacks,
197 verifier_callback,
198 allow_soft_failures,
199 log_level,
200 api_level,
201 error);
202 }
203
204
VerifyClass(Thread * self,VerifierDeps * verifier_deps,const DexFile * dex_file,Handle<mirror::DexCache> dex_cache,Handle<mirror::ClassLoader> class_loader,const dex::ClassDef & class_def,CompilerCallbacks * callbacks,bool allow_soft_failures,HardFailLogMode log_level,uint32_t api_level,std::string * error)205 FailureKind ClassVerifier::VerifyClass(Thread* self,
206 VerifierDeps* verifier_deps,
207 const DexFile* dex_file,
208 Handle<mirror::DexCache> dex_cache,
209 Handle<mirror::ClassLoader> class_loader,
210 const dex::ClassDef& class_def,
211 CompilerCallbacks* callbacks,
212 bool allow_soft_failures,
213 HardFailLogMode log_level,
214 uint32_t api_level,
215 std::string* error) {
216 StandardVerifyCallback svc;
217 return VerifyClass(self,
218 verifier_deps,
219 dex_file,
220 dex_cache,
221 class_loader,
222 class_def,
223 callbacks,
224 &svc,
225 allow_soft_failures,
226 log_level,
227 api_level,
228 error);
229 }
230
VerifyClass(Thread * self,VerifierDeps * verifier_deps,const DexFile * dex_file,Handle<mirror::DexCache> dex_cache,Handle<mirror::ClassLoader> class_loader,const dex::ClassDef & class_def,CompilerCallbacks * callbacks,VerifierCallback * verifier_callback,bool allow_soft_failures,HardFailLogMode log_level,uint32_t api_level,std::string * error)231 FailureKind ClassVerifier::VerifyClass(Thread* self,
232 VerifierDeps* verifier_deps,
233 const DexFile* dex_file,
234 Handle<mirror::DexCache> dex_cache,
235 Handle<mirror::ClassLoader> class_loader,
236 const dex::ClassDef& class_def,
237 CompilerCallbacks* callbacks,
238 VerifierCallback* verifier_callback,
239 bool allow_soft_failures,
240 HardFailLogMode log_level,
241 uint32_t api_level,
242 std::string* error) {
243 // A class must not be abstract and final.
244 if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
245 *error = "Verifier rejected class ";
246 *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
247 *error += ": class is abstract and final.";
248 return FailureKind::kHardFailure;
249 }
250
251 ClassAccessor accessor(*dex_file, class_def);
252 SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(accessor.GetDescriptor());
253 metrics::AutoTimer timer{GetMetrics()->ClassVerificationTotalTime()};
254
255 int64_t previous_method_idx[2] = { -1, -1 };
256 MethodVerifier::FailureData failure_data;
257 ClassLinker* const linker = Runtime::Current()->GetClassLinker();
258
259 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
260 int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
261 self->AllowThreadSuspension();
262 const uint32_t method_idx = method.GetIndex();
263 if (method_idx == *previous_idx) {
264 // smali can create dex files with two encoded_methods sharing the same method_idx
265 // http://code.google.com/p/smali/issues/detail?id=119
266 continue;
267 }
268 *previous_idx = method_idx;
269 const InvokeType type = method.GetInvokeType(class_def.access_flags_);
270 ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
271 method_idx, dex_cache, class_loader, /* referrer= */ nullptr, type);
272 if (resolved_method == nullptr) {
273 DCHECK(self->IsExceptionPending());
274 // We couldn't resolve the method, but continue regardless.
275 self->ClearException();
276 } else {
277 DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
278 }
279 std::string hard_failure_msg;
280 MethodVerifier::FailureData result =
281 MethodVerifier::VerifyMethod(self,
282 linker,
283 Runtime::Current()->GetArenaPool(),
284 verifier_deps,
285 method_idx,
286 dex_file,
287 dex_cache,
288 class_loader,
289 class_def,
290 method.GetCodeItem(),
291 resolved_method,
292 method.GetAccessFlags(),
293 callbacks,
294 verifier_callback,
295 allow_soft_failures,
296 log_level,
297 /*need_precise_constants=*/ false,
298 api_level,
299 Runtime::Current()->IsAotCompiler(),
300 &hard_failure_msg);
301 if (result.kind == FailureKind::kHardFailure) {
302 if (failure_data.kind == FailureKind::kHardFailure) {
303 // If we logged an error before, we need a newline.
304 *error += "\n";
305 } else {
306 // If we didn't log a hard failure before, print the header of the message.
307 *error += "Verifier rejected class ";
308 *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
309 *error += ":";
310 }
311 *error += " ";
312 *error += hard_failure_msg;
313 }
314 failure_data.Merge(result);
315 }
316 uint64_t elapsed_time_microseconds = timer.Stop();
317 VLOG(verifier) << "VerifyClass took " << PrettyDuration(UsToNs(elapsed_time_microseconds))
318 << ", class: " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
319
320 GetMetrics()->ClassVerificationCount()->AddOne();
321
322 if (failure_data.kind == FailureKind::kNoFailure) {
323 return FailureKind::kNoFailure;
324 } else {
325 if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) {
326 // Print a warning about expected slow-down. Use a string temporary to print one contiguous
327 // warning.
328 std::string tmp =
329 StringPrintf("Class %s failed lock verification and will run slower.",
330 PrettyDescriptor(accessor.GetDescriptor()).c_str());
331 if (!gPrintedDxMonitorText) {
332 tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
333 "and incorrect proguard optimizations.";
334 gPrintedDxMonitorText = true;
335 }
336 LOG(WARNING) << tmp;
337 }
338 return failure_data.kind;
339 }
340 }
341
Init(ClassLinker * class_linker)342 void ClassVerifier::Init(ClassLinker* class_linker) {
343 MethodVerifier::Init(class_linker);
344 }
345
Shutdown()346 void ClassVerifier::Shutdown() {
347 MethodVerifier::Shutdown();
348 }
349
VisitStaticRoots(RootVisitor * visitor)350 void ClassVerifier::VisitStaticRoots(RootVisitor* visitor) {
351 MethodVerifier::VisitStaticRoots(visitor);
352 }
353
354 } // namespace verifier
355 } // namespace art
356