• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EnforcementPolicyFromInt(int api_policy_int)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.
AccessContext(bool is_trusted)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).
AccessContext(ObjPtr<mirror::ClassLoader> class_loader,ObjPtr<mirror::DexCache> 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).
AccessContext(ObjPtr<mirror::ClassLoader> class_loader,const DexFile * dex_file)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.
AccessContext(ObjPtr<mirror::Class> klass)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 
GetClass()86   ObjPtr<mirror::Class> GetClass() const { return klass_; }
GetDexFile()87   const DexFile* GetDexFile() const { return dex_file_; }
GetDomain()88   Domain GetDomain() const { return domain_; }
IsApplicationDomain()89   bool IsApplicationDomain() const { return domain_ == Domain::kApplication; }
90 
91   // Returns true if this domain is always allowed to access the domain of `callee`.
CanAlwaysAccess(const AccessContext & callee)92   bool CanAlwaysAccess(const AccessContext& callee) const {
93     return IsDomainMoreTrustedThan(domain_, callee.domain_);
94   }
95 
96  private:
GetDexFileFromDexCache(ObjPtr<mirror::DexCache> dex_cache)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 
ComputeDomain(bool is_trusted)102   static Domain ComputeDomain(bool is_trusted) {
103     return is_trusted ? Domain::kCorePlatform : Domain::kApplication;
104   }
105 
ComputeDomain(ObjPtr<mirror::ClassLoader> class_loader,const DexFile * dex_file)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 
ComputeDomain(ObjPtr<mirror::Class> klass,const DexFile * dex_file)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:
ScopedHiddenApiEnforcementPolicySetting(EnforcementPolicy new_policy)144   explicit ScopedHiddenApiEnforcementPolicySetting(EnforcementPolicy new_policy)
145       : initial_policy_(Runtime::Current()->GetHiddenApiEnforcementPolicy()) {
146     Runtime::Current()->SetHiddenApiEnforcementPolicy(new_policy);
147   }
148 
~ScopedHiddenApiEnforcementPolicySetting()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 
GetInterfaceMemberIfProxy(ArtField * field)225 inline ArtField* GetInterfaceMemberIfProxy(ArtField* field) { return field; }
226 
GetInterfaceMemberIfProxy(ArtMethod * method)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).
CreateRuntimeFlags_Impl(uint32_t dex_flags)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).
CreateRuntimeFlags(const ClassAccessor::BaseItem & member)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>
CreateRuntimeFlags(T * member)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.
GetRuntimeFlags(ArtField * field)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.
GetRuntimeFlags(ArtMethod * method)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>
ShouldDenyAccessToMember(T * member,const std::function<AccessContext ()> & fn_get_access_context,AccessMethod access_method)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>
ShouldDenyAccessToMember(T * member,const AccessContext & access_context,AccessMethod access_method)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