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 conditionally blocked & blocklist
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 unsupported,
207 // conditionally or unconditionally blocked. 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::Sdk())) {
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::kReferenceRefersTo:
288 case Intrinsics::kMemoryPeekByte:
289 case Intrinsics::kMemoryPokeByte:
290 case Intrinsics::kCRC32Update:
291 case Intrinsics::kCRC32UpdateBytes:
292 case Intrinsics::kCRC32UpdateByteBuffer:
293 case Intrinsics::kStringNewStringFromBytes:
294 case Intrinsics::kStringNewStringFromChars:
295 case Intrinsics::kStringNewStringFromString:
296 case Intrinsics::kMemoryPeekIntNative:
297 case Intrinsics::kMemoryPeekLongNative:
298 case Intrinsics::kMemoryPeekShortNative:
299 case Intrinsics::kMemoryPokeIntNative:
300 case Intrinsics::kMemoryPokeLongNative:
301 case Intrinsics::kMemoryPokeShortNative:
302 case Intrinsics::kUnsafeCASInt:
303 case Intrinsics::kUnsafeCASLong:
304 case Intrinsics::kUnsafeCASObject:
305 case Intrinsics::kUnsafeGetAndAddInt:
306 case Intrinsics::kUnsafeGetAndAddLong:
307 case Intrinsics::kUnsafeGetAndSetInt:
308 case Intrinsics::kUnsafeGetAndSetLong:
309 case Intrinsics::kUnsafeGetAndSetObject:
310 case Intrinsics::kUnsafeGetLongVolatile:
311 case Intrinsics::kUnsafeGetObjectVolatile:
312 case Intrinsics::kUnsafeGetVolatile:
313 case Intrinsics::kUnsafePutLongOrdered:
314 case Intrinsics::kUnsafePutLongVolatile:
315 case Intrinsics::kUnsafePutObjectOrdered:
316 case Intrinsics::kUnsafePutObjectVolatile:
317 case Intrinsics::kUnsafePutOrdered:
318 case Intrinsics::kUnsafePutVolatile:
319 case Intrinsics::kUnsafeLoadFence:
320 case Intrinsics::kUnsafeStoreFence:
321 case Intrinsics::kUnsafeFullFence:
322 case Intrinsics::kVarHandleFullFence:
323 case Intrinsics::kVarHandleAcquireFence:
324 case Intrinsics::kVarHandleReleaseFence:
325 case Intrinsics::kVarHandleLoadLoadFence:
326 case Intrinsics::kVarHandleStoreStoreFence:
327 case Intrinsics::kVarHandleCompareAndExchange:
328 case Intrinsics::kVarHandleCompareAndExchangeAcquire:
329 case Intrinsics::kVarHandleCompareAndExchangeRelease:
330 case Intrinsics::kVarHandleCompareAndSet:
331 case Intrinsics::kVarHandleGet:
332 case Intrinsics::kVarHandleGetAcquire:
333 case Intrinsics::kVarHandleGetAndAdd:
334 case Intrinsics::kVarHandleGetAndAddAcquire:
335 case Intrinsics::kVarHandleGetAndAddRelease:
336 case Intrinsics::kVarHandleGetAndBitwiseAnd:
337 case Intrinsics::kVarHandleGetAndBitwiseAndAcquire:
338 case Intrinsics::kVarHandleGetAndBitwiseAndRelease:
339 case Intrinsics::kVarHandleGetAndBitwiseOr:
340 case Intrinsics::kVarHandleGetAndBitwiseOrAcquire:
341 case Intrinsics::kVarHandleGetAndBitwiseOrRelease:
342 case Intrinsics::kVarHandleGetAndBitwiseXor:
343 case Intrinsics::kVarHandleGetAndBitwiseXorAcquire:
344 case Intrinsics::kVarHandleGetAndBitwiseXorRelease:
345 case Intrinsics::kVarHandleGetAndSet:
346 case Intrinsics::kVarHandleGetAndSetAcquire:
347 case Intrinsics::kVarHandleGetAndSetRelease:
348 case Intrinsics::kVarHandleGetOpaque:
349 case Intrinsics::kVarHandleGetVolatile:
350 case Intrinsics::kVarHandleSet:
351 case Intrinsics::kVarHandleSetOpaque:
352 case Intrinsics::kVarHandleSetRelease:
353 case Intrinsics::kVarHandleSetVolatile:
354 case Intrinsics::kVarHandleWeakCompareAndSet:
355 case Intrinsics::kVarHandleWeakCompareAndSetAcquire:
356 case Intrinsics::kVarHandleWeakCompareAndSetPlain:
357 case Intrinsics::kVarHandleWeakCompareAndSetRelease:
358 return 0u;
359 case Intrinsics::kFP16Ceil:
360 case Intrinsics::kFP16Floor:
361 case Intrinsics::kFP16Greater:
362 case Intrinsics::kFP16GreaterEquals:
363 case Intrinsics::kFP16Less:
364 case Intrinsics::kFP16LessEquals:
365 case Intrinsics::kFP16ToFloat:
366 case Intrinsics::kFP16ToHalf:
367 case Intrinsics::kFP16Rint:
368 case Intrinsics::kUnsafeGet:
369 case Intrinsics::kUnsafeGetLong:
370 case Intrinsics::kUnsafeGetObject:
371 case Intrinsics::kUnsafePutLong:
372 case Intrinsics::kUnsafePut:
373 case Intrinsics::kUnsafePutObject:
374 return kAccCorePlatformApi;
375 default:
376 // Remaining intrinsics are public API. We DCHECK that in SetIntrinsic().
377 return kAccPublicApi;
378 }
379 } else {
380 return method->GetAccessFlags() & kAccHiddenapiBits;
381 }
382 }
383
384 // Called by class linker when a new dex file has been registered. Assigns
385 // the AccessContext domain to the newly-registered dex file based on its
386 // location and class loader.
387 void InitializeDexFileDomain(const DexFile& dex_file, ObjPtr<mirror::ClassLoader> class_loader);
388
389 // Returns true if access to `member` should be denied in the given context.
390 // The decision is based on whether the caller is in a trusted context or not.
391 // Because determining the access context can be expensive, a lambda function
392 // "fn_get_access_context" is lazily invoked after other criteria have been
393 // considered.
394 // This function might print warnings into the log if the member is hidden.
395 template<typename T>
ShouldDenyAccessToMember(T * member,const std::function<AccessContext ()> & fn_get_access_context,AccessMethod access_method)396 inline bool ShouldDenyAccessToMember(T* member,
397 const std::function<AccessContext()>& fn_get_access_context,
398 AccessMethod access_method)
399 REQUIRES_SHARED(Locks::mutator_lock_) {
400 DCHECK(member != nullptr);
401
402 // First check if we have an explicit sdk checker installed that should be used to
403 // verify access. If so, make the decision based on it.
404 //
405 // This is used during off-device AOT compilation which may want to generate verification
406 // metadata only for a specific list of public SDKs. Note that the check here is made
407 // based on descriptor equality and it's aim to further restrict a symbol that would
408 // otherwise be resolved.
409 //
410 // The check only applies to boot classpaths dex files.
411 Runtime* runtime = Runtime::Current();
412 if (UNLIKELY(runtime->IsAotCompiler())) {
413 if (member->GetDeclaringClass()->GetClassLoader() == nullptr &&
414 runtime->GetClassLinker()->DenyAccessBasedOnPublicSdk(member)) {
415 return true;
416 }
417 }
418
419 // Get the runtime flags encoded in member's access flags.
420 // Note: this works for proxy methods because they inherit access flags from their
421 // respective interface methods.
422 const uint32_t runtime_flags = GetRuntimeFlags(member);
423
424 // Exit early if member is public API. This flag is also set for non-boot class
425 // path fields/methods.
426 if ((runtime_flags & kAccPublicApi) != 0) {
427 return false;
428 }
429
430 // Determine which domain the caller and callee belong to.
431 // This can be *very* expensive. This is why ShouldDenyAccessToMember
432 // should not be called on every individual access.
433 const AccessContext caller_context = fn_get_access_context();
434 const AccessContext callee_context(member->GetDeclaringClass());
435
436 // Non-boot classpath callers should have exited early.
437 DCHECK(!callee_context.IsApplicationDomain());
438
439 // Check if the caller is always allowed to access members in the callee context.
440 if (caller_context.CanAlwaysAccess(callee_context)) {
441 return false;
442 }
443
444 // Check if this is platform accessing core platform. We may warn if `member` is
445 // not part of core platform API.
446 switch (caller_context.GetDomain()) {
447 case Domain::kApplication: {
448 DCHECK(!callee_context.IsApplicationDomain());
449
450 // Exit early if access checks are completely disabled.
451 EnforcementPolicy policy = runtime->GetHiddenApiEnforcementPolicy();
452 if (policy == EnforcementPolicy::kDisabled) {
453 return false;
454 }
455
456 // If this is a proxy method, look at the interface method instead.
457 member = detail::GetInterfaceMemberIfProxy(member);
458
459 // Decode hidden API access flags from the dex file.
460 // This is an O(N) operation scaling with the number of fields/methods
461 // in the class. Only do this on slow path and only do it once.
462 ApiList api_list(detail::GetDexFlags(member));
463 DCHECK(api_list.IsValid());
464
465 // Member is hidden and caller is not exempted. Enter slow path.
466 return detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
467 }
468
469 case Domain::kPlatform: {
470 DCHECK(callee_context.GetDomain() == Domain::kCorePlatform);
471
472 // Member is part of core platform API. Accessing it is allowed.
473 if ((runtime_flags & kAccCorePlatformApi) != 0) {
474 return false;
475 }
476
477 // Allow access if access checks are disabled.
478 EnforcementPolicy policy = Runtime::Current()->GetCorePlatformApiEnforcementPolicy();
479 if (policy == EnforcementPolicy::kDisabled) {
480 return false;
481 }
482
483 // If this is a proxy method, look at the interface method instead.
484 member = detail::GetInterfaceMemberIfProxy(member);
485
486 // Access checks are not disabled, report the violation.
487 // This may also add kAccCorePlatformApi to the access flags of `member`
488 // so as to not warn again on next access.
489 return detail::HandleCorePlatformApiViolation(member,
490 caller_context,
491 access_method,
492 policy);
493 }
494
495 case Domain::kCorePlatform: {
496 LOG(FATAL) << "CorePlatform domain should be allowed to access all domains";
497 UNREACHABLE();
498 }
499 }
500 }
501
502 // Helper method for callers where access context can be determined beforehand.
503 // Wraps AccessContext in a lambda and passes it to the real ShouldDenyAccessToMember.
504 template<typename T>
ShouldDenyAccessToMember(T * member,const AccessContext & access_context,AccessMethod access_method)505 inline bool ShouldDenyAccessToMember(T* member,
506 const AccessContext& access_context,
507 AccessMethod access_method)
508 REQUIRES_SHARED(Locks::mutator_lock_) {
509 return ShouldDenyAccessToMember(member, [&]() { return access_context; }, access_method);
510 }
511
512 } // namespace hiddenapi
513 } // namespace art
514
515 #endif // ART_RUNTIME_HIDDEN_API_H_
516