diff options
| author | Chalard Jean <jchalard@google.com> | 2021-07-07 17:13:57 +0900 |
|---|---|---|
| committer | Chalard Jean <jchalard@google.com> | 2021-07-29 13:18:54 +0900 |
| commit | 249be21013e389837f5b2beb7d36890b25ecfaaf (patch) | |
| tree | 24e60e1da38b860d8baaad8efc12c2e15eae3e69 /core/java/android | |
| parent | 9f6b05e6fbf31ec26296f7e506ef0a38ec289038 (diff) | |
Fix: ConnectivityManager methods crashing with SecurityException
Starting in R, some methods in ConnectivityManager like
getNetworkCapabilities started passing the package name from
the context stored in CM to check that the package is really
whom it pretends to be. Unfortunately, in some cases, the
context contains package "android" for an app, and since the
app is not the system, the check fails and crashes the app.
It seems the culprit is updateHttpProxy, which is called by
ProcessList when the PROXY_CHANGE_ACTION broadcast is sent.
If this happens to run between the time the process is created
and the activity thread is "bound", then the mInitialApplication
member is not set, and updateHttpProxy uses a system context.
Since ConnectivityManager caches the context forever in a
static, this leads to subsequent legitimate calls crashing.
Setting the proxy can be deffered until such a time that the
app is bound, as it can't run any code before then. The member
is never reset to null, so it's guaranteed to be non-null at
bind time.
An alternative would be to post a runnable on the handler
thread if the member is null to try again later. This
could however run the lambda a considerable number of times
as binding can be delayed, and risks causing an infinite loop
if some invariants are changed in the future.
See also b/73572062 and ag/4056059
Bug: 155549446
Bug: 189360509
Test: ActivityThreadTest FrameworksNetTests NetworkStackTests
Test: Manually set a proxy, observe the broadcast being sent and
apps not crashing
Change-Id: I956f76be2e0a1a675576511fb394d7ed4354b28a
Merged-In: I956f76be2e0a1a675576511fb394d7ed4354b28a
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 193f7754f974..41170a4c2749 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -352,11 +352,12 @@ public final class ActivityThread extends ClientTransactionHandler { @UnsupportedAppUsage Configuration mConfiguration; Configuration mCompatConfiguration; + @GuardedBy("this") + private boolean mUpdateHttpProxyOnBind = false; @UnsupportedAppUsage Application mInitialApplication; @UnsupportedAppUsage - final ArrayList<Application> mAllApplications - = new ArrayList<Application>(); + final ArrayList<Application> mAllApplications = new ArrayList<>(); /** * Bookkeeping of instantiated backup agents indexed first by user id, then by package name. * Indexing by user id supports parallel backups across users on system packages as they run in @@ -1127,8 +1128,18 @@ public final class ActivityThread extends ClientTransactionHandler { } public void updateHttpProxy() { - ActivityThread.updateHttpProxy( - getApplication() != null ? getApplication() : getSystemContext()); + final Application app; + synchronized (ActivityThread.this) { + app = getApplication(); + if (null == app) { + // The app is not bound yet. Make a note to update the HTTP proxy when the + // app is bound. + mUpdateHttpProxyOnBind = true; + return; + } + } + // App is present, update the proxy inline. + ActivityThread.updateHttpProxy(app); } public void processInBackground() { @@ -6697,6 +6708,15 @@ public final class ActivityThread extends ClientTransactionHandler { app.setContentCaptureOptions(data.contentCaptureOptions); mInitialApplication = app; + final boolean updateHttpProxy; + synchronized (this) { + updateHttpProxy = mUpdateHttpProxyOnBind; + // This synchronized block ensures that any subsequent call to updateHttpProxy() + // will see a non-null mInitialApplication. + } + if (updateHttpProxy) { + ActivityThread.updateHttpProxy(app); + } // don't bring up providers in restricted mode; they may depend on the // app's custom Application class |
