summaryrefslogtreecommitdiff
path: root/runtime/hidden_api.h
diff options
context:
space:
mode:
author David Brazdil <dbrazdil@google.com> 2018-03-22 16:27:18 +0000
committer Nicolas Geoffray <ngeoffray@google.com> 2018-03-26 08:05:33 +0000
commiteefabd28c21e6ae02ca05e97bd22f9e23cbf98a5 (patch)
tree58e4c2635e0d5682c3385bed639664ccfdd44f6a /runtime/hidden_api.h
parente8a4e378c5a928d5de07bee6db99150a57dabcd8 (diff)
Allow hidden API access from system libraries
Libraries like RemoteDisplay provide an APK that an app loads into its process and which accesses internal APIs on the app's behalf, without exposing the internals to the app. These libraries are considered part of the platform, but were not exempt from hidden API checks because they are not loaded with the boot strap class loader. This patch adds a new flag to DexFile class which the constructor sets to true of the canonical location of the newly loaded dex file starts with "${ANDROID_ROOT}/framework/". Hidden API enforcement then checks this flag when determining whether the caller of a hidden class member is allowed to access it or not. Bug: 64382372 Bug: 76138670 Bug: 76165623 Bug: 76112393 Test: art_dex_file_loader_test gtest Test: art/test.py --gtest Change-Id: If062bd668d7ba494bbb7b828e40932748d173b9a
Diffstat (limited to 'runtime/hidden_api.h')
-rw-r--r--runtime/hidden_api.h43
1 files changed, 32 insertions, 11 deletions
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 5c6b4b56bc..dbe776e050 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -130,15 +130,15 @@ inline void WarnAboutMemberAccess(ArtMethod* method, AccessMethod access_method)
}
// Returns true if access to `member` should be denied to the caller of the
-// reflective query. The decision is based on whether the caller is in boot
-// class path or not. Because different users of this function determine this
-// in a different way, `fn_caller_in_boot(self)` is called and should return
-// true if the caller is in boot class path.
+// reflective query. The decision is based on whether the caller is in the
+// platform or not. Because different users of this function determine this
+// in a different way, `fn_caller_in_platform(self)` is called and should
+// return true if the caller is located in the platform.
// This function might print warnings into the log if the member is hidden.
template<typename T>
inline bool ShouldBlockAccessToMember(T* member,
Thread* self,
- std::function<bool(Thread*)> fn_caller_in_boot,
+ std::function<bool(Thread*)> fn_caller_in_platform,
AccessMethod access_method)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(member != nullptr);
@@ -149,14 +149,14 @@ inline bool ShouldBlockAccessToMember(T* member,
return false;
}
- // Member is hidden. Walk the stack to find the caller.
+ // Member is hidden. Invoke `fn_caller_in_platform` and find the origin of the access.
// This can be *very* expensive. Save it for last.
- if (fn_caller_in_boot(self)) {
- // Caller in boot class path. Exit.
+ if (fn_caller_in_platform(self)) {
+ // Caller in the platform. Exit.
return false;
}
- // Member is hidden and we are not in the boot class path.
+ // Member is hidden and caller is not in the platform.
// Print a log message with information about this class member access.
// We do this regardless of whether we block the access or not.
@@ -187,18 +187,39 @@ inline bool ShouldBlockAccessToMember(T* member,
return false;
}
+// Returns true if the caller is either loaded by the boot strap class loader or comes from
+// a dex file located in ${ANDROID_ROOT}/framework/.
+inline bool IsCallerInPlatformDex(ObjPtr<mirror::ClassLoader> caller_class_loader,
+ ObjPtr<mirror::DexCache> caller_dex_cache)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (caller_class_loader.IsNull()) {
+ return true;
+ } else if (caller_dex_cache.IsNull()) {
+ return false;
+ } else {
+ const DexFile* caller_dex_file = caller_dex_cache->GetDexFile();
+ return caller_dex_file != nullptr && caller_dex_file->IsPlatformDexFile();
+ }
+}
+
+inline bool IsCallerInPlatformDex(ObjPtr<mirror::Class> caller)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return !caller.IsNull() && IsCallerInPlatformDex(caller->GetClassLoader(), caller->GetDexCache());
+}
+
// Returns true if access to `member` should be denied to a caller loaded with
// `caller_class_loader`.
// This function might print warnings into the log if the member is hidden.
template<typename T>
inline bool ShouldBlockAccessToMember(T* member,
ObjPtr<mirror::ClassLoader> caller_class_loader,
+ ObjPtr<mirror::DexCache> caller_dex_cache,
AccessMethod access_method)
REQUIRES_SHARED(Locks::mutator_lock_) {
- bool caller_in_boot = (caller_class_loader.IsNull());
+ bool caller_in_platform = IsCallerInPlatformDex(caller_class_loader, caller_dex_cache);
return ShouldBlockAccessToMember(member,
/* thread */ nullptr,
- [caller_in_boot] (Thread*) { return caller_in_boot; },
+ [caller_in_platform] (Thread*) { return caller_in_platform; },
access_method);
}