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