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

Commit 82bebbe6 authored by Rhed Jao's avatar Rhed Jao
Browse files

Fix side channel information disclosure

Application can query which packages are installed on the
device via the api PackageManager#setComponentEnabledSetting.
Two different exceptions are thrown from the api for the caller
to determine whether the application is installed.

Instead of throwing IllegalArgumentException at the beginning,
this cl throws SecurityException first if the caller tries to
modify others's state without the permission.

Bug: 184948501
Test: atest PackageManagerTest
Change-Id: Ie57a79c0c0fdc7bec7ae8aae5bbce48c3023878c
parent b008b8a0
Loading
Loading
Loading
Loading
+25 −38
Original line number Diff line number Diff line
@@ -23823,7 +23823,6 @@ public class PackageManagerService extends IPackageManager.Stub
            throw new IllegalArgumentException("Invalid new component state: "
                    + newState);
        }
        PackageSetting pkgSetting;
        final int callingUid = Binder.getCallingUid();
        final int permission;
        if (callingUid == Process.SYSTEM_UID) {
@@ -23837,42 +23836,20 @@ public class PackageManagerService extends IPackageManager.Stub
        final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
        boolean sendNow = false;
        boolean isApp = (className == null);
        final boolean isCallerInstantApp = (getInstantAppPackageName(callingUid) != null);
        String componentName = isApp ? packageName : className;
        ArrayList<String> components;
        final boolean isCallerTargetApp = ArrayUtils.contains(
                getPackagesForUid(callingUid), packageName);
        final PackageSetting pkgSetting;
        // reader
        synchronized (mLock) {
            pkgSetting = mSettings.getPackageLPr(packageName);
            if (pkgSetting == null) {
                if (!isCallerInstantApp) {
                    if (className == null) {
                        throw new IllegalArgumentException("Unknown package: " + packageName);
                    }
                    throw new IllegalArgumentException(
                            "Unknown component: " + packageName + "/" + className);
                } else {
                    // throw SecurityException to prevent leaking package information
                    throw new SecurityException(
                            "Attempt to change component state; "
                            + "pid=" + Binder.getCallingPid()
                            + ", uid=" + callingUid
                            + (className == null
                                    ? ", package=" + packageName
                                    : ", component=" + packageName + "/" + className));
                }
            }
        }
            // Limit who can change which apps
        if (!UserHandle.isSameApp(callingUid, pkgSetting.appId)) {
            if (!isCallerTargetApp) {
                // Don't allow apps that don't have permission to modify other apps
            final boolean filterApp;
            synchronized (mLock) {
                filterApp = (!allowedByPermission
                        || shouldFilterApplicationLocked(pkgSetting, callingUid, userId));
            }
            if (filterApp) {
                if (!allowedByPermission
                        || shouldFilterApplicationLocked(pkgSetting, callingUid, userId)) {
                    throw new SecurityException(
                            "Attempt to change component state; "
                                    + "pid=" + Binder.getCallingPid()
@@ -23883,9 +23860,19 @@ public class PackageManagerService extends IPackageManager.Stub
                }
                // Don't allow changing protected packages.
                if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
                throw new SecurityException("Cannot disable a protected package: " + packageName);
                    throw new SecurityException(
                            "Cannot disable a protected package: " + packageName);
                }
            }
            if (pkgSetting == null) {
                if (className == null) {
                    throw new IllegalArgumentException("Unknown package: " + packageName);
                }
                throw new IllegalArgumentException(
                        "Unknown component: " + packageName + "/" + className);
            }
        }
        // Only allow apps with CHANGE_COMPONENT_ENABLED_STATE permission to change hidden
        // app details activity
        if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)