diff options
6 files changed, 370 insertions, 250 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 9c8b972985eb..27c05fd53515 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -367,7 +367,6 @@ import com.android.server.pm.parsing.pkg.ParsedPackage; import com.android.server.pm.permission.BasePermission; import com.android.server.pm.permission.PermissionManagerService; import com.android.server.pm.permission.PermissionManagerServiceInternal; -import com.android.server.pm.permission.PermissionsState; import com.android.server.policy.PermissionPolicyInternal; import com.android.server.rollback.RollbackManagerInternal; import com.android.server.security.VerityUtils; @@ -1818,7 +1817,7 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { removeMessages(WRITE_SETTINGS); removeMessages(WRITE_PACKAGE_RESTRICTIONS); - mSettings.writeLPr(); + writeSettingsLPrTEMP(); mDirtyUsers.clear(); } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); @@ -1838,6 +1837,7 @@ public class PackageManagerService extends IPackageManager.Stub Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); synchronized (mLock) { removeMessages(WRITE_PACKAGE_LIST); + mPermissionManager.writePermissionsStateToPackageSettingsTEMP(); mSettings.writePackageListLPr(msg.arg1); } Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); @@ -2518,7 +2518,7 @@ public class PackageManagerService extends IPackageManager.Stub } mSettings.onVolumeForgotten(fsUuid); - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } } }; @@ -3442,6 +3442,7 @@ public class PackageManagerService extends IPackageManager.Stub + ((SystemClock.uptimeMillis()-startTime)/1000f) + " seconds"); + mPermissionManager.readPermissionsStateFromPackageSettingsTEMP(); // If the platform SDK has changed since the last time we booted, // we need to re-grant app permission to catch any new ones that // appear. This is really a hack, and means that apps can in some @@ -3561,7 +3562,7 @@ public class PackageManagerService extends IPackageManager.Stub // can downgrade to reader t.traceBegin("write settings"); - mSettings.writeLPr(); + writeSettingsLPrTEMP(); t.traceEnd(); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis()); @@ -3765,7 +3766,7 @@ public class PackageManagerService extends IPackageManager.Stub Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e); } mPermissionManager.updatePermissions(pkg.getPackageName(), pkg); - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } } catch (PackageManagerException e) { // Whoops! Something went very wrong; roll back to the stub and disable the package @@ -3776,9 +3777,8 @@ public class PackageManagerService extends IPackageManager.Stub // If we don't, installing the system package fails during scan enableSystemPackageLPw(stubPkg); } - installPackageFromSystemLIF(stubPkg.getCodePath(), - null /*allUserHandles*/, null /*origUserHandles*/, - null /*origPermissionsState*/, true /*writeSettings*/); + installPackageFromSystemLIF(stubPkg.getCodePath(), null /*allUserHandles*/, + null /*origUserHandles*/, true /*writeSettings*/); } catch (PackageManagerException pme) { // Serious WTF; we have to be able to install the stub Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.getPackageName(), @@ -3792,7 +3792,7 @@ public class PackageManagerService extends IPackageManager.Stub stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, UserHandle.USER_SYSTEM, "android"); } - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } } return false; @@ -16280,7 +16280,7 @@ public class PackageManagerService extends IPackageManager.Stub res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); //to update install status Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "writeSettings"); - mSettings.writeLPr(); + writeSettingsLPrTEMP(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } @@ -18877,6 +18877,10 @@ public class PackageManagerService extends IPackageManager.Stub if (outInfo != null) { outInfo.removedAppId = removedAppId; } + if ((deletedPs.sharedUser == null || deletedPs.sharedUser.packages.size() == 0) + && !isUpdatedSystemApp(deletedPs)) { + mPermissionManager.removePermissionsStateTEMP(removedAppId); + } mPermissionManager.updatePermissions(deletedPs.name, null); if (deletedPs.sharedUser != null) { // Remove permissions associated with package. Since runtime @@ -18886,10 +18890,10 @@ public class PackageManagerService extends IPackageManager.Stub // package is successful and this causes a change in gids. boolean shouldKill = false; for (int userId : UserManagerService.getInstance().getUserIds()) { - final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs, - userId); - shouldKill |= userIdToKill == UserHandle.USER_ALL - || userIdToKill >= UserHandle.USER_SYSTEM; + final int userIdToKill = mPermissionManager + .revokeSharedUserPermissionsForDeletedPackageTEMP(deletedPs, + userId); + shouldKill |= userIdToKill != UserHandle.USER_NULL; } // If gids changed, kill all affected packages. if (shouldKill) { @@ -18933,7 +18937,7 @@ public class PackageManagerService extends IPackageManager.Stub // can downgrade to reader if (writeSettings) { // Save settings now - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } if (installedStateChanged) { mSettings.writeKernelMappingLPr(deletedPs); @@ -19020,8 +19024,7 @@ public class PackageManagerService extends IPackageManager.Stub if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs); try { installPackageFromSystemLIF(disabledPs.getCodePathString(), allUserHandles, - outInfo == null ? null : outInfo.origUsers, deletedPs.getPermissionsState(), - writeSettings); + outInfo == null ? null : outInfo.origUsers, writeSettings); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to restore system package:" + deletedPkg.getPackageName() + ": " + e.getMessage()); @@ -19052,9 +19055,8 @@ public class PackageManagerService extends IPackageManager.Stub * Installs a package that's already on the system partition. */ private AndroidPackage installPackageFromSystemLIF(@NonNull String codePathString, - @Nullable int[] allUserHandles, @Nullable int[] origUserHandles, - @Nullable PermissionsState origPermissionState, boolean writeSettings) - throws PackageManagerException { + @Nullable int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings) + throws PackageManagerException { final File codePath = new File(codePathString); @ParseFlags int parseFlags = mDefParseFlags @@ -19091,12 +19093,8 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName()); - // Propagate the permissions state as we do not want to drop on the floor - // runtime permissions. The update permissions method below will take - // care of removing obsolete permissions and grant install permissions. - if (origPermissionState != null) { - ps.getPermissionsState().copyFrom(origPermissionState); - } + // The update permissions method below will take care of removing obsolete permissions + // and granting install permissions. mPermissionManager.updatePermissions(pkg.getPackageName(), pkg); final boolean applyUserRestrictions @@ -19130,7 +19128,7 @@ public class PackageManagerService extends IPackageManager.Stub } // can downgrade to reader here if (writeSettings) { - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } } return pkg; @@ -19204,7 +19202,7 @@ public class PackageManagerService extends IPackageManager.Stub } else { ps.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER; } - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } return true; } @@ -20396,7 +20394,7 @@ public class PackageManagerService extends IPackageManager.Stub (parser1, userId1) -> { synchronized (mLock) { mSettings.readAllDomainVerificationsLPr(parser1, userId1); - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } }); } catch (Exception e) { @@ -21747,6 +21745,8 @@ public class PackageManagerService extends IPackageManager.Stub protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; + mPermissionManager.writePermissionsStateToPackageSettingsTEMP(); + DumpState dumpState = new DumpState(); boolean fullPreferred = false; boolean checkin = false; @@ -21942,7 +21942,7 @@ public class PackageManagerService extends IPackageManager.Stub dumpState.setDump(DumpState.DUMP_SERVICE_PERMISSIONS); } else if ("write".equals(cmd)) { synchronized (mLock) { - mSettings.writeLPr(); + writeSettingsLPrTEMP(); pw.println("Settings written."); return; } @@ -22660,7 +22660,7 @@ public class PackageManagerService extends IPackageManager.Stub // Yay, everything is now upgraded ver.forceCurrent(); - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } for (PackageFreezer freezer : freezers) { @@ -22710,7 +22710,7 @@ public class PackageManagerService extends IPackageManager.Stub AttributeCache.instance().removePackage(ps.name); } - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } } @@ -23623,6 +23623,8 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { mDirtyUsers.remove(userId); mUserNeedsBadging.delete(userId); + mPermissionManager.onUserRemoved(userId); + mPermissionManager.writePermissionsStateToPackageSettingsTEMP(); mSettings.removeUserLPw(userId); mPendingBroadcasts.remove(userId); mInstantAppRegistry.onUserRemovedLPw(userId); @@ -23723,7 +23725,9 @@ public class PackageManagerService extends IPackageManager.Stub boolean readPermissionStateForUser(@UserIdInt int userId) { synchronized (mPackages) { + mPermissionManager.writePermissionsStateToPackageSettingsTEMP(); mSettings.readPermissionStateForUserSyncLPr(userId); + mPermissionManager.readPermissionsStateFromPackageSettingsTEMP(); return mPmInternal.isPermissionUpgradeNeeded(userId); } } @@ -25179,7 +25183,7 @@ public class PackageManagerService extends IPackageManager.Stub if (async) { scheduleWriteSettingsLocked(); } else { - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } } } @@ -25226,7 +25230,7 @@ public class PackageManagerService extends IPackageManager.Stub return; } mSettings.mReadExternalStorageEnforced = enforced ? Boolean.TRUE : Boolean.FALSE; - mSettings.writeLPr(); + writeSettingsLPrTEMP(); } } @@ -25740,6 +25744,17 @@ public class PackageManagerService extends IPackageManager.Stub public List<String> getMimeGroup(String packageName, String mimeGroup) { return mSettings.mPackages.get(packageName).getMimeGroup(mimeGroup); } + + /** + * Temporary method that wraps mSettings.writeLPr() and calls + * mPermissionManager.writePermissionsStateToPackageSettingsTEMP() beforehand. + * + * TODO(zhanghai): This should be removed once we finish migration of permission storage. + */ + private void writeSettingsLPrTEMP() { + mPermissionManager.writePermissionsStateToPackageSettingsTEMP(); + mSettings.writeLPr(); + } } interface PackageSender { diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index de0e4b53adab..491b4fc515ce 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -34,7 +34,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfoLite; import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; import android.content.pm.PackageParser; import android.content.pm.PackageParser.PackageParserException; import android.content.pm.ResolveInfo; @@ -68,7 +67,6 @@ import com.android.server.EventLogTags; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.PackageDexUsage; import com.android.server.pm.parsing.pkg.AndroidPackage; -import com.android.server.pm.permission.PermissionsState; import dalvik.system.VMRuntime; @@ -968,20 +966,6 @@ public class PackageManagerServiceUtils { } /** - * Returns the {@link PermissionsState} for the given package. If the {@link PermissionsState} - * could not be found, {@code null} will be returned. - */ - public static PermissionsState getPermissionsState( - PackageManagerInternal packageManagerInternal, AndroidPackage pkg) { - final PackageSetting packageSetting = packageManagerInternal.getPackageSetting( - pkg.getPackageName()); - if (packageSetting == null) { - return null; - } - return packageSetting.getPermissionsState(); - } - - /** * Recursively create target directory */ public static void makeDirRecursive(File targetDir, int mode) throws ErrnoException { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index acb149b9ec3d..d545bd4c1531 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -955,93 +955,6 @@ public final class Settings { } } - /* - * Update the shared user setting when a package with a shared user id is removed. The gids - * associated with each permission of the deleted package are removed from the shared user' - * gid list only if its not in use by other permissions of packages in the shared user setting. - * - * @return the affected user id - */ - @UserIdInt - int updateSharedUserPermsLPw(PackageSetting deletedPs, int userId) { - if ((deletedPs == null) || (deletedPs.pkg == null)) { - Slog.i(PackageManagerService.TAG, - "Trying to update info for null package. Just ignoring"); - return UserHandle.USER_NULL; - } - - // No sharedUserId - if (deletedPs.sharedUser == null) { - return UserHandle.USER_NULL; - } - - SharedUserSetting sus = deletedPs.sharedUser; - - int affectedUserId = UserHandle.USER_NULL; - // Update permissions - for (String eachPerm : deletedPs.pkg.getRequestedPermissions()) { - BasePermission bp = mPermissions.getPermission(eachPerm); - if (bp == null) { - continue; - } - - // Check if another package in the shared user needs the permission. - boolean used = false; - for (PackageSetting pkg : sus.packages) { - if (pkg.pkg != null - && !pkg.pkg.getPackageName().equals(deletedPs.pkg.getPackageName()) - && pkg.pkg.getRequestedPermissions().contains(eachPerm)) { - used = true; - break; - } - } - if (used) { - continue; - } - - PermissionsState permissionsState = sus.getPermissionsState(); - PackageSetting disabledPs = getDisabledSystemPkgLPr(deletedPs.pkg.getPackageName()); - - // If the package is shadowing is a disabled system package, - // do not drop permissions that the shadowed package requests. - if (disabledPs != null) { - boolean reqByDisabledSysPkg = false; - for (String permission : disabledPs.pkg.getRequestedPermissions()) { - if (permission.equals(eachPerm)) { - reqByDisabledSysPkg = true; - break; - } - } - if (reqByDisabledSysPkg) { - continue; - } - } - - // Try to revoke as an install permission which is for all users. - // The package is gone - no need to keep flags for applying policy. - permissionsState.updatePermissionFlags(bp, userId, - PackageManager.MASK_PERMISSION_FLAGS_ALL, 0); - - if (permissionsState.revokeInstallPermission(bp) == - PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) { - affectedUserId = UserHandle.USER_ALL; - } - - // Try to revoke as an install permission which is per user. - if (permissionsState.revokeRuntimePermission(bp, userId) == - PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) { - if (affectedUserId == UserHandle.USER_NULL) { - affectedUserId = userId; - } else if (affectedUserId != userId) { - // Multiple users affected. - affectedUserId = UserHandle.USER_ALL; - } - } - } - - return affectedUserId; - } - int removePackageLPw(String name) { final PackageSetting p = mPackages.get(name); if (p != null) { @@ -5533,32 +5446,11 @@ public final class Settings { // Make sure we do not mHandler.removeMessages(userId); - for (SettingBase sb : mPackages.values()) { - revokeRuntimePermissionsAndClearFlags(sb, userId); - } - - for (SettingBase sb : mSharedUsers.values()) { - revokeRuntimePermissionsAndClearFlags(sb, userId); - } - mPermissionUpgradeNeeded.delete(userId); mVersions.delete(userId); mFingerprints.remove(userId); } - private void revokeRuntimePermissionsAndClearFlags(SettingBase sb, int userId) { - PermissionsState permissionsState = sb.getPermissionsState(); - for (PermissionState permissionState - : permissionsState.getRuntimePermissionStates(userId)) { - BasePermission bp = mPermissions.getPermission(permissionState.getName()); - if (bp != null) { - permissionsState.revokeRuntimePermission(bp, userId); - permissionsState.updatePermissionFlags(bp, userId, - PackageManager.MASK_PERMISSION_FLAGS_ALL, 0); - } - } - } - public void deleteUserRuntimePermissionsFile(int userId) { mPersistence.deleteForUser(UserHandle.of(userId)); } diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index cfa0449aaf33..962638b4f63c 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -38,7 +38,6 @@ import android.util.Slog; import com.android.server.pm.DumpState; import com.android.server.pm.PackageManagerService; -import com.android.server.pm.PackageSetting; import com.android.server.pm.PackageSettingBase; import com.android.server.pm.parsing.PackageInfoUtils; import com.android.server.pm.parsing.pkg.AndroidPackage; @@ -420,8 +419,7 @@ public final class BasePermission { } public void enforceDeclaredUsedAndRuntimeOrDevelopment(AndroidPackage pkg, - PackageSetting pkgSetting) { - final PermissionsState permsState = pkgSetting.getPermissionsState(); + PermissionsState permsState) { int index = pkg.getRequestedPermissions().indexOf(name); if (!permsState.hasRequestedPermission(name) && index == -1) { throw new SecurityException("Package " + pkg.getPackageName() diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 1be74154b53a..f5dd918a18f3 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -162,6 +162,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -227,6 +228,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { /** Internal connection to the user manager */ private final UserManagerInternal mUserManagerInt; + /** Maps from App ID to PermissionsState */ + private final SparseArray<PermissionsState> mAppIdStates = new SparseArray<>(); + /** Permission controller: User space permission management */ private PermissionControllerManager mPermissionControllerManager; @@ -671,11 +675,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (pkg == null) { return 0; } - final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( - pkg.getPackageName()); - if (ps == null) { - return 0; - } synchronized (mLock) { if (mSettings.getPermissionLocked(permName) == null) { return 0; @@ -684,7 +683,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) { return 0; } - PermissionsState permissionsState = ps.getPermissionsState(); + final PermissionsState permissionsState = getPermissionsState(pkg); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + packageName); + return 0; + } return permissionsState.getPermissionFlags(permName, userId); } @@ -771,9 +774,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); - final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( - packageName); - if (pkg == null || ps == null) { + if (pkg == null) { Log.e(TAG, "Unknown package: " + packageName); return; } @@ -789,7 +790,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { throw new IllegalArgumentException("Unknown permission: " + permName); } - final PermissionsState permissionsState = ps.getPermissionsState(); + final PermissionsState permissionsState = getPermissionsState(pkg); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + packageName); + return; + } + final boolean hadState = permissionsState.getRuntimePermissionState(permName, userId) != null; if (!hadState) { @@ -864,12 +870,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { final boolean[] changed = new boolean[1]; mPackageManagerInt.forEachPackage(pkg -> { - final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( - pkg.getPackageName()); - if (ps == null) { + final PermissionsState permissionsState = getPermissionsState(pkg); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()); return; } - final PermissionsState permissionsState = ps.getPermissionsState(); changed[0] |= permissionsState.updatePermissionFlagsForAllPermissions( userId, effectiveFlagMask, effectiveFlagValues); mOnPermissionChangeListeners.onPermissionsChanged(pkg.getUid()); @@ -923,12 +928,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { } final int uid = UserHandle.getUid(userId, pkg.getUid()); - final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( - pkg.getPackageName()); - if (ps == null) { + final PermissionsState permissionsState = getPermissionsState(pkg); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()); return PackageManager.PERMISSION_DENIED; } - final PermissionsState permissionsState = ps.getPermissionsState(); if (checkSinglePermissionInternal(uid, permissionsState, permissionName)) { return PackageManager.PERMISSION_GRANTED; @@ -1139,9 +1143,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { final long identity = Binder.clearCallingIdentity(); try { - final PermissionsState permissionsState = - PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg); + final PermissionsState permissionsState = getPermissionsState(pkg); if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + packageName); return null; } @@ -1451,7 +1455,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { throw new IllegalArgumentException("Unknown package: " + packageName); } - bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, ps); + final PermissionsState permissionsState = getPermissionsState(pkg); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()); + return; + } + + bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, permissionsState); // If a permission review is required for legacy apps we represent // their permissions as always granted runtime ones since we need @@ -1464,8 +1474,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid())); - final PermissionsState permissionsState = ps.getPermissionsState(); - final int flags = permissionsState.getPermissionFlags(permName, userId); if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) { Log.e(TAG, "Cannot grant system fixed permission " @@ -1599,9 +1607,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { "revokeRuntimePermission"); final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); - final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( - packageName); - if (pkg == null || ps == null) { + if (pkg == null) { Log.e(TAG, "Unknown package: " + packageName); return; } @@ -1613,7 +1619,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { throw new IllegalArgumentException("Unknown permission: " + permName); } - bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, ps); + final PermissionsState permissionsState = getPermissionsState(pkg); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()); + return; + } + + bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, permissionsState); // If a permission review is required for legacy apps we represent // their permissions as always granted runtime ones since we need @@ -1624,8 +1636,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { return; } - final PermissionsState permissionsState = ps.getPermissionsState(); - final int flags = permissionsState.getPermissionFlags(permName, userId); // Only the system may revoke SYSTEM_FIXED permissions. if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0 @@ -2456,14 +2466,36 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } + private void onUserRemoved(@UserIdInt int userId) { + synchronized (mLock) { + final int appIdStatesSize = mAppIdStates.size(); + for (int i = 0; i < appIdStatesSize; i++) { + PermissionsState permissionsState = mAppIdStates.valueAt(i); + for (PermissionState permissionState + : permissionsState.getRuntimePermissionStates(userId)) { + BasePermission bp = mSettings.getPermission(permissionState.getName()); + if (bp != null) { + permissionsState.revokeRuntimePermission(bp, userId); + permissionsState.updatePermissionFlags(bp, userId, + PackageManager.MASK_PERMISSION_FLAGS_ALL, 0); + } + } + } + } + } + @NonNull private Set<String> getGrantedPermissions(@NonNull String packageName, @UserIdInt int userId) { final PackageSetting ps = mPackageManagerInt.getPackageSetting(packageName); if (ps == null) { - return null; + return Collections.emptySet(); + } + final PermissionsState permissionsState = getPermissionsState(ps); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + packageName); + return Collections.emptySet(); } - final PermissionsState permissionsState = ps.getPermissionsState(); if (!ps.getInstantApp(userId)) { return permissionsState.getPermissions(userId); } else { @@ -2503,7 +2535,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (ps == null) { return null; } - final PermissionsState permissionsState = ps.getPermissionsState(); + final PermissionsState permissionsState = getPermissionsState(ps); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + packageName); + return null; + } return permissionsState.computeGids(userId); } @@ -2541,8 +2577,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (ps == null) { return; } - - final PermissionsState permissionsState = ps.getPermissionsState(); + final PermissionsState permissionsState = getOrCreatePermissionsState(ps); final int[] userIds = getAllUserIds(); @@ -2614,8 +2649,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { // changed runtime permissions here are promotion of an install to // runtime and revocation of a runtime from a shared user. synchronized (mLock) { - updatedUserIds = revokeUnusedSharedUserPermissionsLocked(ps.getSharedUser(), - userIds); + updatedUserIds = revokeUnusedSharedUserPermissionsLocked( + ps.getSharedUser().getPackages(), permissionsState, userIds); if (!ArrayUtils.isEmpty(updatedUserIds)) { runtimePermissionsRevoked = true; } @@ -3091,6 +3126,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { updatedUserIds); } + // TODO: Kill UIDs whose GIDs or runtime permissions changed. This might be more important + // for shared users. // Persist the runtime permissions state for users with changes. If permissions // were revoked because no app in the shared user declares them we have to // write synchronously to avoid losing runtime permissions state. @@ -3554,37 +3591,15 @@ public class PermissionManagerService extends IPermissionManager.Stub { final PackageSetting disabledPs = mPackageManagerInt .getDisabledSystemPackage(pkg.getPackageName()); final AndroidPackage disabledPkg = disabledPs == null ? null : disabledPs.pkg; - if (disabledPs != null - && disabledPs.getPermissionsState().hasInstallPermission(perm)) { - // If the original was granted this permission, we take - // that grant decision as read and propagate it to the - // update. - if ((privilegedPermission && disabledPs.isPrivileged()) - || (oemPermission && disabledPs.isOem() - && canGrantOemPermission(disabledPs, perm))) { - allowed = true; - } - } else { - // The system apk may have been updated with an older - // version of the one on the data partition, but which - // granted a new system permission that it didn't have - // before. In this case we do want to allow the app to - // now get the new permission if the ancestral apk is - // privileged to get it. - if (disabledPs != null && disabledPkg != null - && isPackageRequestingPermission(disabledPkg, perm) - && ((privilegedPermission && disabledPs.isPrivileged()) - || (oemPermission && disabledPs.isOem() - && canGrantOemPermission(disabledPs, perm)))) { - allowed = true; - } + if (disabledPkg != null && isPackageRequestingPermission(disabledPkg, perm) + && ((privilegedPermission && disabledPkg.isPrivileged()) + || (oemPermission && canGrantOemPermission(disabledPkg, + perm)))) { + allowed = true; } } else { - final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( - pkg.getPackageName()); allowed = (privilegedPermission && pkg.isPrivileged()) - || (oemPermission && pkg.isOem() - && canGrantOemPermission(ps, perm)); + || (oemPermission && canGrantOemPermission(pkg, perm)); } // In any case, don't grant a privileged permission to privileged vendor apps, if // the permission's protectionLevel does not have the extra 'vendorPrivileged' @@ -3735,16 +3750,16 @@ public class PermissionManagerService extends IPermissionManager.Stub { return false; } - private static boolean canGrantOemPermission(PackageSetting ps, String permission) { - if (!ps.isOem()) { + private static boolean canGrantOemPermission(AndroidPackage pkg, String permission) { + if (!pkg.isOem()) { return false; } // all oem permissions must explicitly be granted or denied final Boolean granted = - SystemConfig.getInstance().getOemPermissions(ps.name).get(permission); + SystemConfig.getInstance().getOemPermissions(pkg.getPackageName()).get(permission); if (granted == null) { throw new IllegalStateException("OEM permission" + permission + " requested by package " - + ps.name + " must be explicitly declared granted or not"); + + pkg.getPackageName() + " must be explicitly declared granted or not"); } return Boolean.TRUE == granted; } @@ -3757,12 +3772,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { } // Legacy apps have the permission and get user consent on launch. - final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( - pkg.getPackageName()); - if (ps == null) { + final PermissionsState permissionsState = getPermissionsState(pkg); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()); return false; } - final PermissionsState permissionsState = ps.getPermissionsState(); return permissionsState.isPermissionReviewRequired(userId); } @@ -3787,14 +3801,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { private void grantRequestedRuntimePermissionsForUser(AndroidPackage pkg, int userId, String[] grantedPermissions, int callingUid, PermissionCallback callback) { - PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( - pkg.getPackageName()); - if (ps == null) { + final PermissionsState permissionsState = getPermissionsState(pkg); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()); return; } - PermissionsState permissionsState = ps.getPermissionsState(); - final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED | PackageManager.FLAG_PERMISSION_POLICY_FIXED; @@ -3838,9 +3850,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { private void setWhitelistedRestrictedPermissionsForUsers(@NonNull AndroidPackage pkg, @UserIdInt int[] userIds, @Nullable List<String> permissions, int callingUid, @PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) { - final PermissionsState permissionsState = - PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg); + final PermissionsState permissionsState = getPermissionsState(pkg); if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()); return; } @@ -3958,9 +3970,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { for (int j = 0; j < oldGrantedCount; j++) { final String permission = oldPermsForUser.valueAt(j); // Sometimes we create a new permission state instance during update. - final PermissionsState newPermissionsState = - PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, - pkg); + final PermissionsState newPermissionsState = getPermissionsState(pkg); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()); + continue; + } if (!newPermissionsState.hasPermission(permission, userId)) { callback.onPermissionRevoked(pkg.getUid(), userId, null); break; @@ -3970,12 +3984,100 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } + @UserIdInt + private int revokeSharedUserPermissionsForDeletedPackage(@NonNull PackageSetting deletedPs, + @UserIdInt int userId) { + if ((deletedPs == null) || (deletedPs.pkg == null)) { + Slog.i(TAG, "Trying to update info for null package. Just ignoring"); + return UserHandle.USER_NULL; + } + + SharedUserSetting sus = deletedPs.getSharedUser(); + + // No sharedUserId + if (sus == null) { + return UserHandle.USER_NULL; + } + + int affectedUserId = UserHandle.USER_NULL; + // Update permissions + for (String eachPerm : deletedPs.pkg.getRequestedPermissions()) { + BasePermission bp = mSettings.getPermission(eachPerm); + if (bp == null) { + continue; + } + + // Check if another package in the shared user needs the permission. + boolean used = false; + final List<AndroidPackage> pkgs = sus.getPackages(); + if (pkgs != null) { + for (AndroidPackage pkg : pkgs) { + if (pkg != null + && !pkg.getPackageName().equals(deletedPs.pkg.getPackageName()) + && pkg.getRequestedPermissions().contains(eachPerm)) { + used = true; + break; + } + } + } + if (used) { + continue; + } + + PermissionsState permissionsState = getPermissionsState(deletedPs.pkg); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + deletedPs.pkg.getPackageName()); + continue; + } + + PackageSetting disabledPs = mPackageManagerInt.getDisabledSystemPackage( + deletedPs.pkg.getPackageName()); + + // If the package is shadowing is a disabled system package, + // do not drop permissions that the shadowed package requests. + if (disabledPs != null) { + boolean reqByDisabledSysPkg = false; + for (String permission : disabledPs.pkg.getRequestedPermissions()) { + if (permission.equals(eachPerm)) { + reqByDisabledSysPkg = true; + break; + } + } + if (reqByDisabledSysPkg) { + continue; + } + } + + // Try to revoke as an install permission which is for all users. + // The package is gone - no need to keep flags for applying policy. + permissionsState.updatePermissionFlags(bp, userId, + PackageManager.MASK_PERMISSION_FLAGS_ALL, 0); + + if (permissionsState.revokeInstallPermission(bp) + == PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) { + affectedUserId = UserHandle.USER_ALL; + } + + // Try to revoke as a runtime permission which is per user. + if (permissionsState.revokeRuntimePermission(bp, userId) + == PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) { + if (affectedUserId == UserHandle.USER_NULL) { + affectedUserId = userId; + } else if (affectedUserId != userId) { + // Multiple users affected. + affectedUserId = UserHandle.USER_ALL; + } + } + } + + return affectedUserId; + } + @GuardedBy("mLock") private int[] revokeUnusedSharedUserPermissionsLocked( - SharedUserSetting suSetting, int[] allUserIds) { + List<AndroidPackage> pkgList, PermissionsState permissionsState, int[] allUserIds) { // Collect all used permissions in the UID final ArraySet<String> usedPermissions = new ArraySet<>(); - final List<AndroidPackage> pkgList = suSetting.getPackages(); if (pkgList == null || pkgList.size() == 0) { return EmptyArray.INT; } @@ -3993,7 +4095,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - PermissionsState permissionsState = suSetting.getPermissionsState(); // Prune install permissions List<PermissionState> installPermStates = permissionsState.getInstallPermissionStates(); final int installPermCount = installPermStates.size(); @@ -4279,12 +4380,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } else { mPackageManagerInt.forEachPackage(p -> { - PackageSetting ps = mPackageManagerInt.getPackageSetting( - p.getPackageName()); - if (ps == null) { + final PermissionsState permissionsState = getPermissionsState(p); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + p.getPackageName()); return; } - PermissionsState permissionsState = ps.getPermissionsState(); if (permissionsState.getInstallPermissionState(bp.getName()) != null) { permissionsState.revokeInstallPermission(bp); permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL, @@ -4695,6 +4795,67 @@ public class PermissionManagerService extends IPermissionManager.Stub { return mBackgroundPermissions; } + @Nullable + private PermissionsState getPermissionsState(@NonNull PackageSetting ps) { + return getPermissionsState(ps.getAppId()); + } + + @Nullable + private PermissionsState getPermissionsState(@NonNull AndroidPackage pkg) { + return getPermissionsState(pkg.getUid()); + } + + @Nullable + private PermissionsState getPermissionsState(int appId) { + synchronized (mLock) { + return mAppIdStates.get(appId); + } + } + + @Nullable + private PermissionsState getOrCreatePermissionsState(@NonNull PackageSetting ps) { + return getOrCreatePermissionsState(ps.getAppId()); + } + + @Nullable + private PermissionsState getOrCreatePermissionsState(int appId) { + synchronized (mLock) { + PermissionsState state = mAppIdStates.get(appId); + if (state == null) { + state = new PermissionsState(); + mAppIdStates.put(appId, state); + } + return state; + } + } + + private void removePermissionsState(int appId) { + synchronized (mLock) { + mAppIdStates.remove(appId); + } + } + + private void readPermissionsStateFromPackageSettings() { + mPackageManagerInt.forEachPackageSetting(ps -> { + synchronized (mLock) { + mAppIdStates.put(ps.getAppId(), new PermissionsState(ps.getPermissionsState())); + } + }); + } + + private void writePermissionsStateToPackageSettings() { + mPackageManagerInt.forEachPackageSetting(ps -> { + synchronized (mLock) { + final PermissionsState permissionsState = mAppIdStates.get(ps.getAppId()); + if (permissionsState == null) { + Slog.e(TAG, "Missing permissions state for " + ps.name); + return; + } + ps.getPermissionsState().copyFrom(permissionsState); + } + }); + } + private class PermissionManagerServiceInternalImpl extends PermissionManagerServiceInternal { @Override public void systemReady() { @@ -4726,6 +4887,29 @@ public class PermissionManagerService extends IPermissionManager.Stub { public void removeAllPermissions(AndroidPackage pkg, boolean chatty) { PermissionManagerService.this.removeAllPermissions(pkg, chatty); } + @Override + public void readPermissionsStateFromPackageSettingsTEMP() { + PermissionManagerService.this.readPermissionsStateFromPackageSettings(); + } + @Override + public void writePermissionsStateToPackageSettingsTEMP() { + PermissionManagerService.this.writePermissionsStateToPackageSettings(); + } + @Override + public void onUserRemoved(@UserIdInt int userId) { + PermissionManagerService.this.onUserRemoved(userId); + } + @Override + public void removePermissionsStateTEMP(int appId) { + PermissionManagerService.this.removePermissionsState(appId); + } + @Override + @UserIdInt + public int revokeSharedUserPermissionsForDeletedPackageTEMP( + @NonNull PackageSetting deletedPs, @UserIdInt int userId) { + return PermissionManagerService.this.revokeSharedUserPermissionsForDeletedPackage( + deletedPs, userId); + } @NonNull @Override public Set<String> getGrantedPermissions(@NonNull String packageName, diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java index cfa371ddbad3..f319bf495e8b 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java @@ -24,6 +24,7 @@ import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; import android.permission.PermissionManagerInternal; +import com.android.server.pm.PackageSetting; import com.android.server.pm.parsing.pkg.AndroidPackage; import java.util.ArrayList; @@ -265,6 +266,52 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty); /** + * Read {@code PermissionsState} from package settings. + * + * TODO(zhanghai): This is a temporary method because we should not expose + * {@code PackageSetting} which is a implementation detail that permission should not know. + * Instead, it should retrieve the legacy state via a defined API. + */ + public abstract void readPermissionsStateFromPackageSettingsTEMP(); + + /** + * Write {@code PermissionsState} from to settings. + * + * TODO(zhanghai): This is a temporary method and should be removed once we migrated persistence + * for permission. + */ + public abstract void writePermissionsStateToPackageSettingsTEMP(); + + /** + * Notify that a user has been removed and its permission state should be removed as well. + */ + public abstract void onUserRemoved(@UserIdInt int userId); + + /** + * Remove the {@code PermissionsState} associated with an app ID, called the same time as the + * removal of a {@code PackageSetitng}. + * + * TODO(zhanghai): This is a temporary method before we figure out a way to get notified of app + * ID removal via API. + */ + public abstract void removePermissionsStateTEMP(int appId); + + /** + * Update the shared user setting when a package with a shared user id is removed. The gids + * associated with each permission of the deleted package are removed from the shared user' + * gid list only if its not in use by other permissions of packages in the shared user setting. + * + * TODO(zhanghai): We should not need this when permission no longer sees an incomplete package + * state where the updated system package is uninstalled but the disabled system package is yet + * to be installed. Then we should handle this in restorePermissionState(). + * + * @return the affected user id, may be a real user ID, USER_ALL, or USER_NULL when none. + */ + @UserIdInt + public abstract int revokeSharedUserPermissionsForDeletedPackageTEMP( + @NonNull PackageSetting deletedPs, @UserIdInt int userId); + + /** * Get all the permissions granted to a package. */ @NonNull |