From c72875b01e04a12fa25bbc5468cf87f8bf11fcfa Mon Sep 17 00:00:00 2001 From: Chad Brubaker Date: Wed, 27 Apr 2016 16:35:11 -0700 Subject: [PATCH] Update trusted certificates when the trust store is changed This CL flushes the trusted cert cache of all active Network Security Configs and their TrustManagers. Previously CA addition mostly worked however removed CAs would remain cached in the X509TrustManager causing the removed CA to still be trusted. Change-Id: I0f5fd39932f8f8ed3ec5dfd088a82e982b366c43 --- api/test-current.txt | 1 - core/java/android/app/ActivityThread.java | 6 +++++ .../android/app/ApplicationThreadNative.java | 14 ++++++++++++ core/java/android/app/IApplicationThread.java | 2 ++ .../security/NetworkSecurityPolicy.java | 6 +++-- .../net/config/ApplicationConfig.java | 22 ++++++++++++------- .../server/am/ActivityManagerService.java | 20 +++++++++++++++++ 7 files changed, 60 insertions(+), 11 deletions(-) diff --git a/api/test-current.txt b/api/test-current.txt index 2ebe4907af23b..62e9e37ac6fd5 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -34406,7 +34406,6 @@ package android.security { public class NetworkSecurityPolicy { method public static android.security.NetworkSecurityPolicy getInstance(); - method public void handleTrustStorageUpdate(); method public boolean isCleartextTrafficPermitted(); method public boolean isCleartextTrafficPermitted(java.lang.String); } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index cd9474044ff63..18a5d64206ab3 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -81,6 +81,7 @@ import android.os.Trace; import android.os.TransactionTooLargeException; import android.os.UserHandle; import android.provider.Settings; +import android.security.NetworkSecurityPolicy; import android.security.net.config.NetworkSecurityConfigProvider; import android.util.AndroidRuntimeException; import android.util.ArrayMap; @@ -1324,6 +1325,11 @@ public final class ActivityThread { args.arg2 = voiceInteractor; sendMessage(H.LOCAL_VOICE_INTERACTION_STARTED, args); } + + @Override + public void handleTrustStorageUpdate() { + NetworkSecurityPolicy.getInstance().handleTrustStorageUpdate(); + } } private int getLifecycleSeq() { diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index d6da3f44f4a00..3063d98c27a3c 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -749,6 +749,12 @@ public abstract class ApplicationThreadNative extends Binder schedulePictureInPictureModeChanged(b, inPip); return true; } + case HANDLE_TRUST_STORAGE_UPDATE_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + handleTrustStorageUpdate(); + return true; + } } @@ -1522,4 +1528,12 @@ class ApplicationThreadProxy implements IApplicationThread { IBinder.FLAG_ONEWAY); data.recycle(); } + + @Override + public void handleTrustStorageUpdate() throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + mRemote.transact(HANDLE_TRUST_STORAGE_UPDATE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + data.recycle(); + } } diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 559f69fc2aec1..7732157c2c814 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -161,6 +161,7 @@ public interface IApplicationThread extends IInterface { void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode) throws RemoteException; void schedulePictureInPictureModeChanged(IBinder token, boolean isInPictureInPictureMode) throws RemoteException; void scheduleLocalVoiceInteractionStarted(IBinder token, IVoiceInteractor voiceInteractor) throws RemoteException; + void handleTrustStorageUpdate() throws RemoteException; String descriptor = "android.app.IApplicationThread"; @@ -224,4 +225,5 @@ public interface IApplicationThread extends IInterface { int SCHEDULE_MULTI_WINDOW_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58; int SCHEDULE_PICTURE_IN_PICTURE_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59; int SCHEDULE_LOCAL_VOICE_INTERACTION_STARTED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+60; + int HANDLE_TRUST_STORAGE_UPDATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+61; } diff --git a/core/java/android/security/NetworkSecurityPolicy.java b/core/java/android/security/NetworkSecurityPolicy.java index 1b1c30048ee76..812c956f4c617 100644 --- a/core/java/android/security/NetworkSecurityPolicy.java +++ b/core/java/android/security/NetworkSecurityPolicy.java @@ -97,9 +97,11 @@ public class NetworkSecurityPolicy { * Handle an update to the system or user certificate stores. * @hide */ - @TestApi public void handleTrustStorageUpdate() { - ApplicationConfig.getDefaultInstance().handleTrustStorageUpdate(); + ApplicationConfig config = ApplicationConfig.getDefaultInstance(); + if (config != null) { + config.handleTrustStorageUpdate(); + } } /** diff --git a/core/java/android/security/net/config/ApplicationConfig.java b/core/java/android/security/net/config/ApplicationConfig.java index fadea5682cdb8..801ecebc616f1 100644 --- a/core/java/android/security/net/config/ApplicationConfig.java +++ b/core/java/android/security/net/config/ApplicationConfig.java @@ -148,14 +148,20 @@ public final class ApplicationConfig { } public void handleTrustStorageUpdate() { - ensureInitialized(); - mDefaultConfig.handleTrustStorageUpdate(); - if (mConfigs != null) { - Set updatedConfigs = - new HashSet(mConfigs.size()); - for (Pair entry : mConfigs) { - if (updatedConfigs.add(entry.second)) { - entry.second.handleTrustStorageUpdate(); + synchronized(mLock) { + // If the config is uninitialized then there is no work to be done to handle an update, + // avoid needlessly parsing configs. + if (!mInitialized) { + return; + } + mDefaultConfig.handleTrustStorageUpdate(); + if (mConfigs != null) { + Set updatedConfigs = + new HashSet(mConfigs.size()); + for (Pair entry : mConfigs) { + if (updatedConfigs.add(entry.second)) { + entry.second.handleTrustStorageUpdate(); + } } } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index b6982cde3833b..3ffc9f47764b4 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -286,6 +286,7 @@ import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL; import static android.provider.Settings.Global.LENIENT_BACKGROUND_CHECK; import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER; import static android.provider.Settings.System.FONT_SCALE; +import static android.security.KeyChain.ACTION_TRUST_STORE_CHANGED; import static com.android.internal.util.XmlUtils.readBooleanAttribute; import static com.android.internal.util.XmlUtils.readIntAttribute; import static com.android.internal.util.XmlUtils.readLongAttribute; @@ -1522,6 +1523,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 68; static final int VR_MODE_APPLY_IF_NEEDED_MSG = 69; static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 70; + static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 71; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -2322,6 +2324,21 @@ public final class ActivityManagerService extends ActivityManagerNative r.info.getComponentName(), false); } } break; + case HANDLE_TRUST_STORAGE_UPDATE_MSG: { + synchronized (ActivityManagerService.this) { + for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { + ProcessRecord r = mLruProcesses.get(i); + if (r.thread != null) { + try { + r.thread.handleTrustStorageUpdate(); + } catch (RemoteException ex) { + Slog.w(TAG, "Failed to handle trust storage update for: " + + r.info.processName); + } + } + } + } + } break; } } }; @@ -17959,6 +17976,9 @@ public final class ActivityManagerService extends ActivityManagerNative } // Lie; we don't want to crash the app. return ActivityManager.BROADCAST_SUCCESS; + case android.security.KeyChain.ACTION_TRUST_STORE_CHANGED: + mHandler.sendEmptyMessage(HANDLE_TRUST_STORAGE_UPDATE_MSG); + break; } }