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

Commit e5029e61 authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Enforce REQUEST_DELETE_PACKAGES for intent uninstall.

Test: Uninstalled app from launcher and settings
Bug: 64576642
Change-Id: I2b78fae9065e97d51a13c5e9eea56c3d94565784
parent 10f770c6
Loading
Loading
Loading
Loading
+3 −17
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.packageinstaller;

import static com.android.packageinstaller.PackageUtil.getMaxTargetSdkVersionForUid;

import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
@@ -73,7 +75,7 @@ public class InstallStart extends Activity {
        }

        if (!isTrustedSource && originatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) {
            final int targetSdkVersion = getMaxTargetSdkVersionForUid(originatingUid);
            final int targetSdkVersion = getMaxTargetSdkVersionForUid(this, originatingUid);
            if (targetSdkVersion < 0) {
                Log.w(LOG_TAG, "Cannot get target sdk version for uid " + originatingUid);
                // Invalid originating uid supplied. Abort install.
@@ -149,22 +151,6 @@ public class InstallStart extends Activity {
        return false;
    }

    private int getMaxTargetSdkVersionForUid(int uid) {
        final String[] packages = getPackageManager().getPackagesForUid(uid);
        int targetSdkVersion = -1;
        if (packages != null) {
            for (String packageName : packages) {
                try {
                    ApplicationInfo info = getPackageManager().getApplicationInfo(packageName, 0);
                    targetSdkVersion = Math.max(targetSdkVersion, info.targetSdkVersion);
                } catch (PackageManager.NameNotFoundException e) {
                    // Ignore and try the next package
                }
            }
        }
        return targetSdkVersion;
    }

    /**
     * @return the ApplicationInfo for the installation source (the calling package), if available
     */
+25 −0
Original line number Diff line number Diff line
@@ -182,4 +182,29 @@ public class PackageUtil {
        }
        return new PackageUtil.AppSnippet(label, icon);
    }

    /**
     * Get the maximum target sdk for a UID.
     *
     * @param context The context to use
     * @param uid The UID requesting the install/uninstall
     *
     * @return The maximum target SDK or -1 if the uid does not match any packages.
     */
    static int getMaxTargetSdkVersionForUid(@NonNull Context context, int uid) {
        PackageManager pm = context.getPackageManager();
        final String[] packages = pm.getPackagesForUid(uid);
        int targetSdkVersion = -1;
        if (packages != null) {
            for (String packageName : packages) {
                try {
                    ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
                    targetSdkVersion = Math.max(targetSdkVersion, info.targetSdkVersion);
                } catch (PackageManager.NameNotFoundException e) {
                    // Ignore and try the next package
                }
            }
        }
        return targetSdkVersion;
    }
}
+34 −0
Original line number Diff line number Diff line
@@ -16,8 +16,13 @@
*/
package com.android.packageinstaller;

import static com.android.packageinstaller.PackageUtil.getMaxTargetSdkVersionForUid;

import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentTransaction;
@@ -37,6 +42,7 @@ import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
@@ -79,6 +85,34 @@ public class UninstallerActivity extends Activity {
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        try {
            int callingUid = ActivityManager.getService().getLaunchedFromUid(getActivityToken());

            if (getMaxTargetSdkVersionForUid(this, callingUid)
                    >= Build.VERSION_CODES.P && AppGlobals.getPackageManager().checkUidPermission(
                    Manifest.permission.REQUEST_DELETE_PACKAGES, callingUid)
                    != PackageManager.PERMISSION_GRANTED
                    && AppGlobals.getPackageManager().checkUidPermission(
                            Manifest.permission.DELETE_PACKAGES, callingUid)
                            != PackageManager.PERMISSION_GRANTED) {
                Log.e(TAG, "Uid " + callingUid + " does not have "
                        + Manifest.permission.REQUEST_DELETE_PACKAGES + " or "
                        + Manifest.permission.DELETE_PACKAGES);

                setResult(Activity.RESULT_FIRST_USER);
                finish();
                return;
            }
        } catch (RemoteException ex) {
            // Cannot reach Package/ActivityManager. Aborting uninstall.
            Log.e(TAG, "Could not determine the launching uid.");

            setResult(Activity.RESULT_FIRST_USER);
            finish();
            return;
        }

        // Get intent information.
        // We expect an intent with URI of the form package://<packageName>#<className>
        // className is optional; if specified, it is the activity the user chose to uninstall