Loading core/java/android/net/Uri.java +5 −1 Original line number Diff line number Diff line Loading @@ -1391,7 +1391,11 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { * @param scheme name or {@code null} if this is a relative Uri */ public Builder scheme(String scheme) { this.scheme = scheme; if (scheme != null) { this.scheme = scheme.replace("://", ""); } else { this.scheme = null; } return this; } Loading core/tests/coretests/src/android/net/UriTest.java +11 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.net; import android.content.ContentUris; import android.os.Parcel; import android.platform.test.annotations.AsbSecurityTest; import androidx.test.filters.SmallTest; Loading Loading @@ -88,6 +89,16 @@ public class UriTest extends TestCase { assertNull(u.getHost()); } @AsbSecurityTest(cveBugId = 261721900) @SmallTest public void testSchemeSanitization() { Uri uri = new Uri.Builder() .scheme("http://https://evil.com:/te:st/") .authority("google.com").path("one/way").build(); assertEquals("httphttpsevil.com:/te:st/", uri.getScheme()); assertEquals("httphttpsevil.com:/te:st/://google.com/one/way", uri.toString()); } @SmallTest public void testStringUri() { assertEquals("bob lee", Loading keystore/java/android/security/AndroidKeyStoreMaintenance.java +22 −0 Original line number Diff line number Diff line Loading @@ -18,8 +18,10 @@ package android.security; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.StrictMode; import android.security.maintenance.IKeystoreMaintenance; import android.system.keystore2.Domain; import android.system.keystore2.KeyDescriptor; Loading Loading @@ -183,4 +185,24 @@ public class AndroidKeyStoreMaintenance { return SYSTEM_ERROR; } } /** * Deletes all keys in all KeyMint devices. * Called by RecoverySystem before rebooting to recovery in order to delete all KeyMint keys, * including synthetic password protector keys (used by LockSettingsService), as well as keys * protecting DE and metadata encryption keys (used by vold). This ensures that FBE-encrypted * data is unrecoverable even if the data wipe in recovery is interrupted or skipped. */ public static void deleteAllKeys() throws KeyStoreException { StrictMode.noteDiskWrite(); try { getService().deleteAllKeys(); } catch (RemoteException | NullPointerException e) { throw new KeyStoreException(SYSTEM_ERROR, "Failure to connect to Keystore while trying to delete all keys."); } catch (ServiceSpecificException e) { throw new KeyStoreException(e.errorCode, "Keystore error while trying to delete all keys."); } } } services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +19 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.os.ShellCallback; import android.os.SystemProperties; import android.provider.DeviceConfig; import android.sysprop.ApexProperties; import android.security.AndroidKeyStoreMaintenance; import android.util.ArrayMap; import android.util.ArraySet; import android.util.FastImmutableArraySet; Loading @@ -66,6 +67,7 @@ import com.android.internal.widget.RebootEscrowListener; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.ApexManager; import com.android.server.utils.Slogf; import libcore.io.IoUtils; Loading Loading @@ -117,6 +119,8 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo static final String LSKF_CAPTURED_TIMESTAMP_PREF = "lskf_captured_timestamp"; static final String LSKF_CAPTURED_COUNT_PREF = "lskf_captured_count"; static final String RECOVERY_WIPE_DATA_COMMAND = "--wipe_data"; private final Injector mInjector; private final Context mContext; Loading Loading @@ -511,17 +515,32 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo @Override // Binder call public void rebootRecoveryWithCommand(String command) { if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]"); boolean isForcedWipe = command != null && command.contains(RECOVERY_WIPE_DATA_COMMAND); synchronized (sRequestLock) { if (!setupOrClearBcb(true, command)) { return; } if (isForcedWipe) { deleteSecrets(); } // Having set up the BCB, go ahead and reboot. PowerManager pm = mInjector.getPowerManager(); pm.reboot(PowerManager.REBOOT_RECOVERY); } } private static void deleteSecrets() { Slogf.w(TAG, "deleteSecrets"); try { AndroidKeyStoreMaintenance.deleteAllKeys(); } catch (android.security.KeyStoreException e) { Log.wtf(TAG, "Failed to delete all keys from keystore.", e); } } private void enforcePermissionForResumeOnReboot() { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.RECOVERY) != PackageManager.PERMISSION_GRANTED Loading Loading
core/java/android/net/Uri.java +5 −1 Original line number Diff line number Diff line Loading @@ -1391,7 +1391,11 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { * @param scheme name or {@code null} if this is a relative Uri */ public Builder scheme(String scheme) { this.scheme = scheme; if (scheme != null) { this.scheme = scheme.replace("://", ""); } else { this.scheme = null; } return this; } Loading
core/tests/coretests/src/android/net/UriTest.java +11 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.net; import android.content.ContentUris; import android.os.Parcel; import android.platform.test.annotations.AsbSecurityTest; import androidx.test.filters.SmallTest; Loading Loading @@ -88,6 +89,16 @@ public class UriTest extends TestCase { assertNull(u.getHost()); } @AsbSecurityTest(cveBugId = 261721900) @SmallTest public void testSchemeSanitization() { Uri uri = new Uri.Builder() .scheme("http://https://evil.com:/te:st/") .authority("google.com").path("one/way").build(); assertEquals("httphttpsevil.com:/te:st/", uri.getScheme()); assertEquals("httphttpsevil.com:/te:st/://google.com/one/way", uri.toString()); } @SmallTest public void testStringUri() { assertEquals("bob lee", Loading
keystore/java/android/security/AndroidKeyStoreMaintenance.java +22 −0 Original line number Diff line number Diff line Loading @@ -18,8 +18,10 @@ package android.security; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.StrictMode; import android.security.maintenance.IKeystoreMaintenance; import android.system.keystore2.Domain; import android.system.keystore2.KeyDescriptor; Loading Loading @@ -183,4 +185,24 @@ public class AndroidKeyStoreMaintenance { return SYSTEM_ERROR; } } /** * Deletes all keys in all KeyMint devices. * Called by RecoverySystem before rebooting to recovery in order to delete all KeyMint keys, * including synthetic password protector keys (used by LockSettingsService), as well as keys * protecting DE and metadata encryption keys (used by vold). This ensures that FBE-encrypted * data is unrecoverable even if the data wipe in recovery is interrupted or skipped. */ public static void deleteAllKeys() throws KeyStoreException { StrictMode.noteDiskWrite(); try { getService().deleteAllKeys(); } catch (RemoteException | NullPointerException e) { throw new KeyStoreException(SYSTEM_ERROR, "Failure to connect to Keystore while trying to delete all keys."); } catch (ServiceSpecificException e) { throw new KeyStoreException(e.errorCode, "Keystore error while trying to delete all keys."); } } }
services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +19 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.os.ShellCallback; import android.os.SystemProperties; import android.provider.DeviceConfig; import android.sysprop.ApexProperties; import android.security.AndroidKeyStoreMaintenance; import android.util.ArrayMap; import android.util.ArraySet; import android.util.FastImmutableArraySet; Loading @@ -66,6 +67,7 @@ import com.android.internal.widget.RebootEscrowListener; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.ApexManager; import com.android.server.utils.Slogf; import libcore.io.IoUtils; Loading Loading @@ -117,6 +119,8 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo static final String LSKF_CAPTURED_TIMESTAMP_PREF = "lskf_captured_timestamp"; static final String LSKF_CAPTURED_COUNT_PREF = "lskf_captured_count"; static final String RECOVERY_WIPE_DATA_COMMAND = "--wipe_data"; private final Injector mInjector; private final Context mContext; Loading Loading @@ -511,17 +515,32 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo @Override // Binder call public void rebootRecoveryWithCommand(String command) { if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]"); boolean isForcedWipe = command != null && command.contains(RECOVERY_WIPE_DATA_COMMAND); synchronized (sRequestLock) { if (!setupOrClearBcb(true, command)) { return; } if (isForcedWipe) { deleteSecrets(); } // Having set up the BCB, go ahead and reboot. PowerManager pm = mInjector.getPowerManager(); pm.reboot(PowerManager.REBOOT_RECOVERY); } } private static void deleteSecrets() { Slogf.w(TAG, "deleteSecrets"); try { AndroidKeyStoreMaintenance.deleteAllKeys(); } catch (android.security.KeyStoreException e) { Log.wtf(TAG, "Failed to delete all keys from keystore.", e); } } private void enforcePermissionForResumeOnReboot() { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.RECOVERY) != PackageManager.PERMISSION_GRANTED Loading