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

Commit a160b9eb authored by Nate Myren's avatar Nate Myren Committed by Automerger Merge Worker
Browse files

Ensure permissions are revoked on state changes am: 84c1247a am: 9259e1b2

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/12933477

Change-Id: Ia699cb9258ade5909de123657c3154f02d3654d2
parents 0b08effb 9259e1b2
Loading
Loading
Loading
Loading
+20 −4
Original line number Original line Diff line number Diff line
@@ -330,6 +330,7 @@ import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.os.Zygote;
import com.android.internal.telephony.CarrierAppUtils;
import com.android.internal.telephony.CarrierAppUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FastXmlSerializer;
@@ -12441,11 +12442,16 @@ public class PackageManagerService extends IPackageManager.Stub
                mPermissionManager.addAllPermissionGroups(pkg, chatty);
                mPermissionManager.addAllPermissionGroups(pkg, chatty);
            }
            }
            // 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;
            // Don't allow ephemeral applications to define new permissions.
            // Don't allow ephemeral applications to define new permissions.
            if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
            if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
                permissionsWithChangedDefinition = null;
                Slog.w(TAG, "Permissions from package " + pkg.getPackageName()
                Slog.w(TAG, "Permissions from package " + pkg.getPackageName()
                        + " ignored: instant apps cannot define new permissions.");
                        + " ignored: instant apps cannot define new permissions.");
            } else {
            } else {
                permissionsWithChangedDefinition =
                        mPermissionManager.addAllPermissions(pkg, chatty);
                        mPermissionManager.addAllPermissions(pkg, chatty);
            }
            }
@@ -12475,7 +12481,10 @@ public class PackageManagerService extends IPackageManager.Stub
                }
                }
            }
            }
            if (oldPkg != null) {
            boolean hasOldPkg = oldPkg != null;
            boolean hasPermissionDefinitionChanges =
                    !CollectionUtils.isEmpty(permissionsWithChangedDefinition);
            if (hasOldPkg || hasPermissionDefinitionChanges) {
                // We need to call revokeRuntimePermissionsIfGroupChanged async as permission
                // We need to call revokeRuntimePermissionsIfGroupChanged async as permission
                // revoke callbacks from this method might need to kill apps which need the
                // revoke callbacks from this method might need to kill apps which need the
                // mPackages lock on a different thread. This would dead lock.
                // mPackages lock on a different thread. This would dead lock.
@@ -12486,9 +12495,16 @@ public class PackageManagerService extends IPackageManager.Stub
                // won't be granted yet, hence new packages are no problem.
                // won't be granted yet, hence new packages are no problem.
                final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
                final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
                AsyncTask.execute(() ->
                AsyncTask.execute(() -> {
                    if (hasOldPkg) {
                        mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg,
                        mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg,
                                allPackageNames));
                                allPackageNames);
                    }
                    if (hasPermissionDefinitionChanges) {
                        mPermissionManager.revokeRuntimePermissionsIfPermissionDefinitionChanged(
                                permissionsWithChangedDefinition, allPackageNames);
                    }
                });
            }
            }
        }
        }
+19 −0
Original line number Original line Diff line number Diff line
@@ -83,6 +83,8 @@ public final class BasePermission {


    final @PermissionType int type;
    final @PermissionType int type;


    private boolean mPermissionDefinitionChanged;

    String sourcePackageName;
    String sourcePackageName;


    int protectionLevel;
    int protectionLevel;
@@ -126,6 +128,11 @@ public final class BasePermission {
    public String getSourcePackageName() {
    public String getSourcePackageName() {
        return sourcePackageName;
        return sourcePackageName;
    }
    }

    public boolean isPermissionDefinitionChanged() {
        return mPermissionDefinitionChanged;
    }

    public int getType() {
    public int getType() {
        return type;
        return type;
    }
    }
@@ -140,6 +147,10 @@ public final class BasePermission {
        this.perm = perm;
        this.perm = perm;
    }
    }


    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];
