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

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

Ensure permissions are revoked on state changes

If a permission owner changes, or a permission level is upgraded, revoke
the permission from all packages

Test: Manual
Bug: 154505240
Merged-In: I0dec9eb7c2fecd3147e33e04d3f79f6dffcf7721
Change-Id: I2b3780ba3ae5147026d4c85b3526fe1807724be6
(manually backported from commit a28931a0)
parent 752cb249
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -35,6 +35,8 @@ final class BasePermission {


    final int type;
    final int type;


    private boolean mPermissionDefinitionChanged;

    int protectionLevel;
    int protectionLevel;


    PackageParser.Permission perm;
    PackageParser.Permission perm;
@@ -67,11 +69,19 @@ final class BasePermission {
                + "}";
                + "}";
    }
    }


    public boolean isPermissionDefinitionChanged() {
        return mPermissionDefinitionChanged;
    }

    public void setGids(int[] gids, boolean perUser) {
    public void setGids(int[] gids, boolean perUser) {
        this.gids = gids;
        this.gids = gids;
        this.perUser = perUser;
        this.perUser = perUser;
    }
    }


    public void setPermissionDefinitionChanged(boolean shouldOverride) {
        mPermissionDefinitionChanged = shouldOverride;
    }

    public int[] computeGids(int userId) {
    public int[] computeGids(int userId) {
        if (perUser) {
        if (perUser) {
            final int[] userGids = new int[gids.length];
            final int[] userGids = new int[gids.length];
+102 −3
Original line number Original line Diff line number Diff line
@@ -10784,7 +10784,7 @@ public class PackageManagerService extends IPackageManager.Stub
        } else {
        } else {
            final int userId = user == null ? 0 : user.getIdentifier();
            final int userId = user == null ? 0 : user.getIdentifier();
            // Modify state for the given package setting
            // Modify state for the given package setting
            commitPackageSettings(pkg, pkgSetting, user, scanFlags,
            commitPackageSettings(pkg, oldPkg, pkgSetting, user, scanFlags,
                    (policyFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/);
                    (policyFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/);
            if (pkgSetting.getInstantApp(userId)) {
            if (pkgSetting.getInstantApp(userId)) {
                mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId);
                mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId);
@@ -11146,11 +11146,74 @@ public class PackageManagerService extends IPackageManager.Stub
        return true;
        return true;
    }
    }
    /**
     * If permissions are upgraded to runtime, or their owner changes to the system, then any
     * granted permissions must be revoked.
     *
     * @param permissionsToRevoke A list of permission names to revoke
     * @param allPackageNames All package names
     */
    private void revokeRuntimePermissionsIfPermissionDefinitionChanged(
            @NonNull List<String> permissionsToRevoke,
            @NonNull ArrayList<String> allPackageNames) {
        final int[] userIds = UserManagerService.getInstance().getUserIds();
        final int numPermissions = permissionsToRevoke.size();
        final int numUserIds = userIds.length;
        final int numPackages = allPackageNames.size();
        final int callingUid = Binder.getCallingUid();
        for (int permNum = 0; permNum < numPermissions; permNum++) {
            String permName = permissionsToRevoke.get(permNum);
            BasePermission bp = mSettings.mPermissions.get(permName);
            if (bp == null || !bp.isRuntime()) {
                continue;
            }
            for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
                final int userId = userIds[userIdNum];
                for (int packageNum = 0; packageNum < numPackages; packageNum++) {
                    final String packageName = allPackageNames.get(packageNum);
                    final int uid = getPackageUid(packageName, 0, userId);
                    if (uid < Process.FIRST_APPLICATION_UID) {
                        // do not revoke from system apps
                        continue;
                    }
                    final int permissionState = checkPermission(permName, packageName,
                            userId);
                    final int flags = getPermissionFlags(permName, packageName, userId);
                    final int flagMask = FLAG_PERMISSION_SYSTEM_FIXED
                            | FLAG_PERMISSION_POLICY_FIXED
                            | FLAG_PERMISSION_GRANTED_BY_DEFAULT;
                    if (permissionState == PackageManager.PERMISSION_GRANTED
                            && (flags & flagMask) == 0) {
                        EventLog.writeEvent(0x534e4554, "154505240", uid,
                                "Revoking permission " + permName + " from package "
                                        + packageName + " due to definition change");
                        EventLog.writeEvent(0x534e4554, "168319670", uid,
                                "Revoking permission " + permName + " from package "
                                        + packageName + " due to definition change");
                        Slog.e(TAG, "Revoking permission " + permName + " from package "
                                + packageName + " due to definition change");
                        try {
                            revokeRuntimePermission(packageName, permName, userId, false);
                        } catch (Exception e) {
                            Slog.e(TAG, "Could not revoke " + permName + " from "
                                    + packageName, e);
                        }
                    }
                }
            }
            bp.setPermissionDefinitionChanged(false);
        }
    }
    /**
    /**
     * Adds a scanned package to the system. When this method is finished, the package will
     * Adds a scanned package to the system. When this method is finished, the package will
     * be available for query, resolution, etc...
     * be available for query, resolution, etc...
     */
     */
    private void commitPackageSettings(PackageParser.Package pkg, PackageSetting pkgSetting,
    private void commitPackageSettings(PackageParser.Package pkg, PackageParser.Package oldPkg,
            PackageSetting pkgSetting,
            UserHandle user, int scanFlags, boolean chatty) throws PackageManagerException {
            UserHandle user, int scanFlags, boolean chatty) throws PackageManagerException {
        final String pkgName = pkg.packageName;
        final String pkgName = pkg.packageName;
        if (mCustomResolverComponentName != null &&
        if (mCustomResolverComponentName != null &&
@@ -11482,6 +11545,10 @@ public class PackageManagerService extends IPackageManager.Stub
                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Permission Groups: " + r);
                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Permission Groups: " + r);
            }
            }
            // If a permission has had its defining app changed, or it has had its protection
            // upgraded, we need to revoke apps that hold it
            final List<String> permissionsWithChangedDefinition = new ArrayList<String>();
            N = pkg.permissions.size();
            N = pkg.permissions.size();
            r = null;
            r = null;
            for (i=0; i<N; i++) {
            for (i=0; i<N; i++) {
@@ -11517,6 +11584,7 @@ public class PackageManagerService extends IPackageManager.Stub
                BasePermission bp = permissionMap.get(p.info.name);
                BasePermission bp = permissionMap.get(p.info.name);
                // Allow system apps to redefine non-system permissions
                // Allow system apps to redefine non-system permissions
                boolean ownerChanged = false;
                if (bp != null && !Objects.equals(bp.sourcePackage, p.info.packageName)) {
                if (bp != null && !Objects.equals(bp.sourcePackage, p.info.packageName)) {
                    final boolean currentOwnerIsSystem = (bp.perm != null
                    final boolean currentOwnerIsSystem = (bp.perm != null
                            && isSystemApp(bp.perm.owner));
                            && isSystemApp(bp.perm.owner));
@@ -11532,6 +11600,7 @@ public class PackageManagerService extends IPackageManager.Stub
                            String msg = "New decl " + p.owner + " of permission  "
                            String msg = "New decl " + p.owner + " of permission  "
                                    + p.info.name + " is system; overriding " + bp.sourcePackage;
                                    + p.info.name + " is system; overriding " + bp.sourcePackage;
                            reportSettingsProblem(Log.WARN, msg);
                            reportSettingsProblem(Log.WARN, msg);
                            ownerChanged = true;
                            bp = null;
                            bp = null;
                        }
                        }
                    }
                    }
@@ -11543,6 +11612,7 @@ public class PackageManagerService extends IPackageManager.Stub
                    permissionMap.put(p.info.name, bp);
                    permissionMap.put(p.info.name, bp);
                }
                }
                boolean wasNormal = bp.type == BasePermission.TYPE_NORMAL;
                if (bp.perm == null) {
                if (bp.perm == null) {
                    if (bp.sourcePackage == null
                    if (bp.sourcePackage == null
                            || bp.sourcePackage.equals(p.info.packageName)) {
                            || bp.sourcePackage.equals(p.info.packageName)) {
@@ -11585,8 +11655,15 @@ public class PackageManagerService extends IPackageManager.Stub
                if (bp.perm == p) {
                if (bp.perm == p) {
                    bp.protectionLevel = p.info.protectionLevel;
                    bp.protectionLevel = p.info.protectionLevel;
                }
                }
            }
                if (bp.isRuntime() && (ownerChanged || wasNormal)) {
                    // If this is a runtime permission and the owner has changed, or this was a normal
                    // permission, then permission state should be cleaned up
                    bp.setPermissionDefinitionChanged(true);
                    permissionsWithChangedDefinition.add(p.info.name);
                }
            }
            if (r != null) {
            if (r != null) {
                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Permissions: " + r);
                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Permissions: " + r);
            }
            }
@@ -11627,6 +11704,28 @@ public class PackageManagerService extends IPackageManager.Stub
                    mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
                    mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
                }
                }
            }
            }
            boolean hasOldPkg = oldPkg != null;
            boolean hasPermissionDefinitionChanges = !permissionsWithChangedDefinition.isEmpty();
            if (hasOldPkg || hasPermissionDefinitionChanges) {
                // We need to call revokeRuntimePermissionsIfPermissionDefinitionChanged async
                // as permission
                // revoke callbacks from this method might need to kill apps which need the
                // mPackages lock on a different thread. This would dead lock.
                //
                // Hence create a copy of all package names and pass it into
                // revokeRuntimePermissionsIfGroupChanged. Only for those permissions might get
                // revoked. If a new package is added before the async code runs the permission
                // won't be granted yet, hence new packages are no problem.
                final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
                AsyncTask.execute(() -> {
                    if (hasPermissionDefinitionChanges) {
                        revokeRuntimePermissionsIfPermissionDefinitionChanged(
                                permissionsWithChangedDefinition, allPackageNames);
                    }
                });
            }
        }
        }
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);