diff options
author | 2023-01-12 15:34:32 +0000 | |
---|---|---|
committer | 2023-02-14 16:27:22 +0000 | |
commit | e8eb9f8da5e8f58e7592e20a1e373954ea2ff0f2 (patch) | |
tree | 0e9640131ea370e51c794bab18ce4cf8380c0e4e | |
parent | 8bb72213932e1f655d871a2da46d3f2c6c372316 (diff) |
Add + enforce new DeviceConfig permissions.
Adds these new permissions, and grants them to `adb`:
- `ALLOWLISTED_WRITE_DEVICE_CONFIG`
- `READ_WRITE_SYNC_DISABLED_MODE_CONFIG`
Uses `ALLOWLISTED_WRITE_DEVICE_CONFIG` to restrict writing flags to
DeviceConfig unless they are explicitly allowlisted.
Revokes `WRITE_DEVICE_CONFIG` from `adb`, and grants it
`ALLOWLISTED_WRITE_DEVICE_CONFIG`.
Bug: 251818659
Test: m
Change-Id: I0d6784a9437e0b0344f47d13dab0f838f63eaded
10 files changed, 89 insertions, 20 deletions
diff --git a/apct-tests/perftests/textclassifier/src/android/view/textclassifier/TextClassificationManagerPerfTest.java b/apct-tests/perftests/textclassifier/src/android/view/textclassifier/TextClassificationManagerPerfTest.java index 46250d74a4e3..e24e9cd3a63a 100644 --- a/apct-tests/perftests/textclassifier/src/android/view/textclassifier/TextClassificationManagerPerfTest.java +++ b/apct-tests/perftests/textclassifier/src/android/view/textclassifier/TextClassificationManagerPerfTest.java @@ -32,8 +32,8 @@ import org.junit.Test; @LargeTest public class TextClassificationManagerPerfTest { - private static final String WRITE_DEVICE_CONFIG_PERMISSION = - "android.permission.WRITE_DEVICE_CONFIG"; + private static final String ALLOWLISTED_WRITE_DEVICE_CONFIG_PERMISSION = + "android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG"; @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); @@ -44,7 +44,7 @@ public class TextClassificationManagerPerfTest { public static void setUpClass() { InstrumentationRegistry.getInstrumentation().getUiAutomation() .adoptShellPermissionIdentity( - WRITE_DEVICE_CONFIG_PERMISSION); + ALLOWLISTED_WRITE_DEVICE_CONFIG_PERMISSION); } @AfterClass diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 67aa074100fb..4869e1b3d157 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -33,6 +33,7 @@ package android { field public static final String ADD_TRUSTED_DISPLAY = "android.permission.ADD_TRUSTED_DISPLAY"; field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY"; field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE"; + field public static final String ALLOWLISTED_WRITE_DEVICE_CONFIG = "android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG"; field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"; field public static final String ALLOW_PLACE_IN_MULTI_PANE_SETTINGS = "android.permission.ALLOW_PLACE_IN_MULTI_PANE_SETTINGS"; field public static final String ALLOW_SLIPPERY_TOUCHES = "android.permission.ALLOW_SLIPPERY_TOUCHES"; @@ -284,6 +285,7 @@ package android { field public static final String READ_SYSTEM_UPDATE_INFO = "android.permission.READ_SYSTEM_UPDATE_INFO"; field public static final String READ_WALLPAPER_INTERNAL = "android.permission.READ_WALLPAPER_INTERNAL"; field public static final String READ_WIFI_CREDENTIAL = "android.permission.READ_WIFI_CREDENTIAL"; + field public static final String READ_WRITE_SYNC_DISABLED_MODE_CONFIG = "android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG"; field public static final String REAL_GET_TASKS = "android.permission.REAL_GET_TASKS"; field public static final String RECEIVE_BLUETOOTH_MAP = "android.permission.RECEIVE_BLUETOOTH_MAP"; field public static final String RECEIVE_DATA_ACTIVITY_CHANGE = "android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index bea2bfc09741..fa5a99e3282a 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -5,6 +5,7 @@ package android { field public static final String ACCESS_NOTIFICATIONS = "android.permission.ACCESS_NOTIFICATIONS"; field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING"; field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY"; + field public static final String ALLOWLISTED_WRITE_DEVICE_CONFIG = "android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG"; field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS"; field public static final String BACKGROUND_CAMERA = "android.permission.BACKGROUND_CAMERA"; field public static final String BIND_CELL_BROADCAST_SERVICE = "android.permission.BIND_CELL_BROADCAST_SERVICE"; @@ -39,6 +40,7 @@ package android { field public static final String QUERY_AUDIO_STATE = "android.permission.QUERY_AUDIO_STATE"; field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS"; field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE"; + field public static final String READ_WRITE_SYNC_DISABLED_MODE_CONFIG = "android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG"; field public static final String RECORD_BACKGROUND_AUDIO = "android.permission.RECORD_BACKGROUND_AUDIO"; field public static final String REMAP_MODIFIER_KEYS = "android.permission.REMAP_MODIFIER_KEYS"; field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS"; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index a4818c7e871f..9d3ef19aab04 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -4187,6 +4187,16 @@ <permission android:name="android.permission.WRITE_DEVICE_CONFIG" android:protectionLevel="signature|verifier|configurator"/> + <!-- @SystemApi @TestApi @hide Allows an application to modify only allowlisted settings. + <p>Not for use by third-party applications. --> + <permission android:name="android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG" + android:protectionLevel="signature|verifier|configurator"/> + + <!-- @SystemApi @TestApi @hide Allows an application to read/write sync disabled mode config. + <p>Not for use by third-party applications. --> + <permission android:name="android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG" + android:protectionLevel="signature|verifier|configurator"/> + <!-- @SystemApi @hide Allows an application to read config settings. <p>Not for use by third-party applications. --> <permission android:name="android.permission.READ_DEVICE_CONFIG" diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 7abace03aa83..104d6e7de9f2 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -1175,7 +1175,7 @@ public class SettingsProvider extends ContentProvider { Slog.v(LOG_TAG, "setAllConfigSettings for prefix: " + prefix); } - enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG); + enforceDeviceConfigWritePermission(getContext(), keyValues.keySet()); final String callingPackage = resolveCallingPackage(); synchronized (mLock) { @@ -1194,7 +1194,8 @@ public class SettingsProvider extends ContentProvider { Slog.v(LOG_TAG, "setSyncDisabledModeConfig(" + syncDisabledMode + ")"); } - enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG); + enforceHasAtLeastOnePermission(Manifest.permission.WRITE_DEVICE_CONFIG, + Manifest.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG); synchronized (mLock) { setSyncDisabledModeConfigLocked(syncDisabledMode); @@ -1206,7 +1207,8 @@ public class SettingsProvider extends ContentProvider { Slog.v(LOG_TAG, "getSyncDisabledModeConfig"); } - enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG); + enforceHasAtLeastOnePermission(Manifest.permission.WRITE_DEVICE_CONFIG, + Manifest.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG); synchronized (mLock) { return getSyncDisabledModeConfigLocked(); @@ -1291,13 +1293,14 @@ public class SettingsProvider extends ContentProvider { private boolean mutateConfigSetting(String name, String value, String prefix, boolean makeDefault, int operation, int mode) { - enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG); final String callingPackage = resolveCallingPackage(); boolean someSettingChanged = false; // Perform the mutation. synchronized (mLock) { switch (operation) { case MUTATION_OPERATION_INSERT: { + enforceDeviceConfigWritePermission(getContext(), Collections.singleton(name)); + someSettingChanged = mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM, name, value, null, makeDefault, true, callingPackage, false, null, @@ -1306,12 +1309,17 @@ public class SettingsProvider extends ContentProvider { } case MUTATION_OPERATION_DELETE: { + enforceDeviceConfigWritePermission(getContext(), Collections.singleton(name)); + someSettingChanged = mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM, name, false, null); break; } case MUTATION_OPERATION_RESET: { + enforceDeviceConfigWritePermission(getContext(), + getAllConfigFlags(prefix).keySet()); + someSettingChanged = mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM, callingPackage, mode, null, prefix); break; @@ -1475,7 +1483,7 @@ public class SettingsProvider extends ContentProvider { boolean makeDefault, int requestingUserId, int operation, boolean forceNotify, int mode, boolean overrideableByRestore) { // Make sure the caller can change the settings - treated as secure. - enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); + enforceHasAtLeastOnePermission(Manifest.permission.WRITE_SECURE_SETTINGS); // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); @@ -1772,7 +1780,7 @@ public class SettingsProvider extends ContentProvider { boolean makeDefault, int requestingUserId, int operation, boolean forceNotify, int mode, boolean overrideableByRestore) { // Make sure the caller can change the settings. - enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); + enforceHasAtLeastOnePermission(Manifest.permission.WRITE_SECURE_SETTINGS); // Resolve the userId on whose behalf the call is made. final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); @@ -2305,11 +2313,57 @@ public class SettingsProvider extends ContentProvider { } } - private void enforceWritePermission(String permission) { - if (getContext().checkCallingOrSelfPermission(permission) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Permission denial: writing to settings requires:" - + permission); + private void enforceHasAtLeastOnePermission(String ...permissions) { + for (String permission : permissions) { + if (getContext().checkCallingOrSelfPermission(permission) + == PackageManager.PERMISSION_GRANTED) { + return; + } + } + throw new SecurityException("Permission denial, must have one of: " + + Arrays.toString(permissions)); + } + + /** + * Throws an exception if write permissions are not granted for {@code flags}. + * <p> + * Write permissions are granted if the calling UID is root, or the + * WRITE_DEVICE_CONFIG permission is granted, or the WRITE_DEVICE_CONFIG_ALLOWLIST + * permission is granted and each flag in {@code flags} is allowlisted in {@code + * WRITABLE_FLAG_ALLOWLIST_FLAG}. + * + * @param context the {@link Context} this is called in + * @param flags a list of flags to check, each one of the form 'namespace/flagName' + * + * @throws SecurityException if the above criteria are not met. + * @hide + */ + private void enforceDeviceConfigWritePermission( + @NonNull Context context, + @NonNull Set<String> flags) { + boolean hasAllowlistPermission = + context.checkCallingOrSelfPermission( + Manifest.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG) + == PackageManager.PERMISSION_GRANTED; + boolean hasWritePermission = + context.checkCallingOrSelfPermission( + Manifest.permission.WRITE_DEVICE_CONFIG) + == PackageManager.PERMISSION_GRANTED; + boolean isRoot = Binder.getCallingUid() == Process.ROOT_UID; + + if (isRoot || hasWritePermission) { + return; + } else if (hasAllowlistPermission) { + for (String flag : flags) { + if (!DeviceConfig.getAdbWritableFlags().contains(flag)) { + throw new SecurityException("Permission denial for flag '" + + flag + + "'; allowlist permission granted, but must add flag to the allowlist."); + } + } + } else { + throw new SecurityException("Permission denial to mutate flag, must have root, " + + "WRITE_DEVICE_CONFIG, or ALLOWLISTED_WRITE_DEVICE_CONFIG"); } } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 0664061401f3..1a8fc0d4d7b4 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -147,7 +147,8 @@ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <uses-permission android:name="android.permission.LOCATION_BYPASS" /> <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> - <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" /> + <uses-permission android:name="android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG" /> + <uses-permission android:name="android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG" /> <uses-permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS" /> <uses-permission android:name="android.permission.BROADCAST_STICKY" /> <uses-permission android:name="android.permission.MANAGE_ACCESSIBILITY" /> diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 687696a03627..a991840f6f00 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -401,7 +401,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Shell permisssions will override permissions of our app, so add all necessary permissions // for this test here: InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity( - "android.permission.WRITE_DEVICE_CONFIG", + "android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG", "android.permission.READ_CONTACTS"); diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java index f8d885ae3faf..0e5d79977b8c 100644 --- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java @@ -124,11 +124,12 @@ public class PackageWatchdogTest { @Before public void setUp() throws Exception { + mAllocatedWatchdogs = new ArrayList<>(); MockitoAnnotations.initMocks(this); new File(InstrumentationRegistry.getContext().getFilesDir(), "package-watchdog.xml").delete(); adoptShellPermissions(Manifest.permission.READ_DEVICE_CONFIG, - Manifest.permission.WRITE_DEVICE_CONFIG); + Manifest.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG); mTestLooper = new TestLooper(); mSpyContext = spy(InstrumentationRegistry.getContext()); when(mSpyContext.getPackageManager()).thenReturn(mMockPackageManager); @@ -182,7 +183,6 @@ public class PackageWatchdogTest { PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT, Integer.toString(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT), false); - mAllocatedWatchdogs = new ArrayList<>(); } @After diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/NetworkStagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/NetworkStagedRollbackTest.java index 314e95229d29..7600a75ad78f 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/NetworkStagedRollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/NetworkStagedRollbackTest.java @@ -82,7 +82,7 @@ public class NetworkStagedRollbackTest { Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, Manifest.permission.FORCE_STOP_PACKAGES, - Manifest.permission.WRITE_DEVICE_CONFIG); + Manifest.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG); } /** diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java index 4cddcfeb91dc..115870f95563 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java @@ -70,7 +70,7 @@ public class StagedRollbackTest { Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, Manifest.permission.FORCE_STOP_PACKAGES, - Manifest.permission.WRITE_DEVICE_CONFIG); + Manifest.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG); } /** |