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