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