Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2018 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 #ifndef ART_RUNTIME_HIDDEN_API_H_
     18 #define ART_RUNTIME_HIDDEN_API_H_
     19 
     20 #include "art_field-inl.h"
     21 #include "art_method-inl.h"
     22 #include "base/mutex.h"
     23 #include "dex/hidden_api_access_flags.h"
     24 #include "mirror/class-inl.h"
     25 #include "reflection.h"
     26 #include "runtime.h"
     27 
     28 namespace art {
     29 namespace hiddenapi {
     30 
     31 // Hidden API enforcement policy
     32 // This must be kept in sync with ApplicationInfo.ApiEnforcementPolicy in
     33 // frameworks/base/core/java/android/content/pm/ApplicationInfo.java
     34 enum class EnforcementPolicy {
     35   kNoChecks             = 0,
     36   kJustWarn             = 1,  // keep checks enabled, but allow everything (enables logging)
     37   kDarkGreyAndBlackList = 2,  // ban dark grey & blacklist
     38   kBlacklistOnly        = 3,  // ban blacklist violations only
     39   kMax = kBlacklistOnly,
     40 };
     41 
     42 inline EnforcementPolicy EnforcementPolicyFromInt(int api_policy_int) {
     43   DCHECK_GE(api_policy_int, 0);
     44   DCHECK_LE(api_policy_int, static_cast<int>(EnforcementPolicy::kMax));
     45   return static_cast<EnforcementPolicy>(api_policy_int);
     46 }
     47 
     48 enum Action {
     49   kAllow,
     50   kAllowButWarn,
     51   kAllowButWarnAndToast,
     52   kDeny
     53 };
     54 
     55 enum AccessMethod {
     56   kNone,  // internal test that does not correspond to an actual access by app
     57   kReflection,
     58   kJNI,
     59   kLinking,
     60 };
     61 
     62 // Do not change the values of items in this enum, as they are written to the
     63 // event log for offline analysis. Any changes will interfere with that analysis.
     64 enum AccessContextFlags {
     65   // Accessed member is a field if this bit is set, else a method
     66   kMemberIsField = 1 << 0,
     67   // Indicates if access was denied to the member, instead of just printing a warning.
     68   kAccessDenied  = 1 << 1,
     69 };
     70 
     71 inline Action GetActionFromAccessFlags(HiddenApiAccessFlags::ApiList api_list) {
     72   if (api_list == HiddenApiAccessFlags::kWhitelist) {
     73     return kAllow;
     74   }
     75 
     76   EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
     77   if (policy == EnforcementPolicy::kNoChecks) {
     78     // Exit early. Nothing to enforce.
     79     return kAllow;
     80   }
     81 
     82   // if policy is "just warn", always warn. We returned above for whitelist APIs.
     83   if (policy == EnforcementPolicy::kJustWarn) {
     84     return kAllowButWarn;
     85   }
     86   DCHECK(policy >= EnforcementPolicy::kDarkGreyAndBlackList);
     87   // The logic below relies on equality of values in the enums EnforcementPolicy and
     88   // HiddenApiAccessFlags::ApiList, and their ordering. Assertions are in hidden_api.cc.
     89   if (static_cast<int>(policy) > static_cast<int>(api_list)) {
     90     return api_list == HiddenApiAccessFlags::kDarkGreylist
     91         ? kAllowButWarnAndToast
     92         : kAllowButWarn;
     93   } else {
     94     return kDeny;
     95   }
     96 }
     97 
     98 class ScopedHiddenApiEnforcementPolicySetting {
     99  public:
    100   explicit ScopedHiddenApiEnforcementPolicySetting(EnforcementPolicy new_policy)
    101       : initial_policy_(Runtime::Current()->GetHiddenApiEnforcementPolicy()) {
    102     Runtime::Current()->SetHiddenApiEnforcementPolicy(new_policy);
    103   }
    104 
    105   ~ScopedHiddenApiEnforcementPolicySetting() {
    106     Runtime::Current()->SetHiddenApiEnforcementPolicy(initial_policy_);
    107   }
    108 
    109  private:
    110   const EnforcementPolicy initial_policy_;
    111   DISALLOW_COPY_AND_ASSIGN(ScopedHiddenApiEnforcementPolicySetting);
    112 };
    113 
    114 // Implementation details. DO NOT ACCESS DIRECTLY.
    115 namespace detail {
    116 
    117 // Class to encapsulate the signature of a member (ArtField or ArtMethod). This
    118 // is used as a helper when matching prefixes, and when logging the signature.
    119 class MemberSignature {
    120  private:
    121   enum MemberType {
    122     kField,
    123     kMethod,
    124   };
    125 
    126   std::string class_name_;
    127   std::string member_name_;
    128   std::string type_signature_;
    129   std::string tmp_;
    130   MemberType type_;
    131 
    132   inline std::vector<const char*> GetSignatureParts() const;
    133 
    134  public:
    135   explicit MemberSignature(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_);
    136   explicit MemberSignature(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
    137 
    138   void Dump(std::ostream& os) const;
    139 
    140   // Performs prefix match on this member. Since the full member signature is
    141   // composed of several parts, we match each part in turn (rather than
    142   // building the entire thing in memory and performing a simple prefix match)
    143   bool DoesPrefixMatch(const std::string& prefix) const;
    144 
    145   bool IsExempted(const std::vector<std::string>& exemptions);
    146 
    147   void WarnAboutAccess(AccessMethod access_method, HiddenApiAccessFlags::ApiList list);
    148 
    149   void LogAccessToEventLog(AccessMethod access_method, Action action_taken);
    150 };
    151 
    152 template<typename T>
    153 Action GetMemberActionImpl(T* member,
    154                            HiddenApiAccessFlags::ApiList api_list,
    155                            Action action,
    156                            AccessMethod access_method)
    157     REQUIRES_SHARED(Locks::mutator_lock_);
    158 
    159 // Returns true if the caller is either loaded by the boot strap class loader or comes from
    160 // a dex file located in ${ANDROID_ROOT}/framework/.
    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 }
    188 
    189 }  // namespace detail
    190 
    191 // Returns true if access to `member` should be denied to the caller of the
    192 // reflective query. The decision is based on whether the caller is trusted or
    193 // not. Because different users of this function determine this in a different
    194 // way, `fn_caller_is_trusted(self)` is called and should return true if the
    195 // caller is allowed to access the platform.
    196 // This function might print warnings into the log if the member is hidden.
    197 template<typename T>
    198 inline Action GetMemberAction(T* member,
    199                               Thread* self,
    200                               std::function<bool(Thread*)> fn_caller_is_trusted,
    201                               AccessMethod access_method)
    202     REQUIRES_SHARED(Locks::mutator_lock_) {
    203   DCHECK(member != nullptr);
    204 
    205   // Decode hidden API access flags.
    206   // NB Multiple threads might try to access (and overwrite) these simultaneously,
    207   // causing a race. We only do that if access has not been denied, so the race
    208   // cannot change Java semantics. We should, however, decode the access flags
    209   // once and use it throughout this function, otherwise we may get inconsistent
    210   // results, e.g. print whitelist warnings (b/78327881).
    211   HiddenApiAccessFlags::ApiList api_list = member->GetHiddenApiAccessFlags();
    212 
    213   Action action = GetActionFromAccessFlags(member->GetHiddenApiAccessFlags());
    214   if (action == kAllow) {
    215     // Nothing to do.
    216     return action;
    217   }
    218 
    219   // Member is hidden. Invoke `fn_caller_in_platform` and find the origin of the access.
    220   // This can be *very* expensive. Save it for last.
    221   if (fn_caller_is_trusted(self)) {
    222     // Caller is trusted. Exit.
    223     return kAllow;
    224   }
    225 
    226   // Member is hidden and caller is not in the platform.
    227   return detail::GetMemberActionImpl(member, api_list, action, access_method);
    228 }
    229 
    230 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 }
    234 
    235 // Returns true if access to `member` should be denied to a caller loaded with
    236 // `caller_class_loader`.
    237 // This function might print warnings into the log if the member is hidden.
    238 template<typename T>
    239 inline Action GetMemberAction(T* member,
    240                               ObjPtr<mirror::ClassLoader> caller_class_loader,
    241                               ObjPtr<mirror::DexCache> caller_dex_cache,
    242                               AccessMethod access_method)
    243     REQUIRES_SHARED(Locks::mutator_lock_) {
    244   bool is_caller_trusted =
    245       detail::IsCallerTrusted(/* caller */ nullptr, caller_class_loader, caller_dex_cache);
    246   return GetMemberAction(member,
    247                          /* thread */ nullptr,
    248                          [is_caller_trusted] (Thread*) { return is_caller_trusted; },
    249                          access_method);
    250 }
    251 
    252 // Calls back into managed code to notify VMRuntime.nonSdkApiUsageConsumer that
    253 // |member| was accessed. This is usually called when an API is on the black,
    254 // dark grey or light grey lists. Given that the callback can execute arbitrary
    255 // code, a call to this method can result in thread suspension.
    256 template<typename T> void NotifyHiddenApiListener(T* member)
    257     REQUIRES_SHARED(Locks::mutator_lock_);
    258 
    259 
    260 }  // namespace hiddenapi
    261 }  // namespace art
    262 
    263 #endif  // ART_RUNTIME_HIDDEN_API_H_
    264