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.h"
     21 #include "art_method.h"
     22 #include "base/hiddenapi_flags.h"
     23 #include "base/locks.h"
     24 #include "intrinsics_enum.h"
     25 #include "mirror/class-inl.h"
     26 #include "reflection.h"
     27 #include "runtime.h"
     28 
     29 namespace art {
     30 namespace hiddenapi {
     31 
     32 // Hidden API enforcement policy
     33 // This must be kept in sync with ApplicationInfo.ApiEnforcementPolicy in
     34 // frameworks/base/core/java/android/content/pm/ApplicationInfo.java
     35 enum class EnforcementPolicy {
     36   kDisabled             = 0,
     37   kJustWarn             = 1,  // keep checks enabled, but allow everything (enables logging)
     38   kEnabled              = 2,  // ban dark grey & blacklist
     39   kMax = kEnabled,
     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 // Hidden API access method
     49 // Thist must be kept in sync with VMRuntime.HiddenApiUsageLogger.ACCESS_METHOD_*
     50 enum class AccessMethod {
     51   kNone = 0,  // internal test that does not correspond to an actual access by app
     52   kReflection = 1,
     53   kJNI = 2,
     54   kLinking = 3,
     55 };
     56 
     57 // Represents the API domain of a caller/callee.
     58 class AccessContext {
     59  public:
     60   // Initialize to either the fully-trusted or fully-untrusted domain.
     61   explicit AccessContext(bool is_trusted)
     62       : klass_(nullptr),
     63         dex_file_(nullptr),
     64         domain_(ComputeDomain(is_trusted)) {}
     65 
     66   // Initialize from class loader and dex file (via dex cache).
     67   AccessContext(ObjPtr<mirror::ClassLoader> class_loader, ObjPtr<mirror::DexCache> dex_cache)
     68       REQUIRES_SHARED(Locks::mutator_lock_)
     69       : klass_(nullptr),
     70         dex_file_(GetDexFileFromDexCache(dex_cache)),
     71         domain_(ComputeDomain(class_loader, dex_file_)) {}
     72 
     73   // Initialize from class loader and dex file (only used by tests).
     74   AccessContext(ObjPtr<mirror::ClassLoader> class_loader, const DexFile* dex_file)
     75       : klass_(nullptr),
     76         dex_file_(dex_file),
     77         domain_(ComputeDomain(class_loader, dex_file_)) {}
     78 
     79   // Initialize from Class.
     80   explicit AccessContext(ObjPtr<mirror::Class> klass)
     81       REQUIRES_SHARED(Locks::mutator_lock_)
     82       : klass_(klass),
     83         dex_file_(GetDexFileFromDexCache(klass->GetDexCache())),
     84         domain_(ComputeDomain(klass, dex_file_)) {}
     85 
     86   ObjPtr<mirror::Class> GetClass() const { return klass_; }
     87   const DexFile* GetDexFile() const { return dex_file_; }
     88   Domain GetDomain() const { return domain_; }
     89   bool IsApplicationDomain() const { return domain_ == Domain::kApplication; }
     90 
     91   // Returns true if this domain is always allowed to access the domain of `callee`.
     92   bool CanAlwaysAccess(const AccessContext& callee) const {
     93     return IsDomainMoreTrustedThan(domain_, callee.domain_);
     94   }
     95 
     96  private:
     97   static const DexFile* GetDexFileFromDexCache(ObjPtr<mirror::DexCache> dex_cache)
     98       REQUIRES_SHARED(Locks::mutator_lock_) {
     99     return dex_cache.IsNull() ? nullptr : dex_cache->GetDexFile();
    100   }
    101 
    102   static Domain ComputeDomain(bool is_trusted) {
    103     return is_trusted ? Domain::kCorePlatform : Domain::kApplication;
    104   }
    105 
    106   static Domain ComputeDomain(ObjPtr<mirror::ClassLoader> class_loader, const DexFile* dex_file) {
    107     if (dex_file == nullptr) {
    108       return ComputeDomain(/* is_trusted= */ class_loader.IsNull());
    109     }
    110 
    111     return dex_file->GetHiddenapiDomain();
    112   }
    113 
    114   static Domain ComputeDomain(ObjPtr<mirror::Class> klass, const DexFile* dex_file)
    115       REQUIRES_SHARED(Locks::mutator_lock_) {
    116     // Check other aspects of the context.
    117     Domain domain = ComputeDomain(klass->GetClassLoader(), dex_file);
    118 
    119     if (domain == Domain::kApplication &&
    120         klass->ShouldSkipHiddenApiChecks() &&
    121         Runtime::Current()->IsJavaDebuggable()) {
    122       // Class is known, it is marked trusted and we are in debuggable mode.
    123       domain = ComputeDomain(/* is_trusted= */ true);
    124     }
    125 
    126     return domain;
    127   }
    128 
    129   // Pointer to declaring class of the caller/callee (null if not provided).
    130   // This is not safe across GC but we're only using this class for passing
    131   // information about the caller to the access check logic and never retain
    132   // the AccessContext instance beyond that.
    133   const ObjPtr<mirror::Class> klass_;
    134 
    135   // DexFile of the caller/callee (null if not provided).
    136   const DexFile* const dex_file_;
    137 
    138   // Computed domain of the caller/callee.
    139   const Domain domain_;
    140 };
    141 
    142 class ScopedHiddenApiEnforcementPolicySetting {
    143  public:
    144   explicit ScopedHiddenApiEnforcementPolicySetting(EnforcementPolicy new_policy)
    145       : initial_policy_(Runtime::Current()->GetHiddenApiEnforcementPolicy()) {
    146     Runtime::Current()->SetHiddenApiEnforcementPolicy(new_policy);
    147   }
    148 
    149   ~ScopedHiddenApiEnforcementPolicySetting() {
    150     Runtime::Current()->SetHiddenApiEnforcementPolicy(initial_policy_);
    151   }
    152 
    153  private:
    154   const EnforcementPolicy initial_policy_;
    155   DISALLOW_COPY_AND_ASSIGN(ScopedHiddenApiEnforcementPolicySetting);
    156 };
    157 
    158 // Implementation details. DO NOT ACCESS DIRECTLY.
    159 namespace detail {
    160 
    161 // Class to encapsulate the signature of a member (ArtField or ArtMethod). This
    162 // is used as a helper when matching prefixes, and when logging the signature.
    163 class MemberSignature {
    164  private:
    165   enum MemberType {
    166     kField,
    167     kMethod,
    168   };
    169 
    170   std::string class_name_;
    171   std::string member_name_;
    172   std::string type_signature_;
    173   std::string tmp_;
    174   MemberType type_;
    175 
    176   inline std::vector<const char*> GetSignatureParts() const;
    177 
    178  public:
    179   explicit MemberSignature(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_);
    180   explicit MemberSignature(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
    181   explicit MemberSignature(const ClassAccessor::Field& field);
    182   explicit MemberSignature(const ClassAccessor::Method& method);
    183 
    184   void Dump(std::ostream& os) const;
    185 
    186   bool Equals(const MemberSignature& other);
    187   bool MemberNameAndTypeMatch(const MemberSignature& other);
    188 
    189   // Performs prefix match on this member. Since the full member signature is
    190   // composed of several parts, we match each part in turn (rather than
    191   // building the entire thing in memory and performing a simple prefix match)
    192   bool DoesPrefixMatch(const std::string& prefix) const;
    193 
    194   bool IsExempted(const std::vector<std::string>& exemptions);
    195 
    196   void WarnAboutAccess(AccessMethod access_method, ApiList list, bool access_denied);
    197 
    198   void LogAccessToEventLog(uint32_t sampled_value, AccessMethod access_method, bool access_denied);
    199 
    200   // Calls back into managed code to notify VMRuntime.nonSdkApiUsageConsumer that
    201   // |member| was accessed. This is usually called when an API is on the black,
    202   // dark grey or light grey lists. Given that the callback can execute arbitrary
    203   // code, a call to this method can result in thread suspension.
    204   void NotifyHiddenApiListener(AccessMethod access_method);
    205 };
    206 
    207 // Locates hiddenapi flags for `field` in the corresponding dex file.
    208 // NB: This is an O(N) operation, linear with the number of members in the class def.
    209 template<typename T>
    210 uint32_t GetDexFlags(T* member) REQUIRES_SHARED(Locks::mutator_lock_);
    211 
    212 // Handler of detected core platform API violations. Returns true if access to
    213 // `member` should be denied.
    214 template<typename T>
    215 bool HandleCorePlatformApiViolation(T* member,
    216                                     const AccessContext& caller_context,
    217                                     AccessMethod access_method,
    218                                     EnforcementPolicy policy)
    219     REQUIRES_SHARED(Locks::mutator_lock_);
    220 
    221 template<typename T>
    222 bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod access_method)
    223     REQUIRES_SHARED(Locks::mutator_lock_);
    224 
    225 inline ArtField* GetInterfaceMemberIfProxy(ArtField* field) { return field; }
    226 
    227 inline ArtMethod* GetInterfaceMemberIfProxy(ArtMethod* method)
    228     REQUIRES_SHARED(Locks::mutator_lock_) {
    229   return method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
    230 }
    231 
    232 // Returns access flags for the runtime representation of a class member (ArtField/ArtMember).
    233 ALWAYS_INLINE inline uint32_t CreateRuntimeFlags_Impl(uint32_t dex_flags) {
    234   uint32_t runtime_flags = 0u;
    235 
    236   ApiList api_list(dex_flags);
    237   DCHECK(api_list.IsValid());
    238 
    239   if (api_list.Contains(ApiList::Whitelist())) {
    240     runtime_flags |= kAccPublicApi;
    241   } else {
    242     // Only add domain-specific flags for non-public API members.
    243     // This simplifies hardcoded values for intrinsics.
    244     if (api_list.Contains(ApiList::CorePlatformApi())) {
    245       runtime_flags |= kAccCorePlatformApi;
    246     }
    247   }
    248 
    249   DCHECK_EQ(runtime_flags & kAccHiddenapiBits, runtime_flags)
    250       << "Runtime flags not in reserved access flags bits";
    251   return runtime_flags;
    252 }
    253 
    254 }  // namespace detail
    255 
    256 // Returns access flags for the runtime representation of a class member (ArtField/ArtMember).
    257 ALWAYS_INLINE inline uint32_t CreateRuntimeFlags(const ClassAccessor::BaseItem& member) {
    258   return detail::CreateRuntimeFlags_Impl(member.GetHiddenapiFlags());
    259 }
    260 
    261 // Returns access flags for the runtime representation of a class member (ArtField/ArtMember).
    262 template<typename T>
    263 ALWAYS_INLINE inline uint32_t CreateRuntimeFlags(T* member) REQUIRES_SHARED(Locks::mutator_lock_) {
    264   return detail::CreateRuntimeFlags_Impl(detail::GetDexFlags(member));
    265 }
    266 
    267 // Extracts hiddenapi runtime flags from access flags of ArtField.
    268 ALWAYS_INLINE inline uint32_t GetRuntimeFlags(ArtField* field)
    269     REQUIRES_SHARED(Locks::mutator_lock_) {
    270   return field->GetAccessFlags() & kAccHiddenapiBits;
    271 }
    272 
    273 // Extracts hiddenapi runtime flags from access flags of ArtMethod.
    274 // Uses hardcoded values for intrinsics.
    275 ALWAYS_INLINE inline uint32_t GetRuntimeFlags(ArtMethod* method)
    276     REQUIRES_SHARED(Locks::mutator_lock_) {
    277   if (UNLIKELY(method->IsIntrinsic())) {
    278     switch (static_cast<Intrinsics>(method->GetIntrinsic())) {
    279       case Intrinsics::kSystemArrayCopyChar:
    280       case Intrinsics::kStringGetCharsNoCheck:
    281       case Intrinsics::kReferenceGetReferent:
    282       case Intrinsics::kMemoryPeekByte:
    283       case Intrinsics::kMemoryPokeByte:
    284       case Intrinsics::kUnsafeCASInt:
    285       case Intrinsics::kUnsafeCASLong:
    286       case Intrinsics::kUnsafeCASObject:
    287       case Intrinsics::kUnsafeGet:
    288       case Intrinsics::kUnsafeGetAndAddInt:
    289       case Intrinsics::kUnsafeGetAndAddLong:
    290       case Intrinsics::kUnsafeGetAndSetInt:
    291       case Intrinsics::kUnsafeGetAndSetLong:
    292       case Intrinsics::kUnsafeGetAndSetObject:
    293       case Intrinsics::kUnsafeGetLongVolatile:
    294       case Intrinsics::kUnsafeGetObject:
    295       case Intrinsics::kUnsafeGetObjectVolatile:
    296       case Intrinsics::kUnsafeGetVolatile:
    297       case Intrinsics::kUnsafePut:
    298       case Intrinsics::kUnsafePutLong:
    299       case Intrinsics::kUnsafePutLongOrdered:
    300       case Intrinsics::kUnsafePutLongVolatile:
    301       case Intrinsics::kUnsafePutObject:
    302       case Intrinsics::kUnsafePutObjectOrdered:
    303       case Intrinsics::kUnsafePutObjectVolatile:
    304       case Intrinsics::kUnsafePutOrdered:
    305       case Intrinsics::kUnsafePutVolatile:
    306       case Intrinsics::kUnsafeLoadFence:
    307       case Intrinsics::kUnsafeStoreFence:
    308       case Intrinsics::kUnsafeFullFence:
    309       case Intrinsics::kCRC32Update:
    310       case Intrinsics::kCRC32UpdateBytes:
    311       case Intrinsics::kCRC32UpdateByteBuffer:
    312       case Intrinsics::kStringNewStringFromBytes:
    313       case Intrinsics::kStringNewStringFromChars:
    314       case Intrinsics::kStringNewStringFromString:
    315       case Intrinsics::kMemoryPeekIntNative:
    316       case Intrinsics::kMemoryPeekLongNative:
    317       case Intrinsics::kMemoryPeekShortNative:
    318       case Intrinsics::kMemoryPokeIntNative:
    319       case Intrinsics::kMemoryPokeLongNative:
    320       case Intrinsics::kMemoryPokeShortNative:
    321       case Intrinsics::kVarHandleFullFence:
    322       case Intrinsics::kVarHandleAcquireFence:
    323       case Intrinsics::kVarHandleReleaseFence:
    324       case Intrinsics::kVarHandleLoadLoadFence:
    325       case Intrinsics::kVarHandleStoreStoreFence:
    326       case Intrinsics::kVarHandleCompareAndExchange:
    327       case Intrinsics::kVarHandleCompareAndExchangeAcquire:
    328       case Intrinsics::kVarHandleCompareAndExchangeRelease:
    329       case Intrinsics::kVarHandleCompareAndSet:
    330       case Intrinsics::kVarHandleGet:
    331       case Intrinsics::kVarHandleGetAcquire:
    332       case Intrinsics::kVarHandleGetAndAdd:
    333       case Intrinsics::kVarHandleGetAndAddAcquire:
    334       case Intrinsics::kVarHandleGetAndAddRelease:
    335       case Intrinsics::kVarHandleGetAndBitwiseAnd:
    336       case Intrinsics::kVarHandleGetAndBitwiseAndAcquire:
    337       case Intrinsics::kVarHandleGetAndBitwiseAndRelease:
    338       case Intrinsics::kVarHandleGetAndBitwiseOr:
    339       case Intrinsics::kVarHandleGetAndBitwiseOrAcquire:
    340       case Intrinsics::kVarHandleGetAndBitwiseOrRelease:
    341       case Intrinsics::kVarHandleGetAndBitwiseXor:
    342       case Intrinsics::kVarHandleGetAndBitwiseXorAcquire:
    343       case Intrinsics::kVarHandleGetAndBitwiseXorRelease:
    344       case Intrinsics::kVarHandleGetAndSet:
    345       case Intrinsics::kVarHandleGetAndSetAcquire:
    346       case Intrinsics::kVarHandleGetAndSetRelease:
    347       case Intrinsics::kVarHandleGetOpaque:
    348       case Intrinsics::kVarHandleGetVolatile:
    349       case Intrinsics::kVarHandleSet:
    350       case Intrinsics::kVarHandleSetOpaque:
    351       case Intrinsics::kVarHandleSetRelease:
    352       case Intrinsics::kVarHandleSetVolatile:
    353       case Intrinsics::kVarHandleWeakCompareAndSet:
    354       case Intrinsics::kVarHandleWeakCompareAndSetAcquire:
    355       case Intrinsics::kVarHandleWeakCompareAndSetPlain:
    356       case Intrinsics::kVarHandleWeakCompareAndSetRelease:
    357         return 0u;
    358       case Intrinsics::kUnsafeGetLong:
    359         return kAccCorePlatformApi;
    360       default:
    361         // Remaining intrinsics are public API. We DCHECK that in SetIntrinsic().
    362         return kAccPublicApi;
    363     }
    364   } else {
    365     return method->GetAccessFlags() & kAccHiddenapiBits;
    366   }
    367 }
    368 
    369 // Called by class linker when a new dex file has been registered. Assigns
    370 // the AccessContext domain to the newly-registered dex file based on its
    371 // location and class loader.
    372 void InitializeDexFileDomain(const DexFile& dex_file, ObjPtr<mirror::ClassLoader> class_loader);
    373 
    374 // Returns true if access to `member` should be denied in the given context.
    375 // The decision is based on whether the caller is in a trusted context or not.
    376 // Because determining the access context can be expensive, a lambda function
    377 // "fn_get_access_context" is lazily invoked after other criteria have been
    378 // considered.
    379 // This function might print warnings into the log if the member is hidden.
    380 template<typename T>
    381 inline bool ShouldDenyAccessToMember(T* member,
    382                                      const std::function<AccessContext()>& fn_get_access_context,
    383                                      AccessMethod access_method)
    384     REQUIRES_SHARED(Locks::mutator_lock_) {
    385   DCHECK(member != nullptr);
    386 
    387   // Get the runtime flags encoded in member's access flags.
    388   // Note: this works for proxy methods because they inherit access flags from their
    389   // respective interface methods.
    390   const uint32_t runtime_flags = GetRuntimeFlags(member);
    391 
    392   // Exit early if member is public API. This flag is also set for non-boot class
    393   // path fields/methods.
    394   if ((runtime_flags & kAccPublicApi) != 0) {
    395     return false;
    396   }
    397 
    398   // Determine which domain the caller and callee belong to.
    399   // This can be *very* expensive. This is why ShouldDenyAccessToMember
    400   // should not be called on every individual access.
    401   const AccessContext caller_context = fn_get_access_context();
    402   const AccessContext callee_context(member->GetDeclaringClass());
    403 
    404   // Non-boot classpath callers should have exited early.
    405   DCHECK(!callee_context.IsApplicationDomain());
    406 
    407   // Check if the caller is always allowed to access members in the callee context.
    408   if (caller_context.CanAlwaysAccess(callee_context)) {
    409     return false;
    410   }
    411 
    412   // Check if this is platform accessing core platform. We may warn if `member` is
    413   // not part of core platform API.
    414   switch (caller_context.GetDomain()) {
    415     case Domain::kApplication: {
    416       DCHECK(!callee_context.IsApplicationDomain());
    417 
    418       // Exit early if access checks are completely disabled.
    419       EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
    420       if (policy == EnforcementPolicy::kDisabled) {
    421         return false;
    422       }
    423 
    424       // If this is a proxy method, look at the interface method instead.
    425       member = detail::GetInterfaceMemberIfProxy(member);
    426 
    427       // Decode hidden API access flags from the dex file.
    428       // This is an O(N) operation scaling with the number of fields/methods
    429       // in the class. Only do this on slow path and only do it once.
    430       ApiList api_list(detail::GetDexFlags(member));
    431       DCHECK(api_list.IsValid());
    432 
    433       // Member is hidden and caller is not exempted. Enter slow path.
    434       return detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
    435     }
    436 
    437     case Domain::kPlatform: {
    438       DCHECK(callee_context.GetDomain() == Domain::kCorePlatform);
    439 
    440       // Member is part of core platform API. Accessing it is allowed.
    441       if ((runtime_flags & kAccCorePlatformApi) != 0) {
    442         return false;
    443       }
    444 
    445       // Allow access if access checks are disabled.
    446       EnforcementPolicy policy = Runtime::Current()->GetCorePlatformApiEnforcementPolicy();
    447       if (policy == EnforcementPolicy::kDisabled) {
    448         return false;
    449       }
    450 
    451       // If this is a proxy method, look at the interface method instead.
    452       member = detail::GetInterfaceMemberIfProxy(member);
    453 
    454       // Access checks are not disabled, report the violation.
    455       // This may also add kAccCorePlatformApi to the access flags of `member`
    456       // so as to not warn again on next access.
    457       return detail::HandleCorePlatformApiViolation(member,
    458                                                     caller_context,
    459                                                     access_method,
    460                                                     policy);
    461     }
    462 
    463     case Domain::kCorePlatform: {
    464       LOG(FATAL) << "CorePlatform domain should be allowed to access all domains";
    465       UNREACHABLE();
    466     }
    467   }
    468 }
    469 
    470 // Helper method for callers where access context can be determined beforehand.
    471 // Wraps AccessContext in a lambda and passes it to the real ShouldDenyAccessToMember.
    472 template<typename T>
    473 inline bool ShouldDenyAccessToMember(T* member,
    474                                      const AccessContext& access_context,
    475                                      AccessMethod access_method)
    476     REQUIRES_SHARED(Locks::mutator_lock_) {
    477   return ShouldDenyAccessToMember(member, [&]() { return access_context; }, access_method);
    478 }
    479 
    480 }  // namespace hiddenapi
    481 }  // namespace art
    482 
    483 #endif  // ART_RUNTIME_HIDDEN_API_H_
    484