@@ -322,6 +333,7 @@ public final class BasePermission {
        final PackageSettingBase pkgSetting =
        final PackageSettingBase pkgSetting =
                (PackageSettingBase) packageManagerInternal.getPackageSetting(pkg.getPackageName());
                (PackageSettingBase) packageManagerInternal.getPackageSetting(pkg.getPackageName());
        // 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.sourcePackageName, p.getPackageName())) {
        if (bp != null && !Objects.equals(bp.sourcePackageName, p.getPackageName())) {
            final boolean currentOwnerIsSystem;
            final boolean currentOwnerIsSystem;
            if (bp.perm == null) {
            if (bp.perm == null) {
@@ -347,6 +359,7 @@ public final class BasePermission {
                    String msg = "New decl " + pkg + " of permission  "
                    String msg = "New decl " + pkg + " of permission  "
                            + p.getName() + " is system; overriding " + bp.sourcePackageName;
                            + p.getName() + " is system; overriding " + bp.sourcePackageName;
                    PackageManagerService.reportSettingsProblem(Log.WARN, msg);
                    PackageManagerService.reportSettingsProblem(Log.WARN, msg);
                    ownerChanged = true;
                    bp = null;
                    bp = null;
                }
                }
            }
            }
@@ -354,6 +367,7 @@ public final class BasePermission {
        if (bp == null) {
        if (bp == null) {
            bp = new BasePermission(p.getName(), p.getPackageName(), TYPE_NORMAL);
            bp = new BasePermission(p.getName(), p.getPackageName(), TYPE_NORMAL);
        }
        }
        boolean wasNormal = bp.isNormal();
        StringBuilder r = null;
        StringBuilder r = null;
        if (bp.perm == null) {
        if (bp.perm == null) {
            if (bp.sourcePackageName == null
            if (bp.sourcePackageName == null
@@ -397,6 +411,11 @@ public final class BasePermission {
                && Objects.equals(bp.perm.getName(), p.getName())) {
                && Objects.equals(bp.perm.getName(), p.getName())) {
            bp.protectionLevel = p.getProtectionLevel();
            bp.protectionLevel = p.getProtectionLevel();
        }
        }
        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.mPermissionDefinitionChanged = true;
        }
        if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
        if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
            Log.d(TAG, "  Permissions: " + r);
            Log.d(TAG, "  Permissions: " + r);
        }
        }
+85 −5
Original line number Original line Diff line number Diff line
@@ -2344,8 +2344,74 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        }
        }
    }
    }


    private void addAllPermissions(AndroidPackage pkg, boolean chatty) {
    /**
     * 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
     * @param permissionCallback Callback for permission changed
     */
    private void revokeRuntimePermissionsIfPermissionDefinitionChanged(
            @NonNull List<String> permissionsToRevoke,
            @NonNull ArrayList<String> allPackageNames,
            @NonNull PermissionCallback permissionCallback) {

        final int[] userIds = mUserManagerInt.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.getPermission(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 = mPackageManagerInt.getPackageUid(packageName, 0, userId);
                    if (uid < Process.FIRST_APPLICATION_UID) {
                        // do not revoke from system apps
                        continue;
                    }
                    final int permissionState = checkPermissionImpl(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
                            | FLAG_PERMISSION_GRANTED_BY_ROLE;
                    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 {
                            revokeRuntimePermissionInternal(permName, packageName,
                                    false, callingUid, userId, null, permissionCallback);
                        } catch (Exception e) {
                            Slog.e(TAG, "Could not revoke " + permName + " from "
                                    + packageName, e);
                        }
                    }
                }
            }
            bp.setPermissionDefinitionChanged(false);
        }
    }

    private List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) {
        final int N = ArrayUtils.size(pkg.getPermissions());
        final int N = ArrayUtils.size(pkg.getPermissions());
        ArrayList<String> definitionChangedPermissions = new ArrayList<>();
        for (int i=0; i<N; i++) {
        for (int i=0; i<N; i++) {
            ParsedPermission p = pkg.getPermissions().get(i);
            ParsedPermission p = pkg.getPermissions().get(i);


@@ -2367,21 +2433,26 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                    }
                    }
                }
                }


                final BasePermission bp;
                if (p.isTree()) {
                if (p.isTree()) {
                    final BasePermission bp = BasePermission.createOrUpdate(
                    bp = BasePermission.createOrUpdate(
                            mPackageManagerInt,
                            mPackageManagerInt,
                            mSettings.getPermissionTreeLocked(p.getName()), p, pkg,
                            mSettings.getPermissionTreeLocked(p.getName()), p, pkg,
                            mSettings.getAllPermissionTreesLocked(), chatty);
                            mSettings.getAllPermissionTreesLocked(), chatty);
                    mSettings.putPermissionTreeLocked(p.getName(), bp);
                    mSettings.putPermissionTreeLocked(p.getName(), bp);
                } else {
                } else {
                    final BasePermission bp = BasePermission.createOrUpdate(
                    bp = BasePermission.createOrUpdate(
                            mPackageManagerInt,
                            mPackageManagerInt,
                            mSettings.getPermissionLocked(p.getName()),
                            mSettings.getPermissionLocked(p.getName()),
                            p, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
                            p, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
                    mSettings.putPermissionLocked(p.getName(), bp);
                    mSettings.putPermissionLocked(p.getName(), bp);
                }
                }
                if (bp.isPermissionDefinitionChanged()) {
                    definitionChangedPermissions.add(p.getName());
                }
            }
            }
        }
        }
        return definitionChangedPermissions;
    }
    }


    private void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
    private void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
