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

Commit 346acb12 authored by Christopher Tate's avatar Christopher Tate
Browse files

Sanity-check erroneous backup agent instantiations

Two distinct changes:

Fix a bug seen in the wild where a newly-launched application will be
spuriously asked to instantiate a backup agent.  What was happening
there is that some Activity Manager state was being left stale in certain
circumstances, and then in combination with app uninstall / install, there
could be a case where uid reuse wound up looking like an app identity
match.

We now positively verify before instantiating the agent that the intended
backup target package is uid-compatible with the app process that the
instantiation was requested of.  The incomplete bookkeeping in the
Activity Manager has also been tightened up, and the Backup Manager is
more aggressive about cleaning up pending operations pertaining to
apps being uninstalled.

Bug 5874010

Change-Id: Ic389f4a96c9dcd0ba6b3962b579084033d8ae9f8
parent 69b0c974
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -2809,6 +2809,15 @@ class ActivityManagerProxy implements IActivityManager
        return success;
    }

    public void clearPendingBackup() throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        mRemote.transact(CLEAR_PENDING_BACKUP_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }

    public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
+20 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ProviderInfo;
@@ -2396,12 +2397,31 @@ public final class ActivityThread {
    private void handleCreateBackupAgent(CreateBackupAgentData data) {
        if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);

        // Sanity check the requested target package's uid against ours
        try {
            PackageInfo requestedPackage = getPackageManager().getPackageInfo(
                    data.appInfo.packageName, 0, UserHandle.myUserId());
            if (requestedPackage.applicationInfo.uid != Process.myUid()) {
                Slog.w(TAG, "Asked to instantiate non-matching package "
                        + data.appInfo.packageName);
                return;
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Can't reach package manager", e);
            return;
        }

        // no longer idle; we have backup work to do
        unscheduleGcIdler();

        // instantiate the BackupAgent class named in the manifest
        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
        String packageName = packageInfo.mPackageName;
        if (packageName == null) {
            Slog.d(TAG, "Asked to create backup agent for nonexistent package");
            return;
        }

        if (mBackupAgents.get(packageName) != null) {
            Slog.d(TAG, "BackupAgent " + "  for " + packageName
                    + " already exists");
+2 −0
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ public interface IActivityManager extends IInterface {
    
    public boolean bindBackupAgent(ApplicationInfo appInfo, int backupRestoreMode)
            throws RemoteException;
    public void clearPendingBackup() throws RemoteException;
    public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException;
    public void unbindBackupAgent(ApplicationInfo appInfo) throws RemoteException;
    public void killApplicationProcess(String processName, int uid) throws RemoteException;
@@ -619,4 +620,5 @@ public interface IActivityManager extends IInterface {
    int GET_RUNNING_USER_IDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+156;
    int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157;
    int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158;
    int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159;
}
+3 −0
Original line number Diff line number Diff line
@@ -1474,6 +1474,7 @@ class BackupManagerService extends IBackupManager.Stub {
            if (MORE_DEBUG) Slog.v(TAG, "  removing participant " + packageName);
            removeEverBackedUp(packageName);
            set.remove(packageName);
            mPendingBackups.remove(packageName);
        }
    }

@@ -1625,6 +1626,7 @@ class BackupManagerService extends IBackupManager.Stub {
                        } catch (InterruptedException e) {
                            // just bail
                            if (DEBUG) Slog.w(TAG, "Interrupted: " + e);
                            mActivityManager.clearPendingBackup();
                            return null;
                        }
                    }
@@ -1632,6 +1634,7 @@ class BackupManagerService extends IBackupManager.Stub {
                    // if we timed out with no connect, abort and move on
                    if (mConnecting == true) {
                        Slog.w(TAG, "Timeout waiting for agent " + app);
                        mActivityManager.clearPendingBackup();
                        return null;
                    }
                    if (DEBUG) Slog.i(TAG, "got agent " + mConnectedAgent);
+37 −24
Original line number Diff line number Diff line
@@ -11119,8 +11119,8 @@ public final class ActivityManagerService extends ActivityManagerNative
    // instantiated.  The backup agent will invoke backupAgentCreated() on the
    // activity manager to announce its creation.
    public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
        if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
        enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
        if (DEBUG_BACKUP) Slog.v(TAG, "bindBackupAgent: app=" + app + " mode=" + backupMode);
        enforceCallingPermission("android.permission.BACKUP", "bindBackupAgent");
        synchronized(this) {
            // !!! TODO: currently no check here that we're already bound
@@ -11181,6 +11181,17 @@ public final class ActivityManagerService extends ActivityManagerNative
        return true;
    }
    @Override
    public void clearPendingBackup() {
        if (DEBUG_BACKUP) Slog.v(TAG, "clearPendingBackup");
        enforceCallingPermission("android.permission.BACKUP", "clearPendingBackup");
        synchronized (this) {
            mBackupTarget = null;
            mBackupAppName = null;
        }
    }
    // A backup agent has just come up                    
    public void backupAgentCreated(String agentPackageName, IBinder agent) {
        if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
@@ -11217,6 +11228,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        synchronized(this) {
            try {
                if (mBackupAppName == null) {
                    Slog.w(TAG, "Unbinding backup agent with no active backup");
                    return;
@@ -11227,11 +11239,8 @@ public final class ActivityManagerService extends ActivityManagerNative
                    return;
                }
            ProcessRecord proc = mBackupTarget.app;
            mBackupTarget = null;
            mBackupAppName = null;
                // Not backing this app up any more; reset its OOM adjustment
                final ProcessRecord proc = mBackupTarget.app;
                updateOomAdjLocked(proc);
                // If the app crashed during backup, 'thread' will be null here
@@ -11244,6 +11253,10 @@ public final class ActivityManagerService extends ActivityManagerNative
                        e.printStackTrace();
                    }
                }
            } finally {
                mBackupTarget = null;
                mBackupAppName = null;
            }
        }
    }
    // =========================================================