Reenable core platform API violation warnings, dedupe
Print a warning the first time a non-core platform API member is
accessed and add kAccCorePlatformApi to its access flags to not report
it next time. Only do this when policy is kJustWarn. This prevents
logspam.
Bug: 125701194
Bug: 119068555
Test: compiles, boots
Test: art/test.py -b -r -t 674
Change-Id: Ia7d6ba4f1f30fbea7bdea1670183c17f84ca1150
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index 68ed102..b458582 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -260,10 +260,10 @@
}
template<typename T>
-static ALWAYS_INLINE void MaybeWhitelistMember(Runtime* runtime, T* member)
+static ALWAYS_INLINE void MaybeUpdateAccessFlags(Runtime* runtime, T* member, uint32_t flag)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (CanUpdateRuntimeFlags(member) && runtime->ShouldDedupeHiddenApiWarnings()) {
- member->SetAccessFlags(member->GetAccessFlags() | kAccPublicApi);
+ member->SetAccessFlags(member->GetAccessFlags() | flag);
}
}
@@ -357,14 +357,27 @@
}
template<typename T>
-void MaybeReportCorePlatformApiViolation(T* member,
- const AccessContext& caller_context,
- AccessMethod access_method) {
+bool HandleCorePlatformApiViolation(T* member,
+ const AccessContext& caller_context,
+ AccessMethod access_method,
+ EnforcementPolicy policy) {
+ DCHECK(policy != EnforcementPolicy::kDisabled)
+ << "Should never enter this function when access checks are completely disabled";
+
if (access_method != AccessMethod::kNone) {
- MemberSignature sig(member);
- LOG(ERROR) << "CorePlatformApi violation: " << Dumpable<MemberSignature>(sig)
- << " from " << caller_context << " using " << access_method;
+ LOG(WARNING) << "Core platform API violation: "
+ << Dumpable<MemberSignature>(MemberSignature(member))
+ << " from " << caller_context << " using " << access_method;
+
+ // If policy is set to just warn, add kAccCorePlatformApi to access flags of
+ // `member` to avoid reporting the violation again next time.
+ if (policy == EnforcementPolicy::kJustWarn) {
+ MaybeUpdateAccessFlags(Runtime::Current(), member, kAccCorePlatformApi);
+ }
}
+
+ // Deny access if enforcement is enabled.
+ return policy == EnforcementPolicy::kEnabled;
}
template<typename T>
@@ -388,7 +401,7 @@
// Avoid re-examining the exemption list next time.
// Note this results in no warning for the member, which seems like what one would expect.
// Exemptions effectively adds new members to the whitelist.
- MaybeWhitelistMember(runtime, member);
+ MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
return false;
}
@@ -418,7 +431,7 @@
// If this access was not denied, move the member into whitelist and skip
// the warning the next time the member is accessed.
if (!deny_access) {
- MaybeWhitelistMember(runtime, member);
+ MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
}
}
@@ -428,12 +441,14 @@
// Need to instantiate these.
template uint32_t GetDexFlags<ArtField>(ArtField* member);
template uint32_t GetDexFlags<ArtMethod>(ArtMethod* member);
-template void MaybeReportCorePlatformApiViolation(ArtField* member,
- const AccessContext& caller_context,
- AccessMethod access_method);
-template void MaybeReportCorePlatformApiViolation(ArtMethod* member,
- const AccessContext& caller_context,
- AccessMethod access_method);
+template bool HandleCorePlatformApiViolation(ArtField* member,
+ const AccessContext& caller_context,
+ AccessMethod access_method,
+ EnforcementPolicy policy);
+template bool HandleCorePlatformApiViolation(ArtMethod* member,
+ const AccessContext& caller_context,
+ AccessMethod access_method,
+ EnforcementPolicy policy);
template bool ShouldDenyAccessToMemberImpl<ArtField>(ArtField* member,
ApiList api_list,
AccessMethod access_method);
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 0a40341..08a9fff 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -80,8 +80,7 @@
ObjPtr<mirror::Class> GetClass() const { return klass_; }
const DexFile* GetDexFile() const { return dex_file_; }
Domain GetDomain() const { return domain_; }
-
- bool IsUntrustedDomain() const { return domain_ == Domain::kApplication; }
+ bool IsApplicationDomain() const { return domain_ == Domain::kApplication; }
// Returns true if this domain is always allowed to access the domain of `callee`.
bool CanAlwaysAccess(const AccessContext& callee) const {
@@ -212,10 +211,13 @@
template<typename T>
uint32_t GetDexFlags(T* member) REQUIRES_SHARED(Locks::mutator_lock_);
+// Handler of detected core platform API violations. Returns true if access to
+// `member` should be denied.
template<typename T>
-void MaybeReportCorePlatformApiViolation(T* member,
- const AccessContext& caller_context,
- AccessMethod access_method)
+bool HandleCorePlatformApiViolation(T* member,
+ const AccessContext& caller_context,
+ AccessMethod access_method,
+ EnforcementPolicy policy)
REQUIRES_SHARED(Locks::mutator_lock_);
template<typename T>
@@ -385,7 +387,7 @@
const AccessContext callee_context(member->GetDeclaringClass());
// Non-boot classpath callers should have exited early.
- DCHECK(!callee_context.IsUntrustedDomain());
+ DCHECK(!callee_context.IsApplicationDomain());
// Check if the caller is always allowed to access members in the callee context.
if (caller_context.CanAlwaysAccess(callee_context)) {
@@ -396,7 +398,7 @@
// not part of core platform API.
switch (caller_context.GetDomain()) {
case Domain::kApplication: {
- DCHECK(!callee_context.IsUntrustedDomain());
+ DCHECK(!callee_context.IsApplicationDomain());
// Exit early if access checks are completely disabled.
EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
@@ -435,10 +437,12 @@
member = detail::GetInterfaceMemberIfProxy(member);
// Access checks are not disabled, report the violation.
- // detail::MaybeReportCorePlatformApiViolation(member, caller_context, access_method);
-
- // Deny access if the policy is enabled.
- return policy == EnforcementPolicy::kEnabled;
+ // This may also add kAccCorePlatformApi to the access flags of `member`
+ // so as to not warn again on next access.
+ return detail::HandleCorePlatformApiViolation(member,
+ caller_context,
+ access_method,
+ policy);
}
case Domain::kCorePlatform: {