From a7e87acb2416d4212c84fb9c45353dbf6ee15e6a Mon Sep 17 00:00:00 2001 From: Paul Crowley Date: Tue, 18 Nov 2014 13:50:19 +0000 Subject: [PATCH] Add flag for wiping factory reset protection data. Bug: 18366448 Change-Id: If8904888a6bf8611d34647e6d65d2347d824dbb3 --- api/current.txt | 1 + .../app/admin/DevicePolicyManager.java | 20 ++++++--- .../DevicePolicyManagerService.java | 42 +++++++++++-------- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/api/current.txt b/api/current.txt index 27b107a6a1241..707ddab4d49be 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5441,6 +5441,7 @@ package android.app.admin { field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1 + field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index d00cbb7c5138c..0e1c85c4cb2d1 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1473,22 +1473,30 @@ public class DevicePolicyManager { /** * Flag for {@link #wipeData(int)}: also erase the device's external - * storage. + * storage (such as SD cards). */ public static final int WIPE_EXTERNAL_STORAGE = 0x0001; + /** + * Flag for {@link #wipeData(int)}: also erase the factory reset protection + * data. + * + * This flag may only be set by device owner admins; if it is set by other + * admins a {@link SecurityException} will be thrown. + */ + public static final int WIPE_RESET_PROTECTION_DATA = 0x0002; + /** * Ask the user data be wiped. This will cause the device to reboot, - * erasing all user data while next booting up. External storage such - * as SD cards will be also erased if the flag {@link #WIPE_EXTERNAL_STORAGE} - * is set. + * erasing all user data while next booting up. * *

The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} to be able to call * this method; if it has not, a security exception will be thrown. * - * @param flags Bit mask of additional options: currently 0 and - * {@link #WIPE_EXTERNAL_STORAGE} are supported. + * @param flags Bit mask of additional options: currently supported flags + * are {@link #WIPE_EXTERNAL_STORAGE} and + * {@link #WIPE_RESET_PROTECTION_DATA}. */ public void wipeData(int flags) { if (mService != null) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 6331dfe6e36d7..21b7b8b27bdf7 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -17,6 +17,8 @@ package com.android.server.devicepolicy; import static android.Manifest.permission.MANAGE_CA_CERTIFICATES; +import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE; +import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA; import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES; import android.accessibilityservice.AccessibilityServiceInfo; @@ -78,6 +80,7 @@ import android.security.IKeyChainService; import android.security.KeyChain; import android.security.KeyChain.KeyChainConnection; import android.text.TextUtils; +import android.service.persistentdata.PersistentDataBlockManager; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Printer; @@ -2925,10 +2928,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return false; } - void wipeDataLocked(int flags, String reason) { + private void wipeDataLocked(boolean wipeExtRequested, String reason) { // If the SD card is encrypted and non-removable, we have to force a wipe. boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted(); - boolean wipeExtRequested = (flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0; // Note: we can only do the wipe via ExternalStorageFormatter if the volume is not emulated. if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) { @@ -2941,9 +2943,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else { try { RecoverySystem.rebootWipeUserData(mContext, reason); - } catch (IOException e) { - Slog.w(LOG_TAG, "Failed requesting data wipe", e); - } catch (SecurityException e) { + } catch (IOException | SecurityException e) { Slog.w(LOG_TAG, "Failed requesting data wipe", e); } } @@ -2962,20 +2962,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DeviceAdminInfo.USES_POLICY_WIPE_DATA); final String source; - if (admin != null && admin.info != null) { - final ComponentName cname = admin.info.getComponent(); - if (cname != null) { - source = cname.flattenToShortString(); - } else { - source = admin.info.getPackageName(); - } + final ComponentName cname = admin.info.getComponent(); + if (cname != null) { + source = cname.flattenToShortString(); } else { - source = "?"; + source = admin.info.getPackageName(); } long ident = Binder.clearCallingIdentity(); try { - wipeDeviceOrUserLocked(flags, userHandle, + if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) { + if (userHandle != UserHandle.USER_OWNER + || !isDeviceOwner(admin.info.getPackageName())) { + throw new SecurityException( + "Only device owner admins can set WIPE_RESET_PROTECTION_DATA"); + } + PersistentDataBlockManager manager = (PersistentDataBlockManager) + mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE); + manager.wipe(); + } + boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0; + wipeDeviceOrUserLocked(wipeExtRequested, userHandle, "DevicePolicyManager.wipeData() from " + source); } finally { Binder.restoreCallingIdentity(ident); @@ -2983,9 +2990,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - private void wipeDeviceOrUserLocked(int flags, final int userHandle, String reason) { + private void wipeDeviceOrUserLocked(boolean wipeExtRequested, final int userHandle, String reason) { if (userHandle == UserHandle.USER_OWNER) { - wipeDataLocked(flags, reason); + wipeDataLocked(wipeExtRequested, reason); } else { mHandler.post(new Runnable() { public void run() { @@ -3137,7 +3144,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } if (wipeData) { // Call without holding lock. - wipeDeviceOrUserLocked(0, identifier, "reportFailedPasswordAttempt()"); + wipeDeviceOrUserLocked(false, identifier, + "reportFailedPasswordAttempt()"); } } finally { Binder.restoreCallingIdentity(ident);