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

Commit 6a6a15d5 authored by Philip P. Moltmann's avatar Philip P. Moltmann Committed by Android (Google) Code Review
Browse files

Merge changes from topic "12933477" into rvc-dev

* changes:
  Revoke permission on non-runtime -> runtime upgrade
  Ensure permissions are revoked on state changes
parents a7bc88f9 33e24c88
Loading
Loading
Loading
Loading
+20 −4
Original line number Diff line number Diff line
@@ -329,6 +329,7 @@ import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.telephony.CarrierAppUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -12428,11 +12429,16 @@ public class PackageManagerService extends IPackageManager.Stub
                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.
            if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
                permissionsWithChangedDefinition = null;
                Slog.w(TAG, "Permissions from package " + pkg.getPackageName()
                        + " ignored: instant apps cannot define new permissions.");
            } else {
                permissionsWithChangedDefinition =
                        mPermissionManager.addAllPermissions(pkg, chatty);
            }
@@ -12462,7 +12468,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
                // revoke callbacks from this method might need to kill apps which need the
                // mPackages lock on a different thread. This would dead lock.
@@ -12473,9 +12482,16 @@ public class PackageManagerService extends IPackageManager.Stub
                // won't be granted yet, hence new packages are no problem.
                final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
                AsyncTask.execute(() ->
                AsyncTask.execute(() -> {
                    if (hasOldPkg) {
                        mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg,
                                allPackageNames));
                                allPackageNames);
                    }
                    if (hasPermissionDefinitionChanges) {
                        mPermissionManager.revokeRuntimePermissionsIfPermissionDefinitionChanged(
                                permissionsWithChangedDefinition, allPackageNames);
                    }
                });
            }
        }
+19 −0
Original line number Diff line number Diff line
@@ -83,6 +83,8 @@ public final class BasePermission {

    final @PermissionType int type;

    private boolean mPermissionDefinitionChanged;

    String sourcePackageName;

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

    public boolean isPermissionDefinitionChanged() {
        return mPermissionDefinitionChanged;
    }

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

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

    public int[] computeGids(int userId) {
        if (perUser) {
            final int[] userGids = new int[gids.length];
@@ -322,6 +333,7 @@ public final class BasePermission {
        final PackageSettingBase pkgSetting =
                (PackageSettingBase) packageManagerInternal.getPackageSetting(pkg.getPackageName());
        // Allow system apps to redefine non-system permissions
        boolean ownerChanged = false;
        if (bp != null && !Objects.equals(bp.sourcePackageName, p.getPackageName())) {
            final boolean currentOwnerIsSystem;
            if (bp.perm == null) {
@@ -347,6 +359,7 @@ public final class BasePermission {
                    String msg = "New decl " + pkg + " of permission  "
                            + p.getName() + " is system; overriding " + bp.sourcePackageName;
                    PackageManagerService.reportSettingsProblem(Log.WARN, msg);
                    ownerChanged = true;
                    bp = null;
                }
            }
@@ -354,6 +367,7 @@ public final class BasePermission {
        if (bp == null) {
            bp = new BasePermission(p.getName(), p.getPackageName(), TYPE_NORMAL);
        }
        boolean wasNonRuntime = !bp.isRuntime();
        StringBuilder r = null;
        if (bp.perm == null) {
            if (bp.sourcePackageName == null
@@ -397,6 +411,11 @@ public final class BasePermission {
                && Objects.equals(bp.perm.getName(), p.getName())) {
            bp.protectionLevel = p.getProtectionLevel();
        }
        if (bp.isRuntime() && (ownerChanged || wasNonRuntime)) {
            // 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) {
            Log.d(TAG, "  Permissions: " + r);
        }
+85 −5
Original line number 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());
        ArrayList<String> definitionChangedPermissions = new ArrayList<>();
        for (int i=0; i<N; i++) {
            ParsedPermission p = pkg.getPermissions().get(i);

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

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

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

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

        @Override
        public void addAllPermissions(AndroidPackage pkg, boolean chatty) {
            PermissionManagerService.this.addAllPermissions(pkg, chatty);
        public List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) {
            return PermissionManagerService.this.addAllPermissions(pkg, chatty);
        }
        @Override
        public void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
+15 −1
Original line number Diff line number Diff line
@@ -253,13 +253,27 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
            @NonNull AndroidPackage oldPackage,
            @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.
     * <p>
     * NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to
     * 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 removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);