blob: 13bead28be1d8e315c30fc87146df951335899e3 [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"
David Brazdildcfa89b2018-10-31 11:04:10 +000022#include "base/hiddenapi_flags.h"
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080023#include "base/locks.h"
David Brazdil85865692018-10-30 17:26:20 +000024#include "intrinsics_enum.h"
David Brazdil8ce3bfa2018-03-12 18:01:18 +000025#include "mirror/class-inl.h"
David Brazdil5a61bb72018-01-19 16:59:46 +000026#include "reflection.h"
27#include "runtime.h"
28
29namespace art {
30namespace hiddenapi {
31
Mathew Inwood597d7f62018-03-22 11:36:47 +000032// 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
35enum class EnforcementPolicy {
David Brazdilf50ac102018-10-17 18:00:06 +010036 kDisabled = 0,
Mathew Inwooda8503d92018-04-05 16:10:25 +010037 kJustWarn = 1, // keep checks enabled, but allow everything (enables logging)
David Brazdilf50ac102018-10-17 18:00:06 +010038 kEnabled = 2, // ban dark grey & blacklist
39 kMax = kEnabled,
Mathew Inwood597d7f62018-03-22 11:36:47 +000040};
41
42inline 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
David Brazdilf50ac102018-10-17 18:00:06 +010048enum class AccessMethod {
Mathew Inwood17245202018-04-12 13:56:37 +010049 kNone, // internal test that does not correspond to an actual access by app
50 kReflection,
51 kJNI,
52 kLinking,
Mathew Inwood1fd97f22018-04-03 15:32:32 +010053};
54
David Brazdilf50ac102018-10-17 18:00:06 +010055struct AccessContext {
56 public:
57 explicit AccessContext(bool is_trusted) : is_trusted_(is_trusted) {}
58
59 explicit AccessContext(ObjPtr<mirror::Class> klass) : is_trusted_(GetIsTrusted(klass)) {}
60
61 AccessContext(ObjPtr<mirror::ClassLoader> class_loader, ObjPtr<mirror::DexCache> dex_cache)
62 : is_trusted_(GetIsTrusted(class_loader, dex_cache)) {}
63
64 bool IsTrusted() const { return is_trusted_; }
65
66 private:
67 static bool GetIsTrusted(ObjPtr<mirror::ClassLoader> class_loader,
68 ObjPtr<mirror::DexCache> dex_cache)
69 REQUIRES_SHARED(Locks::mutator_lock_) {
70 // Trust if the caller is in is boot class loader.
71 if (class_loader.IsNull()) {
72 return true;
73 }
74
75 // Trust if caller is in a platform dex file.
76 if (!dex_cache.IsNull()) {
77 const DexFile* dex_file = dex_cache->GetDexFile();
78 if (dex_file != nullptr && dex_file->IsPlatformDexFile()) {
79 return true;
80 }
81 }
82
83 return false;
84 }
85
86 static bool GetIsTrusted(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
87 DCHECK(!klass.IsNull());
88
89 if (klass->ShouldSkipHiddenApiChecks() && Runtime::Current()->IsJavaDebuggable()) {
90 // Class is known, it is marked trusted and we are in debuggable mode.
91 return true;
92 }
93
94 // Check other aspects of the context.
95 return GetIsTrusted(klass->GetClassLoader(), klass->GetDexCache());
96 }
97
98 bool is_trusted_;
David Brazdil068d68d2018-02-12 13:04:17 -080099};
100
David Brazdil32bde992018-05-14 15:24:34 +0100101class ScopedHiddenApiEnforcementPolicySetting {
102 public:
103 explicit ScopedHiddenApiEnforcementPolicySetting(EnforcementPolicy new_policy)
104 : initial_policy_(Runtime::Current()->GetHiddenApiEnforcementPolicy()) {
105 Runtime::Current()->SetHiddenApiEnforcementPolicy(new_policy);
106 }
107
108 ~ScopedHiddenApiEnforcementPolicySetting() {
109 Runtime::Current()->SetHiddenApiEnforcementPolicy(initial_policy_);
110 }
111
112 private:
113 const EnforcementPolicy initial_policy_;
114 DISALLOW_COPY_AND_ASSIGN(ScopedHiddenApiEnforcementPolicySetting);
115};
116
Andreas Gampeaa120012018-03-28 16:23:24 -0700117// Implementation details. DO NOT ACCESS DIRECTLY.
118namespace detail {
David Brazdilee7d2fd2018-01-20 17:25:23 +0000119
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000120// Class to encapsulate the signature of a member (ArtField or ArtMethod). This
121// is used as a helper when matching prefixes, and when logging the signature.
122class MemberSignature {
123 private:
Mathew Inwood1fd97f22018-04-03 15:32:32 +0100124 enum MemberType {
125 kField,
126 kMethod,
127 };
128
129 std::string class_name_;
130 std::string member_name_;
131 std::string type_signature_;
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000132 std::string tmp_;
Mathew Inwood1fd97f22018-04-03 15:32:32 +0100133 MemberType type_;
134
135 inline std::vector<const char*> GetSignatureParts() const;
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000136
137 public:
Andreas Gampeaa120012018-03-28 16:23:24 -0700138 explicit MemberSignature(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_);
139 explicit MemberSignature(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
David Brazdil1a658632018-12-01 17:54:26 +0000140 explicit MemberSignature(const ClassAccessor::Field& field);
141 explicit MemberSignature(const ClassAccessor::Method& method);
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000142
Andreas Gampeaa120012018-03-28 16:23:24 -0700143 void Dump(std::ostream& os) const;
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000144
David Brazdil1a658632018-12-01 17:54:26 +0000145 bool Equals(const MemberSignature& other);
146 bool MemberNameAndTypeMatch(const MemberSignature& other);
147
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000148 // Performs prefix match on this member. Since the full member signature is
149 // composed of several parts, we match each part in turn (rather than
150 // building the entire thing in memory and performing a simple prefix match)
Andreas Gampeaa120012018-03-28 16:23:24 -0700151 bool DoesPrefixMatch(const std::string& prefix) const;
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000152
Andreas Gampeaa120012018-03-28 16:23:24 -0700153 bool IsExempted(const std::vector<std::string>& exemptions);
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000154
David Brazdil47cd2722018-10-23 12:50:02 +0100155 void WarnAboutAccess(AccessMethod access_method, ApiList list);
Mathew Inwood1fd97f22018-04-03 15:32:32 +0100156
David Brazdilf50ac102018-10-17 18:00:06 +0100157 void LogAccessToEventLog(AccessMethod access_method, bool access_denied);
158
159 // Calls back into managed code to notify VMRuntime.nonSdkApiUsageConsumer that
160 // |member| was accessed. This is usually called when an API is on the black,
161 // dark grey or light grey lists. Given that the callback can execute arbitrary
162 // code, a call to this method can result in thread suspension.
163 void NotifyHiddenApiListener(AccessMethod access_method);
Mathew Inwood7d74ef52018-03-16 14:18:33 +0000164};
David Brazdilee7d2fd2018-01-20 17:25:23 +0000165
David Brazdil85865692018-10-30 17:26:20 +0000166// Locates hiddenapi flags for `field` in the corresponding dex file.
167// NB: This is an O(N) operation, linear with the number of members in the class def.
David Brazdil1a658632018-12-01 17:54:26 +0000168template<typename T>
169uint32_t GetDexFlags(T* member) REQUIRES_SHARED(Locks::mutator_lock_);
David Brazdil85865692018-10-30 17:26:20 +0000170
Andreas Gampeaa120012018-03-28 16:23:24 -0700171template<typename T>
David Brazdilf50ac102018-10-17 18:00:06 +0100172bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod access_method)
Andreas Gampeaa120012018-03-28 16:23:24 -0700173 REQUIRES_SHARED(Locks::mutator_lock_);
174
Andreas Gampeaa120012018-03-28 16:23:24 -0700175} // namespace detail
176
David Brazdil85865692018-10-30 17:26:20 +0000177// Returns access flags for the runtime representation of a class member (ArtField/ArtMember).
178ALWAYS_INLINE inline uint32_t CreateRuntimeFlags(const ClassAccessor::BaseItem& member) {
179 uint32_t runtime_flags = 0u;
180
181 uint32_t dex_flags = member.GetHiddenapiFlags();
David Brazdildcfa89b2018-10-31 11:04:10 +0000182 DCHECK(AreValidDexFlags(dex_flags));
David Brazdil85865692018-10-30 17:26:20 +0000183
David Brazdildcfa89b2018-10-31 11:04:10 +0000184 ApiList api_list = ApiList::FromDexFlags(dex_flags);
185 if (api_list == ApiList::Whitelist()) {
David Brazdil85865692018-10-30 17:26:20 +0000186 runtime_flags |= kAccPublicApi;
187 }
188
189 DCHECK_EQ(runtime_flags & kAccHiddenapiBits, runtime_flags)
190 << "Runtime flags not in reserved access flags bits";
191 return runtime_flags;
192}
193
194// Extracts hiddenapi runtime flags from access flags of ArtField.
195ALWAYS_INLINE inline uint32_t GetRuntimeFlags(ArtField* field)
196 REQUIRES_SHARED(Locks::mutator_lock_) {
197 return field->GetAccessFlags() & kAccHiddenapiBits;
198}
199
200// Extracts hiddenapi runtime flags from access flags of ArtMethod.
201// Uses hardcoded values for intrinsics.
202ALWAYS_INLINE inline uint32_t GetRuntimeFlags(ArtMethod* method)
203 REQUIRES_SHARED(Locks::mutator_lock_) {
204 if (UNLIKELY(method->IsIntrinsic())) {
205 switch (static_cast<Intrinsics>(method->GetIntrinsic())) {
206 case Intrinsics::kSystemArrayCopyChar:
207 case Intrinsics::kStringGetCharsNoCheck:
208 case Intrinsics::kReferenceGetReferent:
209 case Intrinsics::kMemoryPeekByte:
210 case Intrinsics::kMemoryPokeByte:
211 case Intrinsics::kUnsafeCASInt:
212 case Intrinsics::kUnsafeCASLong:
213 case Intrinsics::kUnsafeCASObject:
214 case Intrinsics::kUnsafeGet:
215 case Intrinsics::kUnsafeGetAndAddInt:
216 case Intrinsics::kUnsafeGetAndAddLong:
217 case Intrinsics::kUnsafeGetAndSetInt:
218 case Intrinsics::kUnsafeGetAndSetLong:
219 case Intrinsics::kUnsafeGetAndSetObject:
220 case Intrinsics::kUnsafeGetLong:
221 case Intrinsics::kUnsafeGetLongVolatile:
222 case Intrinsics::kUnsafeGetObject:
223 case Intrinsics::kUnsafeGetObjectVolatile:
224 case Intrinsics::kUnsafeGetVolatile:
225 case Intrinsics::kUnsafePut:
226 case Intrinsics::kUnsafePutLong:
227 case Intrinsics::kUnsafePutLongOrdered:
228 case Intrinsics::kUnsafePutLongVolatile:
229 case Intrinsics::kUnsafePutObject:
230 case Intrinsics::kUnsafePutObjectOrdered:
231 case Intrinsics::kUnsafePutObjectVolatile:
232 case Intrinsics::kUnsafePutOrdered:
233 case Intrinsics::kUnsafePutVolatile:
234 case Intrinsics::kUnsafeLoadFence:
235 case Intrinsics::kUnsafeStoreFence:
236 case Intrinsics::kUnsafeFullFence:
237 case Intrinsics::kCRC32Update:
Evgeny Astigeevich15c5b972018-11-20 13:41:40 +0000238 case Intrinsics::kCRC32UpdateBytes:
David Brazdil85865692018-10-30 17:26:20 +0000239 case Intrinsics::kStringNewStringFromBytes:
240 case Intrinsics::kStringNewStringFromChars:
241 case Intrinsics::kStringNewStringFromString:
242 case Intrinsics::kMemoryPeekIntNative:
243 case Intrinsics::kMemoryPeekLongNative:
244 case Intrinsics::kMemoryPeekShortNative:
245 case Intrinsics::kMemoryPokeIntNative:
246 case Intrinsics::kMemoryPokeLongNative:
247 case Intrinsics::kMemoryPokeShortNative:
248 case Intrinsics::kVarHandleFullFence:
249 case Intrinsics::kVarHandleAcquireFence:
250 case Intrinsics::kVarHandleReleaseFence:
251 case Intrinsics::kVarHandleLoadLoadFence:
252 case Intrinsics::kVarHandleStoreStoreFence:
253 case Intrinsics::kVarHandleCompareAndExchange:
254 case Intrinsics::kVarHandleCompareAndExchangeAcquire:
255 case Intrinsics::kVarHandleCompareAndExchangeRelease:
256 case Intrinsics::kVarHandleCompareAndSet:
257 case Intrinsics::kVarHandleGet:
258 case Intrinsics::kVarHandleGetAcquire:
259 case Intrinsics::kVarHandleGetAndAdd:
260 case Intrinsics::kVarHandleGetAndAddAcquire:
261 case Intrinsics::kVarHandleGetAndAddRelease:
262 case Intrinsics::kVarHandleGetAndBitwiseAnd:
263 case Intrinsics::kVarHandleGetAndBitwiseAndAcquire:
264 case Intrinsics::kVarHandleGetAndBitwiseAndRelease:
265 case Intrinsics::kVarHandleGetAndBitwiseOr:
266 case Intrinsics::kVarHandleGetAndBitwiseOrAcquire:
267 case Intrinsics::kVarHandleGetAndBitwiseOrRelease:
268 case Intrinsics::kVarHandleGetAndBitwiseXor:
269 case Intrinsics::kVarHandleGetAndBitwiseXorAcquire:
270 case Intrinsics::kVarHandleGetAndBitwiseXorRelease:
271 case Intrinsics::kVarHandleGetAndSet:
272 case Intrinsics::kVarHandleGetAndSetAcquire:
273 case Intrinsics::kVarHandleGetAndSetRelease:
274 case Intrinsics::kVarHandleGetOpaque:
275 case Intrinsics::kVarHandleGetVolatile:
276 case Intrinsics::kVarHandleSet:
277 case Intrinsics::kVarHandleSetOpaque:
278 case Intrinsics::kVarHandleSetRelease:
279 case Intrinsics::kVarHandleSetVolatile:
280 case Intrinsics::kVarHandleWeakCompareAndSet:
281 case Intrinsics::kVarHandleWeakCompareAndSetAcquire:
282 case Intrinsics::kVarHandleWeakCompareAndSetPlain:
283 case Intrinsics::kVarHandleWeakCompareAndSetRelease:
284 return 0u;
285 default:
286 // Remaining intrinsics are public API. We DCHECK that in SetIntrinsic().
287 return kAccPublicApi;
288 }
289 } else {
290 return method->GetAccessFlags() & kAccHiddenapiBits;
291 }
292}
293
David Brazdilf50ac102018-10-17 18:00:06 +0100294// Returns true if access to `member` should be denied in the given context.
295// The decision is based on whether the caller is in a trusted context or not.
296// Because determining the access context can be expensive, a lambda function
297// "fn_get_access_context" is lazily invoked after other criteria have been
298// considered.
David Brazdil8ce3bfa2018-03-12 18:01:18 +0000299// This function might print warnings into the log if the member is hidden.
David Brazdilee7d2fd2018-01-20 17:25:23 +0000300template<typename T>
David Brazdilf50ac102018-10-17 18:00:06 +0100301inline bool ShouldDenyAccessToMember(T* member,
302 std::function<AccessContext()> fn_get_access_context,
303 AccessMethod access_method)
David Brazdilee7d2fd2018-01-20 17:25:23 +0000304 REQUIRES_SHARED(Locks::mutator_lock_) {
305 DCHECK(member != nullptr);
David Brazdilee7d2fd2018-01-20 17:25:23 +0000306
David Brazdil85865692018-10-30 17:26:20 +0000307 // Exit early if member is public API. This flag is also set for non-boot class
308 // path fields/methods.
309 if ((GetRuntimeFlags(member) & kAccPublicApi) != 0) {
David Brazdilf50ac102018-10-17 18:00:06 +0100310 return false;
David Brazdila02cb112018-01-31 11:36:39 +0000311 }
312
David Brazdilf50ac102018-10-17 18:00:06 +0100313 // Check if caller is exempted from access checks.
David Brazdila02cb112018-01-31 11:36:39 +0000314 // This can be *very* expensive. Save it for last.
David Brazdilf50ac102018-10-17 18:00:06 +0100315 if (fn_get_access_context().IsTrusted()) {
316 return false;
David Brazdila02cb112018-01-31 11:36:39 +0000317 }
318
David Brazdil85865692018-10-30 17:26:20 +0000319 // Decode hidden API access flags from the dex file.
320 // This is an O(N) operation scaling with the number of fields/methods
321 // in the class. Only do this on slow path and only do it once.
David Brazdildcfa89b2018-10-31 11:04:10 +0000322 ApiList api_list = ApiList::FromDexFlags(detail::GetDexFlags(member));
David Brazdil85865692018-10-30 17:26:20 +0000323
David Brazdilf50ac102018-10-17 18:00:06 +0100324 // Member is hidden and caller is not exempted. Enter slow path.
325 return detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
David Brazdil8e1a7cb2018-03-27 08:14:25 +0000326}
327
David Brazdilf50ac102018-10-17 18:00:06 +0100328// Helper method for callers where access context can be determined beforehand.
329// Wraps AccessContext in a lambda and passes it to the real ShouldDenyAccessToMember.
David Brazdil8ce3bfa2018-03-12 18:01:18 +0000330template<typename T>
David Brazdilf50ac102018-10-17 18:00:06 +0100331inline bool ShouldDenyAccessToMember(T* member,
332 AccessContext access_context,
333 AccessMethod access_method)
David Brazdilee7d2fd2018-01-20 17:25:23 +0000334 REQUIRES_SHARED(Locks::mutator_lock_) {
David Brazdilf50ac102018-10-17 18:00:06 +0100335 return ShouldDenyAccessToMember(
336 member,
337 [&] () REQUIRES_SHARED(Locks::mutator_lock_) { return access_context; },
338 access_method);
David Brazdilee7d2fd2018-01-20 17:25:23 +0000339}
340
David Brazdil5a61bb72018-01-19 16:59:46 +0000341} // namespace hiddenapi
342} // namespace art
343
344#endif // ART_RUNTIME_HIDDEN_API_H_