summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libartbase/base/hiddenapi_flags.h10
-rw-r--r--runtime/hidden_api.cc21
-rw-r--r--runtime/hidden_api_test.cc38
3 files changed, 62 insertions, 7 deletions
diff --git a/libartbase/base/hiddenapi_flags.h b/libartbase/base/hiddenapi_flags.h
index cd0bc7578c..a9a903b71f 100644
--- a/libartbase/base/hiddenapi_flags.h
+++ b/libartbase/base/hiddenapi_flags.h
@@ -290,6 +290,16 @@ class ApiList {
// Returns true when no ApiList is specified and no domain_api flags either.
bool IsEmpty() const { return (GetValue() == Value::kInvalid) && (GetDomainApis() == 0); }
+ // Returns true if the ApiList is on blacklist.
+ bool IsBlacklisted() const {
+ return GetValue() == Value::kBlacklist;
+ }
+
+ // Returns true if the ApiList is a test API.
+ bool IsTestApi() const {
+ return helper::MatchesBitMask(helper::ToBit(DomainApi::kTestApi), dex_flags_);
+ }
+
// Returns the maximum target SDK version allowed to access this ApiList.
SdkVersion GetMaxAllowedSdkVersion() const { return kMaxSdkVersions[GetIntValue()]; }
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index 98774bdf2d..6a9bdf6c79 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -435,15 +435,10 @@ bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod acce
DCHECK(member != nullptr);
Runtime* runtime = Runtime::Current();
- EnforcementPolicy policy = runtime->GetHiddenApiEnforcementPolicy();
- DCHECK(policy != EnforcementPolicy::kDisabled)
+ EnforcementPolicy hiddenApiPolicy = runtime->GetHiddenApiEnforcementPolicy();
+ DCHECK(hiddenApiPolicy != EnforcementPolicy::kDisabled)
<< "Should never enter this function when access checks are completely disabled";
- const bool deny_access =
- (policy == EnforcementPolicy::kEnabled) &&
- IsSdkVersionSetAndMoreThan(runtime->GetTargetSdkVersion(),
- api_list.GetMaxAllowedSdkVersion());
-
MemberSignature member_signature(member);
// Check for an exemption first. Exempted APIs are treated as white list.
@@ -455,6 +450,18 @@ bool ShouldDenyAccessToMemberImpl(T* member, ApiList api_list, AccessMethod acce
return false;
}
+ EnforcementPolicy testApiPolicy = runtime->GetTestApiEnforcementPolicy();
+
+ bool deny_access = false;
+ if (hiddenApiPolicy == EnforcementPolicy::kEnabled) {
+ if (testApiPolicy == EnforcementPolicy::kDisabled && api_list.IsTestApi()) {
+ deny_access = false;
+ } else {
+ deny_access = IsSdkVersionSetAndMoreThan(runtime->GetTargetSdkVersion(),
+ api_list.GetMaxAllowedSdkVersion());
+ }
+ }
+
if (access_method != AccessMethod::kNone) {
// Print a log message with information about this class member access.
// We do this if we're about to deny access, or the app is debuggable.
diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc
index d5c03c3850..145bb07676 100644
--- a/runtime/hidden_api_test.cc
+++ b/runtime/hidden_api_test.cc
@@ -155,6 +155,44 @@ TEST_F(HiddenApiTest, CheckGetActionFromRuntimeFlags) {
ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blacklist()), true);
}
+TEST_F(HiddenApiTest, CheckTestApiEnforcement) {
+ ScopedObjectAccess soa(self_);
+
+ runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
+ runtime_->SetTargetSdkVersion(
+ static_cast<uint32_t>(hiddenapi::ApiList::GreylistMaxQ().GetMaxAllowedSdkVersion()) + 1);
+
+ // Default case where all TestApis are treated like non-TestApi.
+ runtime_->SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Whitelist()), false);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Greylist()), false);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxQ()), true);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxP()), true);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxO()), true);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blacklist()), true);
+
+ // A case where we want to allow access to TestApis.
+ runtime_->SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kDisabled);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Whitelist()), false);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Greylist()), false);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxQ()), false);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxP()), false);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::GreylistMaxO()), false);
+ ASSERT_EQ(
+ ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blacklist()), false);
+}
+
TEST_F(HiddenApiTest, CheckMembersRead) {
ASSERT_NE(nullptr, class1_field1_);
ASSERT_NE(nullptr, class1_field12_);