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

Commit ef9acb6e authored by Todd Kennedy's avatar Todd Kennedy
Browse files

Ensure permission held for MATCH_KNOWN_PACKAGES

There's an escape clause that passes the cross user permissions
if the caller UID is identical to the target user ID [eg. we're not
operating across users]. However, the method getInstalledPackagesList()
uses android.permission.INTERACT_ACROSS_USERS to filter the results and
a calling UID check is not sufficient. Ensuure the permission is
actually held, regardless of the calling UID or target user.

Change-Id: Iebf88668766d387a15246d6eea6420610665105a
Fixes: 80435086
Test: atest CtsAppSecurityHostTestCases:ApplicationVisibilityTest
parent e3348a25
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -248,6 +248,7 @@ package android.content.pm {
  public abstract class PackageManager {
    method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
    method public abstract int getInstallReason(java.lang.String, android.os.UserHandle);
    method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
    method public abstract java.lang.String[] getNamesForUids(int[]);
    method public abstract java.lang.String getPermissionControllerPackageName();
    method public abstract java.lang.String getServicesSystemSharedLibraryPackageName();
@@ -256,6 +257,7 @@ package android.content.pm {
    field public static final java.lang.String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
    field public static final java.lang.String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
    field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
    field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
  }

  public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+2 −0
Original line number Diff line number Diff line
@@ -461,6 +461,7 @@ public abstract class PackageManager {
     * package.
     * @hide
     */
    @TestApi
    public static final int MATCH_KNOWN_PACKAGES = MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER;

    /**
@@ -3420,6 +3421,7 @@ public abstract class PackageManager {
     *         deleted with {@code DONT_DELETE_DATA} flag set).
     * @hide
     */
    @TestApi
    @SystemApi
    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
    public abstract List<PackageInfo> getInstalledPackagesAsUser(@PackageInfoFlags int flags,
+4 −2
Original line number Diff line number Diff line
@@ -4786,8 +4786,10 @@ public class PackageManagerService extends IPackageManager.Stub
            triaged = false;
        }
        if ((flags & PackageManager.MATCH_ANY_USER) != 0) {
            // require the permission to be held; the calling uid and given user id referring
            // to the same user is not sufficient
            mPermissionManager.enforceCrossUserPermission(
                    Binder.getCallingUid(), userId, false, false,
                    Binder.getCallingUid(), userId, false, false, true,
                    "MATCH_ANY_USER flag requires INTERACT_ACROSS_USERS permission at "
                    + Debug.getCallers(5));
        } else if ((flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0 && isCallerSystemUser
@@ -7871,7 +7873,7 @@ public class PackageManagerService extends IPackageManager.Stub
        flags = updateFlagsForPackage(flags, userId, null);
        final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
        mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                true /* requireFullPermission */, false /* checkShell */,
                false /* requireFullPermission */, false /* checkShell */,
                "get installed packages");
        // writer
+8 −0
Original line number Diff line number Diff line
@@ -174,6 +174,14 @@ public abstract class PermissionManagerInternal {
     */
    public abstract void enforceCrossUserPermission(int callingUid, int userId,
            boolean requireFullPermission, boolean checkShell, @NonNull String message);
    /**
     * @see #enforceCrossUserPermission(int, int, boolean, boolean, String)
     * @param requirePermissionWhenSameUser When {@code true}, still require the cross user
     * permission to be held even if the callingUid and userId reference the same user.
     */
    public abstract void enforceCrossUserPermission(int callingUid, int userId,
            boolean requireFullPermission, boolean checkShell,
            boolean requirePermissionWhenSameUser, @NonNull String message);
    public abstract void enforceGrantRevokeRuntimePermissionPermissions(@NonNull String message);

    public abstract @NonNull PermissionSettings getPermissionSettings();
+26 −8
Original line number Diff line number Diff line
@@ -1381,7 +1381,9 @@ public class PermissionManagerService {
                "grantRuntimePermission");

        enforceCrossUserPermission(callingUid, userId,
                true /* requireFullPermission */, true /* checkShell */,
                true,  // requireFullPermission
                true,  // checkShell
                false, // requirePermissionWhenSameUser
                "grantRuntimePermission");

        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
@@ -1501,7 +1503,9 @@ public class PermissionManagerService {
                "revokeRuntimePermission");

        enforceCrossUserPermission(Binder.getCallingUid(), userId,
                true /* requireFullPermission */, true /* checkShell */,
                true,  // requireFullPermission
                true,  // checkShell
                false, // requirePermissionWhenSameUser
                "revokeRuntimePermission");

        final int appId;
@@ -1658,7 +1662,9 @@ public class PermissionManagerService {
        enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");

        enforceCrossUserPermission(callingUid, userId,
                true /* requireFullPermission */, false /* checkShell */,
                true,  // requireFullPermission
                false, // checkShell
                false, // requirePermissionWhenSameUser
                "getPermissionFlags");

        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
@@ -1849,7 +1855,9 @@ public class PermissionManagerService {
        enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");

        enforceCrossUserPermission(callingUid, userId,
                true /* requireFullPermission */, true /* checkShell */,
                true,  // requireFullPermission
                true,  // checkShell
                false, // requirePermissionWhenSameUser
                "updatePermissionFlags");

        // Only the system can change these flags and nothing else.
@@ -1904,7 +1912,9 @@ public class PermissionManagerService {
        enforceGrantRevokeRuntimePermissionPermissions(
                "updatePermissionFlagsForAllApps");
        enforceCrossUserPermission(callingUid, userId,
                true /* requireFullPermission */, true /* checkShell */,
                true,  // requireFullPermission
                true,  // checkShell
                false, // requirePermissionWhenSameUser
                "updatePermissionFlagsForAllApps");

        // Only the system can change system fixed flags.
@@ -1944,7 +1954,8 @@ public class PermissionManagerService {
     * @param message the message to log on security exception
     */
    private void enforceCrossUserPermission(int callingUid, int userId,
            boolean requireFullPermission, boolean checkShell, String message) {
            boolean requireFullPermission, boolean checkShell,
            boolean requirePermissionWhenSameUser, String message) {
        if (userId < 0) {
            throw new IllegalArgumentException("Invalid userId " + userId);
        }
@@ -1952,7 +1963,7 @@ public class PermissionManagerService {
            PackageManagerServiceUtils.enforceShellRestriction(
                    UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
        }
        if (userId == UserHandle.getUserId(callingUid)) return;
        if (!requirePermissionWhenSameUser && userId == UserHandle.getUserId(callingUid)) return;
        if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
            if (requireFullPermission) {
                mContext.enforceCallingOrSelfPermission(
@@ -2139,7 +2150,14 @@ public class PermissionManagerService {
        public void enforceCrossUserPermission(int callingUid, int userId,
                boolean requireFullPermission, boolean checkShell, String message) {
            PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,
                    requireFullPermission, checkShell, message);
                    requireFullPermission, checkShell, false, message);
        }
        @Override
        public void enforceCrossUserPermission(int callingUid, int userId,
                boolean requireFullPermission, boolean checkShell,
                boolean requirePermissionWhenSameUser, String message) {
            PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,
                    requireFullPermission, checkShell, requirePermissionWhenSameUser, message);
        }
        @Override
        public void enforceGrantRevokeRuntimePermissionPermissions(String message) {