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/systrace.h"
24 #include "base/utils.h"
25 #include "class_linker.h"
26 #include "compiler_callbacks.h"
27 #include "dex/class_accessor-inl.h"
28 #include "dex/class_reference.h"
29 #include "dex/descriptors_names.h"
30 #include "dex/dex_file-inl.h"
31 #include "handle_scope-inl.h"
32 #include "method_verifier-inl.h"
33 #include "mirror/class-inl.h"
34 #include "mirror/dex_cache.h"
35 #include "runtime.h"
36 
37 namespace art {
38 namespace verifier {
39 
40 using android::base::StringPrintf;
41 
42 // We print a warning blurb about "dx --no-optimize" when we find monitor-locking issues. Make
43 // sure we only print this once.
44 static bool gPrintedDxMonitorText = false;
45 
VerifyClass(Thread * self,ObjPtr<mirror::Class> klass,CompilerCallbacks * callbacks,bool allow_soft_failures,HardFailLogMode log_level,uint32_t api_level,std::string * error)46 FailureKind ClassVerifier::VerifyClass(Thread* self,
47                                        ObjPtr<mirror::Class> klass,
48                                        CompilerCallbacks* callbacks,
49                                        bool allow_soft_failures,
50                                        HardFailLogMode log_level,
51                                        uint32_t api_level,
52                                        std::string* error) {
53   if (klass->IsVerified()) {
54     return FailureKind::kNoFailure;
55   }
56   bool early_failure = false;
57   std::string failure_message;
58   const DexFile& dex_file = klass->GetDexFile();
59   const dex::ClassDef* class_def = klass->GetClassDef();
60   ObjPtr<mirror::Class> super = klass->GetSuperClass();
61   std::string temp;
62   if (super == nullptr && strcmp("Ljava/lang/Object;", klass->GetDescriptor(&temp)) != 0) {
63     early_failure = true;
64     failure_message = " that has no super class";
65   } else if (super != nullptr && super->IsFinal()) {
66     early_failure = true;
67     failure_message = " that attempts to sub-class final class " + super->PrettyDescriptor();
68   } else if (class_def == nullptr) {
69     early_failure = true;
70     failure_message = " that isn't present in dex file " + dex_file.GetLocation();
71   }
72   if (early_failure) {
73     *error = "Verifier rejected class " + klass->PrettyDescriptor() + failure_message;
74     if (callbacks != nullptr) {
75       ClassReference ref(&dex_file, klass->GetDexClassDefIndex());
76       callbacks->ClassRejected(ref);
77     }
78     return FailureKind::kHardFailure;
79   }
80   StackHandleScope<2> hs(self);
81   Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
82   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
83   return VerifyClass(self,
84                      &dex_file,
85                      dex_cache,
86                      class_loader,
87                      *class_def,
88                      callbacks,
89                      allow_soft_failures,
90                      log_level,
91                      api_level,
92                      error);
93 }
94 
VerifyClass(Thread * self,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)95 FailureKind ClassVerifier::VerifyClass(Thread* self,
96                                        const DexFile* dex_file,
97                                        Handle<mirror::DexCache> dex_cache,
98                                        Handle<mirror::ClassLoader> class_loader,
99                                        const dex::ClassDef& class_def,
100                                        CompilerCallbacks* callbacks,
101                                        bool allow_soft_failures,
102                                        HardFailLogMode log_level,
103                                        uint32_t api_level,
104                                        std::string* error) {
105   // A class must not be abstract and final.
106   if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
107     *error = "Verifier rejected class ";
108     *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
109     *error += ": class is abstract and final.";
110     return FailureKind::kHardFailure;
111   }
112 
113   ClassAccessor accessor(*dex_file, class_def);
114   SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(accessor.GetDescriptor());
115 
116   int64_t previous_method_idx[2] = { -1, -1 };
117   MethodVerifier::FailureData failure_data;
118   ClassLinker* const linker = Runtime::Current()->GetClassLinker();
119 
120   for (const ClassAccessor::Method& method : accessor.GetMethods()) {
121     int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
122     self->AllowThreadSuspension();
123     const uint32_t method_idx = method.GetIndex();
124     if (method_idx == *previous_idx) {
125       // smali can create dex files with two encoded_methods sharing the same method_idx
126       // http://code.google.com/p/smali/issues/detail?id=119
127       continue;
128     }
129     *previous_idx = method_idx;
130     const InvokeType type = method.GetInvokeType(class_def.access_flags_);
131     ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
132         method_idx, dex_cache, class_loader, /* referrer= */ nullptr, type);
133     if (resolved_method == nullptr) {
134       DCHECK(self->IsExceptionPending());
135       // We couldn't resolve the method, but continue regardless.
136       self->ClearException();
137     } else {
138       DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
139     }
140     std::string hard_failure_msg;
141     MethodVerifier::FailureData result =
142         MethodVerifier::VerifyMethod(self,
143                                      method_idx,
144                                      dex_file,
145                                      dex_cache,
146                                      class_loader,
147                                      class_def,
148                                      method.GetCodeItem(),
149                                      resolved_method,
150                                      method.GetAccessFlags(),
151                                      callbacks,
152                                      allow_soft_failures,
153                                      log_level,
154                                      /*need_precise_constants=*/ false,
155                                      api_level,
156                                      &hard_failure_msg);
157     if (result.kind == FailureKind::kHardFailure) {
158       if (failure_data.kind == FailureKind::kHardFailure) {
159         // If we logged an error before, we need a newline.
160         *error += "\n";
161       } else {
162         // If we didn't log a hard failure before, print the header of the message.
163         *error += "Verifier rejected class ";
164         *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
165         *error += ":";
166       }
167       *error += " ";
168       *error += hard_failure_msg;
169     }
170     failure_data.Merge(result);
171   }
172 
173   if (failure_data.kind == FailureKind::kNoFailure) {
174     return FailureKind::kNoFailure;
175   } else {
176     if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) {
177       // Print a warning about expected slow-down. Use a string temporary to print one contiguous
178       // warning.
179       std::string tmp =
180           StringPrintf("Class %s failed lock verification and will run slower.",
181                        PrettyDescriptor(accessor.GetDescriptor()).c_str());
182       if (!gPrintedDxMonitorText) {
183         tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
184                     "and incorrect proguard optimizations.";
185         gPrintedDxMonitorText = true;
186       }
187       LOG(WARNING) << tmp;
188     }
189     return failure_data.kind;
190   }
191 }
192 
Init()193 void ClassVerifier::Init() {
194   MethodVerifier::Init();
195 }
196 
Shutdown()197 void ClassVerifier::Shutdown() {
198   MethodVerifier::Shutdown();
199 }
200 
VisitStaticRoots(RootVisitor * visitor)201 void ClassVerifier::VisitStaticRoots(RootVisitor* visitor) {
202   MethodVerifier::VisitStaticRoots(visitor);
203 }
204 
205 }  // namespace verifier
206 }  // namespace art
207