@@ -4672,9 +4743,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage,
            PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage,
                    oldPackage, allPackageNames, mDefaultPermissionCallback);
                    oldPackage, allPackageNames, mDefaultPermissionCallback);
        }
        }

        @Override
        public void revokeRuntimePermissionsIfPermissionDefinitionChanged(
                @NonNull List<String> permissionsToRevoke,
                @NonNull ArrayList<String> allPackageNames) {
            PermissionManagerService.this.revokeRuntimePermissionsIfPermissionDefinitionChanged(
                    permissionsToRevoke, allPackageNames, mDefaultPermissionCallback);
        }

        @Override
        @Override
        public void addAllPermissions(AndroidPackage pkg, boolean chatty) {
        public List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) {
            PermissionManagerService.this.addAllPermissions(pkg, chatty);
            return PermissionManagerService.this.addAllPermissions(pkg, chatty);
        }
        }
        @Override
        @Override
        public void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
        public void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
+15 −1
Original line number Original line Diff line number Diff line
@@ -253,13 +253,27 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
            @NonNull AndroidPackage oldPackage,
            @NonNull AndroidPackage oldPackage,
            @NonNull ArrayList<String> allPackageNames);
            @NonNull ArrayList<String> allPackageNames);


    /**
     * Some permissions might have been owned by a non-system package, and the system then defined
     * said permission. Some other permissions may one have been install permissions, but are now
     * runtime or higher. These permissions should be revoked.
     *
     * @param permissionsToRevoke A list of permission names to revoke
     * @param allPackageNames All packages
     */
    public abstract void revokeRuntimePermissionsIfPermissionDefinitionChanged(
            @NonNull List<String> permissionsToRevoke,
            @NonNull ArrayList<String> allPackageNames);

    /**
    /**
     * Add all permissions in the given package.
     * Add all permissions in the given package.
     * <p>
     * <p>
     * NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to
     * NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to
     * the permission settings.
     * the permission settings.
     *
     * @return A list of BasePermissions that were updated, and need to be revoked from packages
     */
     */
    public abstract void addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
    public abstract List<String> addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
    public abstract void addAllPermissionGroups(@NonNull AndroidPackage pkg, boolean chatty);
    public abstract void addAllPermissionGroups(@NonNull AndroidPackage pkg, boolean chatty);
    public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
    public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);