Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d90d6457 authored by Chalard Jean's avatar Chalard Jean
Browse files

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
(cherry picked from commit b0d13e29515d5b7c82daed7533b78ac57e46bd93)
parent 9eee7d3f
Loading
Loading
Loading
Loading
+24 −4
Original line number Diff line number Diff line
@@ -369,11 +369,12 @@ public final class ActivityThread extends ClientTransactionHandler
    @UnsupportedAppUsage(trackingBug = 176961850, maxTargetSdk = Build.VERSION_CODES.R,
            publicAlternatives = "Use {@code Context#getResources()#getConfiguration()} instead.")
    Configuration mConfiguration;
    @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
@@ -1187,8 +1188,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() {
@@ -6685,6 +6696,15 @@ public final class ActivityThread extends ClientTransactionHandler
            sendMessage(H.SET_CONTENT_CAPTURE_OPTIONS_CALLBACK, data.appInfo.packageName);

            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