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

Commit d5752bdc authored by Svet Ganov's avatar Svet Ganov
Browse files

Properly handle system app permissions - for real.

System apps targeting SDK greater than Lollipop MR1 get runtime
permissions by default but if the user takes them away we should
not regrant them. To do that we keep track for each package which
user ids were handled in the last permissions update. If a new
user id has appeared we grant runtime permissions for this user
to the sys package. When we start clean (i.e. first boot) the
sys packages were updated for no user so we grant the runtime
perms for the owner. When reading a package from packages.xml
we set the updated user ids to all users ids on the device as
the state in the xml reflects the latest state before a shutdown,
i.e. the last state when permissions were updated.

Change-Id: I93135baa57950405a357b139c59f432cf02f0bc6
parent 4976d6b5
Loading
Loading
Loading
Loading
+29 −7
Original line number Diff line number Diff line
@@ -6967,6 +6967,10 @@ public class PackageManagerService extends IPackageManager.Stub {
        PermissionsState permissionsState = ps.getPermissionsState();
        PermissionsState origPermissions = permissionsState;
        final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
        int[] upgradeUserIds = PermissionsState.USERS_NONE;
        boolean changedPermission = false;
        if (replace) {
@@ -7022,17 +7026,33 @@ public class PackageManagerService extends IPackageManager.Stub {
                        // For legacy apps dangerous permissions are install time ones.
                        grant = GRANT_INSTALL;
                    } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                        // For modern system apps dangerous permissions are runtime ones.
                        final int[] updatedUserIds = ps.getPermissionsUpdatedForUserIds();
                        if (origPermissions.hasInstallPermission(bp.name)) {
                            // If a system app had an install permission, then the app was
                            // upgraded and we grant the permissions as runtime to all users.
                            grant = GRANT_UPGRADE;
                            upgradeUserIds = currentUserIds;
                        } else if (!Arrays.equals(updatedUserIds, currentUserIds)) {
                            // If users changed since the last permissions update for a
                            // system app, we grant the permission as runtime to the new users.
                            grant = GRANT_UPGRADE;
                            upgradeUserIds = currentUserIds;
                            for (int userId : updatedUserIds) {
                                upgradeUserIds = ArrayUtils.removeInt(upgradeUserIds, userId);
                            }
                        } else {
                        if (origPermissions.hasInstallPermission(bp.name)) {
                            // Otherwise, we grant the permission as runtime if the app
                            // already had it, i.e. we preserve runtime permissions.
                            grant = GRANT_RUNTIME;
                        }
                    } else if (origPermissions.hasInstallPermission(bp.name)) {
                        // For legacy apps that became modern, install becomes runtime.
                        grant = GRANT_UPGRADE;
                        upgradeUserIds = currentUserIds;
                    } else if (replace) {
                        // For upgraded modern apps keep runtime permissions unchanged.
                        grant = GRANT_RUNTIME;
                    }
                    }
                } break;
                case PermissionInfo.PROTECTION_SIGNATURE: {
@@ -7086,7 +7106,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                    case GRANT_UPGRADE: {
                        // Grant runtime permissions for a previously held install permission.
                        permissionsState.revokeInstallPermission(bp);
                        for (int userId : UserManagerService.getInstance().getUserIds()) {
                        for (int userId : upgradeUserIds) {
                            if (permissionsState.grantRuntimePermission(bp, userId) !=
                                    PermissionsState.PERMISSION_OPERATION_FAILURE) {
                                changedPermission = true;
@@ -7133,6 +7153,8 @@ public class PackageManagerService extends IPackageManager.Stub {
            // changed.
            ps.permissionsFixed = true;
        }
        ps.setPermissionsUpdatedForUserIds(currentUserIds);
    }
    private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
+1 −0
Original line number Diff line number Diff line
@@ -198,6 +198,7 @@ abstract class PackageSettingBase extends SettingBase {
     * Make a shallow copy of this package settings.
     */
    public void copyFrom(PackageSettingBase base) {
        setPermissionsUpdatedForUserIds(base.getPermissionsUpdatedForUserIds());
        getPermissionsState().copyFrom(base.getPermissionsState());
        primaryCpuAbiString = base.primaryCpuAbiString;
        secondaryCpuAbiString = base.secondaryCpuAbiString;
+8 −2
Original line number Diff line number Diff line
@@ -55,9 +55,9 @@ public final class PermissionsState {
    /** The permission operation failed. */
    public static final int PERMISSION_OPERATION_FAILURE = 3;

    private static final int[] USERS_ALL = {UserHandle.USER_ALL};
    public static final int[] USERS_ALL = {UserHandle.USER_ALL};

    private static final int[] USERS_NONE = {};
    public static final int[] USERS_NONE = {};

    private static final int[] NO_GIDS = {};

@@ -149,6 +149,9 @@ public final class PermissionsState {
     *     #PERMISSION_OPERATION_FAILURE}.
     */
    public int grantRuntimePermission(BasePermission permission, int userId) {
        if (userId == UserHandle.USER_ALL) {
            return PERMISSION_OPERATION_FAILURE;
        }
        return grantPermission(permission, userId);
    }

@@ -162,6 +165,9 @@ public final class PermissionsState {
     *     #PERMISSION_OPERATION_FAILURE}.
     */
    public int revokeRuntimePermission(BasePermission permission, int userId) {
        if (userId == UserHandle.USER_ALL) {
            return PERMISSION_OPERATION_FAILURE;
        }
        return revokePermission(permission, userId);
    }

+20 −1
Original line number Diff line number Diff line
@@ -17,13 +17,15 @@
package com.android.server.pm;

import android.content.pm.ApplicationInfo;
import android.util.ArraySet;

import java.util.Arrays;

abstract class SettingBase {
    int pkgFlags;
    int pkgPrivateFlags;

    private final PermissionsState mPermissionsState;
    private int[] mPermissionsUpdatedForUserIds = PermissionsState.USERS_NONE;

    SettingBase(int pkgFlags, int pkgPrivateFlags) {
        setFlags(pkgFlags);
@@ -35,12 +37,29 @@ abstract class SettingBase {
        pkgFlags = base.pkgFlags;
        pkgPrivateFlags = base.pkgPrivateFlags;
        mPermissionsState = new PermissionsState(base.mPermissionsState);
        setPermissionsUpdatedForUserIds(base.mPermissionsUpdatedForUserIds);
    }

    public PermissionsState getPermissionsState() {
        return mPermissionsState;
    }

    public int[] getPermissionsUpdatedForUserIds() {
        return mPermissionsUpdatedForUserIds;
    }

    public void setPermissionsUpdatedForUserIds(int[] userIds) {
        if (Arrays.equals(mPermissionsUpdatedForUserIds, userIds)) {
            return;
        }

        if (userIds == PermissionsState.USERS_NONE || userIds == PermissionsState.USERS_ALL) {
            mPermissionsUpdatedForUserIds = userIds;
        } else {
            mPermissionsUpdatedForUserIds = Arrays.copyOf(userIds, userIds.length);
        }
    }

    void setFlags(int pkgFlags) {
        this.pkgFlags = pkgFlags
                & (ApplicationInfo.FLAG_SYSTEM
+11 −2
Original line number Diff line number Diff line
@@ -2253,6 +2253,17 @@ final class Settings {
        mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
                + mSharedUsers.size() + " shared uids\n");

        // The persisted state we just read was generated after a permissions
        // update for all users, update each package and shared user setting
        // with the device users ids to start from were we left off.
        final int[] userIds = UserManagerService.getInstance().getUserIds();
        for (PackageSetting ps : mPackages.values()) {
            ps.setPermissionsUpdatedForUserIds(userIds);
        }
        for (SharedUserSetting sus : mSharedUsers.values()) {
            sus.setPermissionsUpdatedForUserIds(userIds);
        }

        return true;
    }

@@ -3010,8 +3021,6 @@ final class Settings {
                    XmlUtils.skipCurrentTag(parser);
                }
            }


        } else {
            XmlUtils.skipCurrentTag(parser);
        }