diff options
| author | 2022-10-26 17:03:33 -0700 | |
|---|---|---|
| committer | 2022-10-27 20:38:43 +0000 | |
| commit | b127850fda23698be0247e5b2110cdd01fff8fd7 (patch) | |
| tree | aab7fd9a22158c8cd0da2ef24ddd095df55e1e60 | |
| parent | 378c4815671736de334cde8fd42e742e8e83b681 (diff) | |
[SettingsProvider] workaround for DevicePolicyResourcesManager
DevicePolicyResourcesManager.getString() was added in T and called in
many places inside system server. However, it uses
DeviceConfig.getBoolean to determine if a feature is enabled or not. In
the places where it is called from inside system server,
`clearCallingIdentity` was not always called, which can result in
DeviceConfig.getBoolean throwing SecurityException due to mismatched
AttributionSource (calling uid is the caller from the binder client,
while the context is "android" which should have calling uid 0). Context
is "android" because it is inside the system server where the
DevicePolicyManager instance is created. This bug might lead to
unexpected behavior such as packages failing to be uninstalled by admin.
The easiest fix is to place a bypass in SettingsProvider and manually clear
the calling uid there. This fix also allows for the cleanest backporting as
it can be cherry-picked into T without touching all the places where
DevicePolicyResourcesManager.getString() is called in the system server.
BUG: 252663068
Test: manual
Change-Id: I37a6ceb29575593018b93093562c85d49770a43c
| -rw-r--r-- | core/java/android/provider/Settings.java | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 4e15b38463d6..c89f5dba8005 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3374,9 +3374,26 @@ public final class Settings { } } - // Fetch all flags for the namespace at once for caching purposes - Bundle b = cp.call(cr.getAttributionSource(), - mProviderHolder.mUri.getAuthority(), mCallListCommand, null, args); + Bundle b; + // b/252663068: if we're in system server and the caller did not call + // clearCallingIdentity, the read would fail due to mismatched AttributionSources. + // TODO(b/256013480): remove this bypass after fixing the callers in system server. + if (namespace.equals(DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER) + && Settings.isInSystemServer() + && Binder.getCallingUid() != Process.myUid()) { + final long token = Binder.clearCallingIdentity(); + try { + // Fetch all flags for the namespace at once for caching purposes + b = cp.call(cr.getAttributionSource(), + mProviderHolder.mUri.getAuthority(), mCallListCommand, null, args); + } finally { + Binder.restoreCallingIdentity(token); + } + } else { + // Fetch all flags for the namespace at once for caching purposes + b = cp.call(cr.getAttributionSource(), + mProviderHolder.mUri.getAuthority(), mCallListCommand, null, args); + } if (b == null) { // Invalid response, return an empty map return keyValues; |