blob: 9d7c646022b14cce3601f9da6a114d9a7d59f630 [file] [log] [blame]
David Brazdil5a61bb72018-01-19 16:59:46 +00001/*
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
David Brazdil85865692018-10-30 17:26:20 +000020#include "art_field.h"
21#include "art_method.h"
Andreas Gampeb74f3072019-05-01 15:19:00 -070022#include "base/hiddenapi_domain.h"
David Brazdildcfa89b2018-10-31 11:04:10 +000023#include "base/hiddenapi_flags.h"
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080024#include "base/locks.h"
David Brazdil85865692018-10-30 17:26:20 +000025#include "intrinsics_enum.h"
David Brazdil8ce3bfa2018-03-12 18:01:18 +000026#include "mirror/class-inl.h"
David Brazdil5a61bb72018-01-19 16:59:46 +000027#include "reflection.h"
28#include "runtime.h"
29
30namespace art {
31namespace hiddenapi {
32
Mathew Inwood597d7f62018-03-22 11:36:47 +000033// Hidden API enforcement policy
34// This must be kept in sync with ApplicationInfo.ApiEnforcementPolicy in
35// frameworks/base/core/java/android/content/pm/ApplicationInfo.java
36enum class EnforcementPolicy {
David Brazdilf50ac102018-10-17 18:00:06 +010037 kDisabled = 0,
Mathew Inwooda8503d92018-04-05 16:10:25 +010038 kJustWarn = 1, // keep checks enabled, but allow everything (enables logging)
David Brazdilf50ac102018-10-17 18:00:06 +010039 kEnabled = 2, // ban dark grey & blacklist
40 kMax = kEnabled,
Mathew Inwood597d7f62018-03-22 11:36:47 +000041};
42
43inline EnforcementPolicy EnforcementPolicyFromInt(int api_policy_int) {
44 DCHECK_GE(api_policy_int, 0);
45 DCHECK_LE(api_policy_int, static_cast<int>(EnforcementPolicy::kMax));
46 return static_cast<EnforcementPolicy>(api_policy_int);
47}
48
Andrei Oneaa2d2bc22019-01-25 16:18:53 +000049// Hidden API access method
50// Thist must be kept in sync with VMRuntime.HiddenApiUsageLogger.ACCESS_METHOD_*
David Brazdilf50ac102018-10-17 18:00:06 +010051enum class AccessMethod {
Andrei Oneaa2d2bc22019-01-25 16:18:53 +000052 kNone = 0, // internal test that does not correspond to an actual access by app
53 kReflection = 1,
54 kJNI = 2,
55 kLinking = 3,
Mathew Inwood1fd97f22018-04-03 15:32:32 +010056};
57
David Brazdile7681822018-12-14 16:25:33 +000058// Represents the API domain of a caller/callee.
59class AccessContext {
David Brazdilf50ac102018-10-17 18:00:06 +010060 public:
David Brazdile7681822018-12-14 16:25:33 +000061 // Initialize to either the fully-trusted or fully-untrusted domain.
62 explicit AccessContext(bool is_trusted)
63 : klass_(nullptr),
64 dex_file_(nullptr),
65 domain_(ComputeDomain(is_trusted)) {}
David Brazdilf50ac102018-10-17 18:00:06 +010066
David Brazdile7681822018-12-14 16:25:33 +000067 // Initialize from class loader and dex file (via dex cache).
David Brazdilf50ac102018-10-17 18:00:06 +010068 AccessContext(ObjPtr<mirror::ClassLoader> class_loader, ObjPtr<mirror::DexCache> dex_cache)
David Brazdile7681822018-12-14 16:25:33 +000069 REQUIRES_SHARED(Locks::mutator_lock_)
70 : klass_(nullptr),
71 dex_file_(GetDexFileFromDexCache(dex_cache)),
72 domain_(ComputeDomain(class_loader, dex_file_)) {}
David Brazdilf50ac102018-10-17 18:00:06 +010073
David Brazdila5c3a802019-03-08 14:59:41 +000074 // Initialize from class loader and dex file (only used by tests).
75 AccessContext(ObjPtr<mirror::ClassLoader> class_loader, const DexFile* dex_file)
76 : klass_(nullptr),
77 dex_file_(dex_file),
78 domain_(ComputeDomain(class_loader, dex_file_)) {}
79
David Brazdile7681822018-12-14 16:25:33 +000080 // Initialize from Class.
81 explicit AccessContext(ObjPtr<mirror::Class> klass)
82 REQUIRES_SHARED(Locks::mutator_lock_)
83 : klass_(klass),
84 dex_file_(GetDexFileFromDexCache(klass->GetDexCache())),
85 domain_(ComputeDomain(klass, dex_file_)) {}
86
87 ObjPtr<mirror::Class> GetClass() const { return klass_; }
88 const DexFile* GetDexFile() const { return dex_file_; }
89 Domain GetDomain() const { return domain_; }
David Brazdild51e5742019-02-28 14:47:32 +000090 bool IsApplicationDomain() const { return domain_ == Domain::kApplication; }
David Brazdile7681822018-12-14 16:25:33 +000091
92 // Returns true if this domain is always allowed to access the domain of `callee`.
93 bool CanAlwaysAccess(const AccessContext& callee) const {
94 return IsDomainMoreTrustedThan(domain_, callee.domain_);
95 }
David Brazdilf50ac102018-10-17 18:00:06 +010096
97 private:
David Brazdile7681822018-12-14 16:25:33 +000098 static const DexFile* GetDexFileFromDexCache(ObjPtr<mirror::DexCache> dex_cache)
David Brazdilf50ac102018-10-17 18:00:06 +010099 REQUIRES_SHARED(Locks::mutator_lock_) {
David Brazdile7681822018-12-14 16:25:33 +0000100 return dex_cache.IsNull() ? nullptr : dex_cache->GetDexFile();
David Brazdilf50ac102018-10-17 18:00:06 +0100101 }
102
David Brazdile7681822018-12-14 16:25:33 +0000103 static Domain ComputeDomain(bool is_trusted) {
104 return is_trusted ? Domain::kCorePlatform : Domain::kApplication;
105 }
David Brazdilf50ac102018-10-17 18:00:06 +0100106
David Brazdila5c3a802019-03-08 14:59:41 +0000107 static Domain ComputeDomain(ObjPtr<mirror::ClassLoader> class_loader, const DexFile* dex_file) {
David Brazdile7681822018-12-14 16:25:33 +0000108 if (dex_file == nullptr) {
109 return ComputeDomain(/* is_trusted= */ class_loader.IsNull());
David Brazdilf50ac102018-10-17 18:00:06 +0100110 }
111
David Brazdila5c3a802019-03-08 14:59:41 +0000112 return dex_file->GetHiddenapiDomain();
David Brazdile7681822018-12-14 16:25:33 +0000113 }
114
115 static Domain ComputeDomain(ObjPtr<mirror::Class> klass, const DexFile* dex_file)
116 REQUIRES_SHARED(Locks::mutator_lock_) {
David Brazdilf50ac102018-10-17 18:00:06 +0100117 // Check other aspects of the context.
David Brazdile7681822018-12-14 16:25:33 +0000118 Domain domain = ComputeDomain(klass->GetClassLoader(), dex_file);
119
120 if (domain == Domain::kApplication &&
121 klass->ShouldSkipHiddenApiChecks() &&
122 Runtime::Current()->IsJavaDebuggable()) {
123 // Class is known, it is marked trusted and we are in debuggable mode.
124 domain = ComputeDomain(/* is_trusted= */ true);
125 }
126
127 return domain;
David Brazdilf50ac102018-10-17 18:00:06 +0100128 }
129
David Brazdile7681822018-12-14 16:25:33 +0000130 // Pointer to declaring class of the caller/callee (null if not provided).
131 // This is not safe across GC but we're only using this class for passing
132 // information about the caller to the access check logic and never retain
133 // the AccessContext instance beyond that.
134 const ObjPtr<mirror::Class> klass_;
135
136 // DexFile of the caller/callee (null if not provided).
137 const DexFile* const dex_file_;
138
139 // Computed domain of the caller/callee.
140 const Domain domain_;
David Brazdil068d68d2018-02-12 13:04:17 -0800141};
142
David Brazdil32bde992018-05-14 15:24:34 +0100143class ScopedHiddenApiEnforcementPolicySetting {
144 public:
145 explicit ScopedHiddenApiEnforcementPolicySetting(EnforcementPolicy new_policy)
146 : initial_policy_(Runtime::Current()->GetHiddenApiEnforcementPolicy()) {
147 Runtime::Current()->SetHiddenApiEnforcementPolicy(new_policy);
148 }
149
150 ~ScopedHiddenApiEnforcementPolicySetting() {
151 Runtime::Current()->SetHiddenApiEnforcementPolicy(initial_policy_);
152 }
153
154 private:
155 const EnforcementPolicy initial_policy_;
156 DISALLOW_COPY_AND_ASSIGN(ScopedHiddenApiEnforcementPolicySetting);
157};
158
Andreas Gampeaa120012018-03-28 16:23:24 -0700159// Implementation details. DO NOT ACCESS DIRECTLY.
160namespace detail {
David Brazdilee7d2fd2018-01-20 17:25:23 +0000161
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000162// Class to encapsulate the signature of a member (ArtField or ArtMethod). This
163// is used as a helper when matching prefixes, and when logging the signature.
164class MemberSignature {
165 private:
Mathew Inwood1fd97f22018-04-03 15:32:32 +0100166 enum MemberType {
167 kField,
168 kMethod,
169 };
170
171 std::string class_name_;
172 std::string member_name_;
173 std::string type_signature_;
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000174 std::string tmp_;
Mathew Inwood1fd97f22018-04-03 15:32:32 +0100175 MemberType type_;
176
177 inline std::vector<const char*> GetSignatureParts() const;
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000178
179 public:
Andreas Gampeaa120012018-03-28 16:23:24 -0700180 explicit MemberSignature(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_);
181 explicit MemberSignature(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
David Brazdil1a658632018-12-01 17:54:26 +0000182 explicit MemberSignature(const ClassAccessor::Field& field);
183 explicit MemberSignature(const ClassAccessor::Method& method);
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000184
Andreas Gampeaa120012018-03-28 16:23:24 -0700185 void Dump(std::ostream& os) const;
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000186
David Brazdil1a658632018-12-01 17:54:26 +0000187 bool Equals(const MemberSignature& other);
188 bool MemberNameAndTypeMatch(const MemberSignature& other);
189
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000190 // Performs prefix match on this member. Since the full member signature is
191 // composed of several parts, we match each part in turn (rather than
192 // building the entire thing in memory and performing a simple prefix match)
Andreas Gampeaa120012018-03-28 16:23:24 -0700193 bool DoesPrefixMatch(const std::string& prefix) const;
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000194
Andreas Gampeaa120012018-03-28 16:23:24 -0700195 bool IsExempted(const std::vector<std::string>& exemptions);
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000196
David Brazdil4de9bb62019-04-03 13:06:17 +0100197 void WarnAboutAccess(AccessMethod access_method, ApiList list, bool access_denied);
Mathew Inwood1fd97f22018-04-03 15:32:32 +0100198
Andrei Onea6ad020d2019-02-18 12:15:51 +0000199 void LogAccessToEventLog(uint32_t sampled_value, AccessMethod access_method, bool access_denied);
David Brazdilf50ac102018-10-17 18:00:06 +0100200
201 // Calls back into managed code to notify VMRuntime.nonSdkApiUsageConsumer that
202 // |member| was accessed. This is usually called when an API is on the black,
203 // dark grey or light grey lists. Given that the callback can execute arbitrary
204 // code, a call to this method can result in thread suspension.
205 void NotifyHiddenApiListener(AccessMethod access_method);
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000206};
David Brazdilee7d2fd2018-01-20 17:25:23 +0000207
David Brazdil85865692018-10-30 17:26:20 +0000208// Locates hiddenapi flags for `field` in the corresponding dex file.
209// NB: This is an O(N) operation, linear with the number of members in the class def.
David Brazdil1a658632018-12-01 17:54:26 +0000210template<typename T>
211uint32_t GetDexFlags(T* member) REQUIRES_SHARED(Locks::mutator_lock_);
David Brazdil85865692018-10-30 17:26:20 +0000212
David Brazdild51e5742019-02-28 14:47:32 +0000213// Handler of detected core platform API violations. Returns true if access to
214// `member` should be denied.
Andreas Gampeaa120012018-03-28 16:23:24 -0700215template<typename T>
David Brazdild51e5742019-02-28 14:47:32 +0000216bool HandleCorePlatformApiViolation(T* member,
217 const AccessContext& caller_context,
218 AccessMethod access_method,
219 EnforcementPolicy policy)
David Brazdile7681822018-12-14 16:25:33 +0000220 REQUIRES_SHARED(Locks::mutator_lock_);
221
222template<typename T>
David Brazdilf50ac102018-10-17 18:00:06 +0100223bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod access_method)
Andreas Gampeaa120012018-03-28 16:23:24 -0700224 REQUIRES_SHARED(Locks::mutator_lock_);
225
David Brazdil6a1dab42019-02-28 18:45:15 +0000226inline ArtField* GetInterfaceMemberIfProxy(ArtField* field) { return field; }
227
228inline ArtMethod* GetInterfaceMemberIfProxy(ArtMethod* method)
229 REQUIRES_SHARED(Locks::mutator_lock_) {
230 return method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
231}
232
David Brazdil85865692018-10-30 17:26:20 +0000233// Returns access flags for the runtime representation of a class member (ArtField/ArtMember).
David Brazdil31cc2792019-04-10 00:31:15 +0100234ALWAYS_INLINE inline uint32_t CreateRuntimeFlags_Impl(uint32_t dex_flags) {
David Brazdil85865692018-10-30 17:26:20 +0000235 uint32_t runtime_flags = 0u;
236
David Brazdil31cc2792019-04-10 00:31:15 +0100237 ApiList api_list(dex_flags);
David Brazdil90faceb2018-12-14 14:36:15 +0000238 DCHECK(api_list.IsValid());
David Brazdil85865692018-10-30 17:26:20 +0000239
David Brazdil90faceb2018-12-14 14:36:15 +0000240 if (api_list.Contains(ApiList::Whitelist())) {
David Brazdil85865692018-10-30 17:26:20 +0000241 runtime_flags |= kAccPublicApi;
David Brazdil90faceb2018-12-14 14:36:15 +0000242 } else {
243 // Only add domain-specific flags for non-public API members.
244 // This simplifies hardcoded values for intrinsics.
245 if (api_list.Contains(ApiList::CorePlatformApi())) {
246 runtime_flags |= kAccCorePlatformApi;
247 }
David Brazdil85865692018-10-30 17:26:20 +0000248 }
249
250 DCHECK_EQ(runtime_flags & kAccHiddenapiBits, runtime_flags)
251 << "Runtime flags not in reserved access flags bits";
252 return runtime_flags;
253}
254
David Brazdil31cc2792019-04-10 00:31:15 +0100255} // namespace detail
256
257// Returns access flags for the runtime representation of a class member (ArtField/ArtMember).
258ALWAYS_INLINE inline uint32_t CreateRuntimeFlags(const ClassAccessor::BaseItem& member) {
259 return detail::CreateRuntimeFlags_Impl(member.GetHiddenapiFlags());
260}
261
262// Returns access flags for the runtime representation of a class member (ArtField/ArtMember).
263template<typename T>
264ALWAYS_INLINE inline uint32_t CreateRuntimeFlags(T* member) REQUIRES_SHARED(Locks::mutator_lock_) {
265 return detail::CreateRuntimeFlags_Impl(detail::GetDexFlags(member));
266}
267
David Brazdil85865692018-10-30 17:26:20 +0000268// Extracts hiddenapi runtime flags from access flags of ArtField.
269ALWAYS_INLINE inline uint32_t GetRuntimeFlags(ArtField* field)
270 REQUIRES_SHARED(Locks::mutator_lock_) {
271 return field->GetAccessFlags() & kAccHiddenapiBits;
272}
273
274// Extracts hiddenapi runtime flags from access flags of ArtMethod.
275// Uses hardcoded values for intrinsics.
276ALWAYS_INLINE inline uint32_t GetRuntimeFlags(ArtMethod* method)
277 REQUIRES_SHARED(Locks::mutator_lock_) {
278 if (UNLIKELY(method->IsIntrinsic())) {
279 switch (static_cast<Intrinsics>(method->GetIntrinsic())) {
280 case Intrinsics::kSystemArrayCopyChar:
281 case Intrinsics::kStringGetCharsNoCheck:
282 case Intrinsics::kReferenceGetReferent:
283 case Intrinsics::kMemoryPeekByte:
284 case Intrinsics::kMemoryPokeByte:
285 case Intrinsics::kUnsafeCASInt:
286 case Intrinsics::kUnsafeCASLong:
287 case Intrinsics::kUnsafeCASObject:
288 case Intrinsics::kUnsafeGet:
289 case Intrinsics::kUnsafeGetAndAddInt:
290 case Intrinsics::kUnsafeGetAndAddLong:
291 case Intrinsics::kUnsafeGetAndSetInt:
292 case Intrinsics::kUnsafeGetAndSetLong:
293 case Intrinsics::kUnsafeGetAndSetObject:
David Brazdil85865692018-10-30 17:26:20 +0000294 case Intrinsics::kUnsafeGetLongVolatile:
295 case Intrinsics::kUnsafeGetObject:
296 case Intrinsics::kUnsafeGetObjectVolatile:
297 case Intrinsics::kUnsafeGetVolatile:
298 case Intrinsics::kUnsafePut:
299 case Intrinsics::kUnsafePutLong:
300 case Intrinsics::kUnsafePutLongOrdered:
301 case Intrinsics::kUnsafePutLongVolatile:
302 case Intrinsics::kUnsafePutObject:
303 case Intrinsics::kUnsafePutObjectOrdered:
304 case Intrinsics::kUnsafePutObjectVolatile:
305 case Intrinsics::kUnsafePutOrdered:
306 case Intrinsics::kUnsafePutVolatile:
307 case Intrinsics::kUnsafeLoadFence:
308 case Intrinsics::kUnsafeStoreFence:
309 case Intrinsics::kUnsafeFullFence:
310 case Intrinsics::kCRC32Update:
Evgeny Astigeevich15c5b972018-11-20 13:41:40 +0000311 case Intrinsics::kCRC32UpdateBytes:
Evgeny Astigeevich776a7c22018-12-17 11:40:34 +0000312 case Intrinsics::kCRC32UpdateByteBuffer:
David Brazdil85865692018-10-30 17:26:20 +0000313 case Intrinsics::kStringNewStringFromBytes:
314 case Intrinsics::kStringNewStringFromChars:
315 case Intrinsics::kStringNewStringFromString:
316 case Intrinsics::kMemoryPeekIntNative:
317 case Intrinsics::kMemoryPeekLongNative:
318 case Intrinsics::kMemoryPeekShortNative:
319 case Intrinsics::kMemoryPokeIntNative:
320 case Intrinsics::kMemoryPokeLongNative:
321 case Intrinsics::kMemoryPokeShortNative:
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;
David Brazdilc63d5662019-04-10 00:31:46 +0100359 case Intrinsics::kUnsafeGetLong:
360 return kAccCorePlatformApi;
David Brazdil85865692018-10-30 17:26:20 +0000361 default:
362 // Remaining intrinsics are public API. We DCHECK that in SetIntrinsic().
363 return kAccPublicApi;
364 }
365 } else {
366 return method->GetAccessFlags() & kAccHiddenapiBits;
367 }
368}
369
David Brazdila5c3a802019-03-08 14:59:41 +0000370// Called by class linker when a new dex file has been registered. Assigns
371// the AccessContext domain to the newly-registered dex file based on its
372// location and class loader.
373void InitializeDexFileDomain(const DexFile& dex_file, ObjPtr<mirror::ClassLoader> class_loader);
374
David Brazdilf50ac102018-10-17 18:00:06 +0100375// Returns true if access to `member` should be denied in the given context.
376// The decision is based on whether the caller is in a trusted context or not.
377// Because determining the access context can be expensive, a lambda function
378// "fn_get_access_context" is lazily invoked after other criteria have been
379// considered.
David Brazdil8ce3bfa2018-03-12 18:01:18 +0000380// This function might print warnings into the log if the member is hidden.
David Brazdilee7d2fd2018-01-20 17:25:23 +0000381template<typename T>
David Brazdilf50ac102018-10-17 18:00:06 +0100382inline bool ShouldDenyAccessToMember(T* member,
David Brazdil4bcd6572019-02-02 20:08:44 +0000383 const std::function<AccessContext()>& fn_get_access_context,
David Brazdilf50ac102018-10-17 18:00:06 +0100384 AccessMethod access_method)
David Brazdilee7d2fd2018-01-20 17:25:23 +0000385 REQUIRES_SHARED(Locks::mutator_lock_) {
386 DCHECK(member != nullptr);
David Brazdil6a1dab42019-02-28 18:45:15 +0000387
388 // Get the runtime flags encoded in member's access flags.
389 // Note: this works for proxy methods because they inherit access flags from their
390 // respective interface methods.
David Brazdile7681822018-12-14 16:25:33 +0000391 const uint32_t runtime_flags = GetRuntimeFlags(member);
David Brazdilee7d2fd2018-01-20 17:25:23 +0000392
David Brazdil85865692018-10-30 17:26:20 +0000393 // Exit early if member is public API. This flag is also set for non-boot class
394 // path fields/methods.
David Brazdile7681822018-12-14 16:25:33 +0000395 if ((runtime_flags & kAccPublicApi) != 0) {
David Brazdilf50ac102018-10-17 18:00:06 +0100396 return false;
David Brazdila02cb112018-01-31 11:36:39 +0000397 }
398
David Brazdile7681822018-12-14 16:25:33 +0000399 // Determine which domain the caller and callee belong to.
400 // This can be *very* expensive. This is why ShouldDenyAccessToMember
401 // should not be called on every individual access.
402 const AccessContext caller_context = fn_get_access_context();
403 const AccessContext callee_context(member->GetDeclaringClass());
404
405 // Non-boot classpath callers should have exited early.
David Brazdild51e5742019-02-28 14:47:32 +0000406 DCHECK(!callee_context.IsApplicationDomain());
David Brazdile7681822018-12-14 16:25:33 +0000407
408 // Check if the caller is always allowed to access members in the callee context.
409 if (caller_context.CanAlwaysAccess(callee_context)) {
David Brazdilc5a96e42019-01-09 10:04:45 +0000410 return false;
411 }
412
David Brazdile7681822018-12-14 16:25:33 +0000413 // Check if this is platform accessing core platform. We may warn if `member` is
414 // not part of core platform API.
415 switch (caller_context.GetDomain()) {
416 case Domain::kApplication: {
David Brazdild51e5742019-02-28 14:47:32 +0000417 DCHECK(!callee_context.IsApplicationDomain());
David Brazdile7681822018-12-14 16:25:33 +0000418
419 // Exit early if access checks are completely disabled.
420 EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
421 if (policy == EnforcementPolicy::kDisabled) {
422 return false;
423 }
424
David Brazdil6a1dab42019-02-28 18:45:15 +0000425 // If this is a proxy method, look at the interface method instead.
426 member = detail::GetInterfaceMemberIfProxy(member);
427
David Brazdile7681822018-12-14 16:25:33 +0000428 // Decode hidden API access flags from the dex file.
429 // This is an O(N) operation scaling with the number of fields/methods
430 // in the class. Only do this on slow path and only do it once.
431 ApiList api_list(detail::GetDexFlags(member));
432 DCHECK(api_list.IsValid());
433
434 // Member is hidden and caller is not exempted. Enter slow path.
435 return detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
436 }
437
438 case Domain::kPlatform: {
439 DCHECK(callee_context.GetDomain() == Domain::kCorePlatform);
440
441 // Member is part of core platform API. Accessing it is allowed.
442 if ((runtime_flags & kAccCorePlatformApi) != 0) {
443 return false;
444 }
445
446 // Allow access if access checks are disabled.
447 EnforcementPolicy policy = Runtime::Current()->GetCorePlatformApiEnforcementPolicy();
448 if (policy == EnforcementPolicy::kDisabled) {
449 return false;
450 }
451
David Brazdil6a1dab42019-02-28 18:45:15 +0000452 // If this is a proxy method, look at the interface method instead.
453 member = detail::GetInterfaceMemberIfProxy(member);
454
David Brazdile7681822018-12-14 16:25:33 +0000455 // Access checks are not disabled, report the violation.
David Brazdild51e5742019-02-28 14:47:32 +0000456 // This may also add kAccCorePlatformApi to the access flags of `member`
457 // so as to not warn again on next access.
458 return detail::HandleCorePlatformApiViolation(member,
459 caller_context,
460 access_method,
461 policy);
David Brazdile7681822018-12-14 16:25:33 +0000462 }
463
464 case Domain::kCorePlatform: {
465 LOG(FATAL) << "CorePlatform domain should be allowed to access all domains";
466 UNREACHABLE();
467 }
David Brazdila02cb112018-01-31 11:36:39 +0000468 }
David Brazdil8e1a7cb2018-03-27 08:14:25 +0000469}
470
David Brazdilf50ac102018-10-17 18:00:06 +0100471// Helper method for callers where access context can be determined beforehand.
472// Wraps AccessContext in a lambda and passes it to the real ShouldDenyAccessToMember.
David Brazdil8ce3bfa2018-03-12 18:01:18 +0000473template<typename T>
David Brazdilf50ac102018-10-17 18:00:06 +0100474inline bool ShouldDenyAccessToMember(T* member,
David Brazdile7681822018-12-14 16:25:33 +0000475 const AccessContext& access_context,
David Brazdilf50ac102018-10-17 18:00:06 +0100476 AccessMethod access_method)
David Brazdilee7d2fd2018-01-20 17:25:23 +0000477 REQUIRES_SHARED(Locks::mutator_lock_) {
David Brazdile7681822018-12-14 16:25:33 +0000478 return ShouldDenyAccessToMember(member, [&]() { return access_context; }, access_method);
David Brazdilee7d2fd2018-01-20 17:25:23 +0000479}
480
David Brazdil5a61bb72018-01-19 16:59:46 +0000481} // namespace hiddenapi
482} // namespace art
483
484#endif // ART_RUNTIME_HIDDEN_API_H_