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

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

insert image description here

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

Guess you like

Origin blog.csdn.net/ziyunLLL/article/details/124871450