ART Learning Series: Android 9's Hidden Api Breakthrough - Meta-reflection Principle Explanation
ART Learning Series: Android 9's Hidden Api Breakthrough - Meta-reflection Principle Explanation
train of thought
1. Android 9 IsCallerTrusted method analysis
2. The role of hiddenapi::IsCallerTrusted
3. Call logic of VisitFrame
55
static bool IsCallerTrusted(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
56 // Walk the stack and find the first frame not from java.lang.Class and not from java.lang.invoke.
57 // This is very expensive. Save this till the last.
58 struct FirstExternalCallerVisitor : public StackVisitor {
59 explicit FirstExternalCallerVisitor(Thread* thread)
60 : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
61 caller(nullptr) {
62 }
63
64 bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
65 ArtMethod *m = GetMethod();
66 if (m == nullptr) {
67 // Attached native thread. Assume this is *not* boot class path.
68 caller = nullptr;
69 return false;
70 } else if (m->IsRuntimeMethod()) {
71 // Internal runtime method, continue walking the stack.
72 return true;
73 }
74
75 ObjPtr<mirror::Class> declaring_class = m->GetDeclaringClass();
76 if (declaring_class->IsBootStrapClassLoaded()) {
77 if (declaring_class->IsClassClass()) {
78 return true;
79 }
80 // Check classes in the java.lang.invoke package. At the time of writing, the
81 // classes of interest are MethodHandles and MethodHandles.Lookup, but this
82 // is subject to change so conservatively cover the entire package.
83 // NB Static initializers within java.lang.invoke are permitted and do not
84 // need further stack inspection.
85 ObjPtr<mirror::Class> lookup_class = mirror::MethodHandlesLookup::StaticClass();
86 if ((declaring_class == lookup_class || declaring_class->IsInSamePackage(lookup_class))
87 && !m->IsClassInitializer()) {
88 return true;
89 }
90 }
91
92 caller = m;
93 return false;
94 }
95
96 ArtMethod* caller;
97 };
98
99 FirstExternalCallerVisitor visitor(self);
100 visitor.WalkStack();
101 return visitor.caller != nullptr &&
102 hiddenapi::IsCallerTrusted(visitor.caller->GetDeclaringClass());
103 }
Break it down
static bool IsCallerTrusted(Thread* self)
// 创建 vsitor 对象
FirstExternalCallerVisitor visitor(self);
// vsitor 对象通过walk stack 方法遍历堆栈
visitor.WalkStack();
// 如果 visitor.caller 不为空 则通过hiddenapi::IsCallerTrusted 再次判断
return visitor.caller != nullptr &&
hiddenapi::IsCallerTrusted(visitor.caller->GetDeclaringClass());
}
hiddenapi::IsCallerTrusted
inline bool IsCallerTrusted(ObjPtr<mirror::Class> caller) REQUIRES_SHARED(Locks::mutator_lock_) {
231 return !caller.IsNull() &&
232 detail::IsCallerTrusted(caller, caller->GetClassLoader(), caller->GetDexCache());
233 }
161 ALWAYS_INLINE
162 inline bool IsCallerTrusted(ObjPtr<mirror::Class> caller,
163 ObjPtr<mirror::ClassLoader> caller_class_loader,
164 ObjPtr<mirror::DexCache> caller_dex_cache)
165 REQUIRES_SHARED(Locks::mutator_lock_) {
166 if (caller_class_loader.IsNull()) {
167 // Boot class loader.
168 return true;
169 }
170
171 if (!caller_dex_cache.IsNull()) {
172 const DexFile* caller_dex_file = caller_dex_cache->GetDexFile();
173 if (caller_dex_file != nullptr && caller_dex_file->IsPlatformDexFile()) {
174 // Caller is in a platform dex file.
175 return true;
176 }
177 }
178
179 if (!caller.IsNull() &&
180 caller->ShouldSkipHiddenApiChecks() &&
181 Runtime::Current()->IsJavaDebuggable()) {
182 // We are in debuggable mode and this caller has been marked trusted.
183 return true;
184 }
185
186 return false;
187 }
visitor.WalkStack(); See how your walkstack traverses the stack
// /art/runtime/stack.cc
766 void StackVisitor::WalkStack(bool include_transitions) {
767
771 bool exit_stubs_installed = Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled();
772 uint32_t instrumentation_stack_depth = 0;
773 size_t inlined_frames_count = 0;
774
775 for (const ManagedStack* current_fragment = thread_->GetManagedStack();
776 current_fragment != nullptr; current_fragment = current_fragment->GetLink()) {
777 cur_shadow_frame_ = current_fragment->GetTopShadowFrame();
778 cur_quick_frame_ = current_fragment->GetTopQuickFrame();
779 cur_quick_frame_pc_ = 0;
780 cur_oat_quick_method_header_ = nullptr;
781
782 if (cur_quick_frame_ != nullptr) {
// Handle quick stack frames.
783 // Can't be both a shadow and a quick fragment.
784 DCHECK(current_fragment->GetTopShadowFrame() == nullptr);
785 ArtMethod* method = *cur_quick_frame_;
786 DCHECK(method != nullptr);
787 bool header_retrieved = false;
788 if (method->IsNative()) {
789 //省略 native
822 }
823 while (method != nullptr) {
824
829 //省略
830 if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames)
831 && (cur_oat_quick_method_header_ != nullptr)
832 && cur_oat_quick_method_header_->IsOptimized()) {
833 CodeInfo code_info = cur_oat_quick_method_header_->GetOptimizedCodeInfo();
834 CodeInfoEncoding encoding = code_info.ExtractEncoding();
835 uint32_t native_pc_offset =
836 cur_oat_quick_method_header_->NativeQuickPcOffset(cur_quick_frame_pc_);
837 StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
838 if (stack_map.IsValid() && stack_map.HasInlineInfo(encoding.stack_map.encoding)) {
839 InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding);
840 DCHECK_EQ(current_inlining_depth_, 0u);
841 for (current_inlining_depth_ = inline_info.GetDepth(encoding.inline_info.encoding);
842 current_inlining_depth_ != 0;
843 --current_inlining_depth_) {
844 bool should_continue = VisitFrame();
845 if (UNLIKELY(!should_continue)) {
846 return;
847 }
848 cur_depth_++;
849 inlined_frames_count++;
850 }
851 }
852 }
853
//这块发现 我们在之前看到的在java_lang_class.cc isCallerTrust方法里调用的内容
854 bool should_continue = VisitFrame();
855 if (UNLIKELY(!should_continue)) {
856 return;
857 }
858
859 // 省略 大概猜是在遍历吧
926 method = *cur_quick_frame_;
927 }
928 } else if (cur_shadow_frame_ != nullptr) {
929 do {
930 SanityCheckFrame();
931 bool should_continue = VisitFrame();
932 if (UNLIKELY(!should_continue)) {
933 return;
934 }
935 cur_depth_++;
936 cur_shadow_frame_ = cur_shadow_frame_->GetLink();
937 } while (cur_shadow_frame_ != nullptr);
938 }
939 if (include_transitions) {
940 bool should_continue = VisitFrame();
941 if (!should_continue) {
942 return;
943 }
944 }
945 if (kCount == CountTransitions::kYes) {
946 cur_depth_++;
947 }
948 }
949 if (num_frames_ != 0) {
950 CHECK_EQ(cur_depth_, num_frames_);
951 }
952 }
After the above WalkStack, if VisitFrame returns false, it means that the caller of the current method has been found.
It can be seen from this that the visitor finds the called caller through traversal. Check the caller.
99 FirstExternalCallerVisitor visitor(self);
100 visitor.WalkStack();
101 return visitor.caller != nullptr &&
102 hiddenapi::IsCallerTrusted(visitor.caller->GetDeclaringClass());
Then let's look at the current calling relationship
It can be seen that the calling relationship has changed by reflecting the method getDeclareMethod of Method itself. Gain the trust of the caller of the ART inspection method.
legacy content
1. The method gap of Android 9, 10, 11
2. Guess the reason why Android 11 is not OK
3. Other bypass methods on Android 11