• 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_domain.h"
23 #include "base/hiddenapi_flags.h"
24 #include "base/locks.h"
25 #include "dex/class_accessor.h"
26 #include "intrinsics_enum.h"
27 #include "jni/jni_internal.h"
28 #include "mirror/class.h"
29 #include "mirror/class_loader.h"
30 #include "reflection.h"
31 #include "runtime.h"
32 
33 namespace art {
34 namespace hiddenapi {
35 
36 // Hidden API enforcement policy
37 // This must be kept in sync with ApplicationInfo.ApiEnforcementPolicy in
38 // frameworks/base/core/java/android/content/pm/ApplicationInfo.java
39 enum class EnforcementPolicy {
40   kDisabled             = 0,
41   kJustWarn             = 1,  // keep checks enabled, but allow everything (enables logging)
42   kEnabled              = 2,  // ban conditionally blocked & blocklist
43   kMax = kEnabled,
44 };
45 
EnforcementPolicyFromInt(int api_policy_int)46 inline EnforcementPolicy EnforcementPolicyFromInt(int api_policy_int) {
47   DCHECK_GE(api_policy_int, 0);
48   DCHECK_LE(api_policy_int, static_cast<int>(EnforcementPolicy::kMax));
49   return static_cast<EnforcementPolicy>(api_policy_int);
50 }
51 
52 // Hidden API access method
53 // Thist must be kept in sync with VMRuntime.HiddenApiUsageLogger.ACCESS_METHOD_*
54 enum class AccessMethod {
55   kNone = 0,  // internal test that does not correspond to an actual access by app
56   kReflection = 1,
57   kJNI = 2,
58   kLinking = 3,
59 };
60 
61 // Represents the API domain of a caller/callee.
62 class AccessContext {
63  public:
64   // Initialize to either the fully-trusted or fully-untrusted domain.
AccessContext(bool is_trusted)65   explicit AccessContext(bool is_trusted)
66       : klass_(nullptr),
67         dex_file_(nullptr),
68         domain_(ComputeDomain(is_trusted)) {}
69 
70   // Initialize from class loader and dex file (via dex cache).
AccessContext(ObjPtr<mirror::ClassLoader> class_loader,ObjPtr<mirror::DexCache> dex_cache)71   AccessContext(ObjPtr<mirror::ClassLoader> class_loader, ObjPtr<mirror::DexCache> dex_cache)
72       REQUIRES_SHARED(Locks::mutator_lock_)
73       : klass_(nullptr),
74         dex_file_(GetDexFileFromDexCache(dex_cache)),
75         domain_(ComputeDomain(class_loader, dex_file_)) {}
76 
77   // Initialize from class loader and dex file (only used by tests).
AccessContext(ObjPtr<mirror::ClassLoader> class_loader,const DexFile * dex_file)78   AccessContext(ObjPtr<mirror::ClassLoader> class_loader, const DexFile* dex_file)
79       : klass_(nullptr),
80         dex_file_(dex_file),
81         domain_(ComputeDomain(class_loader, dex_file_)) {}
82 
83   // Initialize from Class.
AccessContext(ObjPtr<mirror::Class> klass)84   explicit AccessContext(ObjPtr<mirror::Class> klass)
85       REQUIRES_SHARED(Locks::mutator_lock_)
86       : klass_(klass),
87         dex_file_(GetDexFileFromDexCache(klass->GetDexCache())),
88         domain_(ComputeDomain(klass, dex_file_)) {}
89 
GetClass()90   ObjPtr<mirror::Class> GetClass() const { return klass_; }
GetDexFile()91   const DexFile* GetDexFile() const { return dex_file_; }
GetDomain()92   Domain GetDomain() const { return domain_; }
IsApplicationDomain()93   bool IsApplicationDomain() const { return domain_ == Domain::kApplication; }
94 
95   // Returns true if this domain is always allowed to access the domain of `callee`.
CanAlwaysAccess(const AccessContext & callee)96   bool CanAlwaysAccess(const AccessContext& callee) const {
97     return IsDomainMoreTrustedThan(domain_, callee.domain_);
98   }
99 
100  private:
GetDexFileFromDexCache(ObjPtr<mirror::DexCache> dex_cache)101   static const DexFile* GetDexFileFromDexCache(ObjPtr<mirror::DexCache> dex_cache)
102       REQUIRES_SHARED(Locks::mutator_lock_) {
103     return dex_cache.IsNull() ? nullptr : dex_cache->GetDexFile();
104   }
105 
ComputeDomain(bool is_trusted)106   static Domain ComputeDomain(bool is_trusted) {
107     return is_trusted ? Domain::kCorePlatform : Domain::kApplication;
108   }
109 
ComputeDomain(ObjPtr<mirror::ClassLoader> class_loader,const DexFile * dex_file)110   static Domain ComputeDomain(ObjPtr<mirror::ClassLoader> class_loader, const DexFile* dex_file) {
111     if (dex_file == nullptr) {
112       return ComputeDomain(/* is_trusted= */ class_loader.IsNull());
113     }
114 
115     return dex_file->GetHiddenapiDomain();
116   }
117 
ComputeDomain(ObjPtr<mirror::Class> klass,const DexFile * dex_file)118   static Domain ComputeDomain(ObjPtr<mirror::Class> klass, const DexFile* dex_file)
119       REQUIRES_SHARED(Locks::mutator_lock_) {
120     // Check other aspects of the context.
121     Domain domain = ComputeDomain(klass->GetClassLoader(), dex_file);
122 
123     if (domain == Domain::kApplication &&
124         klass->ShouldSkipHiddenApiChecks() &&
125         Runtime::Current()->IsJavaDebuggableAtInit()) {
126       // Class is known, it is marked trusted and we are in debuggable mode.
127       domain = ComputeDomain(/* is_trusted= */ true);
128     }
129 
130     return domain;
131   }
132 
133   // Pointer to declaring class of the caller/callee (null if not provided).
134   // This is not safe across GC but we're only using this class for passing
135   // information about the caller to the access check logic and never retain
136   // the AccessContext instance beyond that.
137   const ObjPtr<mirror::Class> klass_;
138 
139   // DexFile of the caller/callee (null if not provided).
140   const DexFile* const dex_file_;
141 
142   // Computed domain of the caller/callee.
143   const Domain domain_;
144 };
145 
146 class ScopedHiddenApiEnforcementPolicySetting {
147  public:
ScopedHiddenApiEnforcementPolicySetting(EnforcementPolicy new_policy)148   explicit ScopedHiddenApiEnforcementPolicySetting(EnforcementPolicy new_policy)
149       : initial_policy_(Runtime::Current()->GetHiddenApiEnforcementPolicy()) {
150     Runtime::Current()->SetHiddenApiEnforcementPolicy(new_policy);
151   }
152 
~ScopedHiddenApiEnforcementPolicySetting()153   ~ScopedHiddenApiEnforcementPolicySetting() {
154     Runtime::Current()->SetHiddenApiEnforcementPolicy(initial_policy_);
155   }
156 
157  private:
158   const EnforcementPolicy initial_policy_;
159   DISALLOW_COPY_AND_ASSIGN(ScopedHiddenApiEnforcementPolicySetting);
160 };
161 
162 void InitializeCorePlatformApiPrivateFields() REQUIRES(!Locks::mutator_lock_);
163 
164 // Walks the stack, finds the caller of this reflective call and returns
165 // a hiddenapi AccessContext formed from its declaring class.
166 AccessContext GetReflectionCallerAccessContext(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
167 
168 // Implementation details. DO NOT ACCESS DIRECTLY.
169 namespace detail {
170 
171 // Class to encapsulate the signature of a member (ArtField or ArtMethod). This
172 // is used as a helper when matching prefixes, and when logging the signature.
173 class MemberSignature {
174  private:
175   enum MemberType {
176     kField,
177     kMethod,
178   };
179 
180   std::string class_name_;
181   std::string member_name_;
182   std::string type_signature_;
183   std::string tmp_;
184   MemberType type_;
185 
186   inline std::vector<const char*> GetSignatureParts() const;
187 
188  public:
189   explicit MemberSignature(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_);
190   explicit MemberSignature(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
191   explicit MemberSignature(const ClassAccessor::Field& field);
192   explicit MemberSignature(const ClassAccessor::Method& method);
193 
194   void Dump(std::ostream& os) const;
195 
196   bool Equals(const MemberSignature& other);
197   bool MemberNameAndTypeMatch(const MemberSignature& other);
198 
199   // Performs prefix match on this member. Since the full member signature is
200   // composed of several parts, we match each part in turn (rather than
201   // building the entire thing in memory and performing a simple prefix match)
202   bool DoesPrefixMatch(const std::string& prefix) const;
203 
204   bool DoesPrefixMatchAny(const std::vector<std::string>& exemptions);
205 
206   void WarnAboutAccess(AccessMethod access_method, ApiList list, bool access_denied);
207 
208   void LogAccessToEventLog(uint32_t sampled_value, AccessMethod access_method, bool access_denied);
209 
210   // Calls back into managed code to notify VMRuntime.nonSdkApiUsageConsumer that
211   // |member| was accessed. This is usually called when an API is unsupported,
212   // conditionally or unconditionally blocked. Given that the callback can execute arbitrary
213   // code, a call to this method can result in thread suspension.
214   void NotifyHiddenApiListener(AccessMethod access_method);
215 };
216 
217 // Locates hiddenapi flags for `member` in the corresponding dex file.
218 // NB: This is an O(N) operation, linear with the number of members in the class def.
219 template<typename T>
220 uint32_t GetDexFlags(T* member) REQUIRES_SHARED(Locks::mutator_lock_);
221 
222 // Handler of detected core platform API violations. Returns true if access to
223 // `member` should be denied.
224 template<typename T>
225 bool HandleCorePlatformApiViolation(T* member,
226                                     const AccessContext& caller_context,
227                                     AccessMethod access_method,
228                                     EnforcementPolicy policy)
229     REQUIRES_SHARED(Locks::mutator_lock_);
230 
231 template<typename T>
232 bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod access_method)
233     REQUIRES_SHARED(Locks::mutator_lock_);
234 
GetInterfaceMemberIfProxy(ArtField * field)235 inline ArtField* GetInterfaceMemberIfProxy(ArtField* field) { return field; }
236 
GetInterfaceMemberIfProxy(ArtMethod * method)237 inline ArtMethod* GetInterfaceMemberIfProxy(ArtMethod* method)
238     REQUIRES_SHARED(Locks::mutator_lock_) {
239   return method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
240 }
241 
242 // Returns access flags for the runtime representation of a class member (ArtField/ArtMember).
CreateRuntimeFlags_Impl(uint32_t dex_flags)243 ALWAYS_INLINE inline uint32_t CreateRuntimeFlags_Impl(uint32_t dex_flags) {
244   uint32_t runtime_flags = 0u;
245 
246   ApiList api_list(dex_flags);
247   DCHECK(api_list.IsValid());
248 
249   if (api_list.Contains(ApiList::Sdk())) {
250     runtime_flags |= kAccPublicApi;
251   } else {
252     // Only add domain-specific flags for non-public API members.
253     // This simplifies hardcoded values for intrinsics.
254     if (api_list.Contains(ApiList::CorePlatformApi())) {
255       runtime_flags |= kAccCorePlatformApi;
256     }
257   }
258 
259   DCHECK_EQ(runtime_flags & kAccHiddenapiBits, runtime_flags)
260       << "Runtime flags not in reserved access flags bits";
261   return runtime_flags;
262 }
263 
264 }  // namespace detail
265 
266 // Returns access flags for the runtime representation of a class member (ArtField/ArtMember).
CreateRuntimeFlags(const ClassAccessor::BaseItem & member)267 ALWAYS_INLINE inline uint32_t CreateRuntimeFlags(const ClassAccessor::BaseItem& member) {
268   return detail::CreateRuntimeFlags_Impl(member.GetHiddenapiFlags());
269 }
270 
271 // Returns access flags for the runtime representation of a class member (ArtField/ArtMember).
272 template<typename T>
CreateRuntimeFlags(T * member)273 ALWAYS_INLINE inline uint32_t CreateRuntimeFlags(T* member) REQUIRES_SHARED(Locks::mutator_lock_) {
274   return detail::CreateRuntimeFlags_Impl(detail::GetDexFlags(member));
275 }
276 
277 // Extracts hiddenapi runtime flags from access flags of ArtField.
GetRuntimeFlags(ArtField * field)278 ALWAYS_INLINE inline uint32_t GetRuntimeFlags(ArtField* field)
279     REQUIRES_SHARED(Locks::mutator_lock_) {
280   return field->GetAccessFlags() & kAccHiddenapiBits;
281 }
282 
283 // Extracts hiddenapi runtime flags from access flags of ArtMethod.
284 // Uses hardcoded values for intrinsics.
GetRuntimeFlags(ArtMethod * method)285 ALWAYS_INLINE inline uint32_t GetRuntimeFlags(ArtMethod* method)
286     REQUIRES_SHARED(Locks::mutator_lock_) {
287   if (UNLIKELY(method->IsIntrinsic())) {
288     switch (static_cast<Intrinsics>(method->GetIntrinsic())) {
289       case Intrinsics::kSystemArrayCopyChar:
290       case Intrinsics::kSystemArrayCopyByte:
291       case Intrinsics::kSystemArrayCopyInt:
292       case Intrinsics::kStringGetCharsNoCheck:
293       case Intrinsics::kReferenceGetReferent:
294       case Intrinsics::kReferenceRefersTo:
295       case Intrinsics::kMemoryPeekByte:
296       case Intrinsics::kMemoryPokeByte:
297       case Intrinsics::kCRC32Update:
298       case Intrinsics::kCRC32UpdateBytes:
299       case Intrinsics::kCRC32UpdateByteBuffer:
300       case Intrinsics::kStringNewStringFromBytes:
301       case Intrinsics::kStringNewStringFromChars:
302       case Intrinsics::kStringNewStringFromString:
303       case Intrinsics::kMemoryPeekIntNative:
304       case Intrinsics::kMemoryPeekLongNative:
305       case Intrinsics::kMemoryPeekShortNative:
306       case Intrinsics::kMemoryPokeIntNative:
307       case Intrinsics::kMemoryPokeLongNative:
308       case Intrinsics::kMemoryPokeShortNative:
309       case Intrinsics::kUnsafeCASInt:
310       case Intrinsics::kUnsafeCASLong:
311       case Intrinsics::kUnsafeCASObject:
312       case Intrinsics::kUnsafeGetAndAddInt:
313       case Intrinsics::kUnsafeGetAndAddLong:
314       case Intrinsics::kUnsafeGetAndSetInt:
315       case Intrinsics::kUnsafeGetAndSetLong:
316       case Intrinsics::kUnsafeGetAndSetObject:
317       case Intrinsics::kUnsafeGetLongVolatile:
318       case Intrinsics::kUnsafeGetObjectVolatile:
319       case Intrinsics::kUnsafeGetVolatile:
320       case Intrinsics::kUnsafePutLongOrdered:
321       case Intrinsics::kUnsafePutLongVolatile:
322       case Intrinsics::kUnsafePutObjectOrdered:
323       case Intrinsics::kUnsafePutObjectVolatile:
324       case Intrinsics::kUnsafePutOrdered:
325       case Intrinsics::kUnsafePutVolatile:
326       case Intrinsics::kUnsafeLoadFence:
327       case Intrinsics::kUnsafeStoreFence:
328       case Intrinsics::kUnsafeFullFence:
329       case Intrinsics::kJdkUnsafeCASInt:
330       case Intrinsics::kJdkUnsafeCASLong:
331       case Intrinsics::kJdkUnsafeCASObject:
332       case Intrinsics::kJdkUnsafeCompareAndSetInt:
333       case Intrinsics::kJdkUnsafeCompareAndSetLong:
334       case Intrinsics::kJdkUnsafeCompareAndSetObject:
335       case Intrinsics::kJdkUnsafeGetAndAddInt:
336       case Intrinsics::kJdkUnsafeGetAndAddLong:
337       case Intrinsics::kJdkUnsafeGetAndSetInt:
338       case Intrinsics::kJdkUnsafeGetAndSetLong:
339       case Intrinsics::kJdkUnsafeGetAndSetObject:
340       case Intrinsics::kJdkUnsafeGetLongVolatile:
341       case Intrinsics::kJdkUnsafeGetLongAcquire:
342       case Intrinsics::kJdkUnsafeGetObjectVolatile:
343       case Intrinsics::kJdkUnsafeGetObjectAcquire:
344       case Intrinsics::kJdkUnsafeGetVolatile:
345       case Intrinsics::kJdkUnsafeGetAcquire:
346       case Intrinsics::kJdkUnsafePutLongOrdered:
347       case Intrinsics::kJdkUnsafePutLongVolatile:
348       case Intrinsics::kJdkUnsafePutLongRelease:
349       case Intrinsics::kJdkUnsafePutObjectOrdered:
350       case Intrinsics::kJdkUnsafePutObjectVolatile:
351       case Intrinsics::kJdkUnsafePutObjectRelease:
352       case Intrinsics::kJdkUnsafePutOrdered:
353       case Intrinsics::kJdkUnsafePutVolatile:
354       case Intrinsics::kJdkUnsafePutRelease:
355       case Intrinsics::kJdkUnsafeLoadFence:
356       case Intrinsics::kJdkUnsafeStoreFence:
357       case Intrinsics::kJdkUnsafeFullFence:
358       case Intrinsics::kJdkUnsafeGet:
359       case Intrinsics::kJdkUnsafeGetLong:
360       case Intrinsics::kJdkUnsafeGetObject:
361       case Intrinsics::kJdkUnsafePutLong:
362       case Intrinsics::kJdkUnsafePut:
363       case Intrinsics::kJdkUnsafePutObject:
364         return 0u;
365       case Intrinsics::kFP16Ceil:
366       case Intrinsics::kFP16Compare:
367       case Intrinsics::kFP16Floor:
368       case Intrinsics::kFP16Greater:
369       case Intrinsics::kFP16GreaterEquals:
370       case Intrinsics::kFP16Less:
371       case Intrinsics::kFP16LessEquals:
372       case Intrinsics::kFP16Min:
373       case Intrinsics::kFP16Max:
374       case Intrinsics::kFP16ToFloat:
375       case Intrinsics::kFP16ToHalf:
376       case Intrinsics::kFP16Rint:
377       case Intrinsics::kUnsafeGet:
378       case Intrinsics::kUnsafeGetLong:
379       case Intrinsics::kUnsafeGetObject:
380       case Intrinsics::kUnsafePutLong:
381       case Intrinsics::kUnsafePut:
382       case Intrinsics::kUnsafePutObject:
383         return kAccCorePlatformApi;
384       default:
385         // Remaining intrinsics are public API. We DCHECK that in SetIntrinsic().
386         return kAccPublicApi;
387     }
388   } else {
389     return method->GetAccessFlags() & kAccHiddenapiBits;
390   }
391 }
392 
393 // Called by class linker when a new dex file has been registered. Assigns
394 // the AccessContext domain to the newly-registered dex file based on its
395 // location and class loader.
396 void InitializeDexFileDomain(const DexFile& dex_file, ObjPtr<mirror::ClassLoader> class_loader);
397 
398 // Returns true if access to `member` should be denied in the given context.
399 // The decision is based on whether the caller is in a trusted context or not.
400 // Because determining the access context can be expensive, a lambda function
401 // "fn_get_access_context" is lazily invoked after other criteria have been
402 // considered.
403 // This function might print warnings into the log if the member is hidden.
404 template<typename T>
405 bool ShouldDenyAccessToMember(T* member,
406                               const std::function<AccessContext()>& fn_get_access_context,
407                               AccessMethod access_method)
408     REQUIRES_SHARED(Locks::mutator_lock_);
409 
410 // Helper method for callers where access context can be determined beforehand.
411 // Wraps AccessContext in a lambda and passes it to the real ShouldDenyAccessToMember.
412 template<typename T>
ShouldDenyAccessToMember(T * member,const AccessContext & access_context,AccessMethod access_method)413 inline bool ShouldDenyAccessToMember(T* member,
414                                      const AccessContext& access_context,
415                                      AccessMethod access_method)
416     REQUIRES_SHARED(Locks::mutator_lock_) {
417   return ShouldDenyAccessToMember(member, [&]() { return access_context; }, access_method);
418 }
419 
420 }  // namespace hiddenapi
421 }  // namespace art
422 
423 #endif  // ART_RUNTIME_HIDDEN_API_H_
424