summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvet Ganov <svetoslavganov@google.com>2015-03-25 22:57:39 -0700
committerSvet Ganov <svetoslavganov@google.com>2015-03-25 23:48:17 -0700
commitd5752bdc8fd39d4f0a508f9088c538e30e73044a (patch)
tree3526cfdef1e846671a81778917b9f3cfc71c189d
parent4976d6b52588772117dff43fb814fe6661bfe598 (diff)
downloadframeworks_base-d5752bdc8fd39d4f0a508f9088c538e30e73044a.zip
frameworks_base-d5752bdc8fd39d4f0a508f9088c538e30e73044a.tar.gz
frameworks_base-d5752bdc8fd39d4f0a508f9088c538e30e73044a.tar.bz2
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
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java36
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java1
-rw-r--r--services/core/java/com/android/server/pm/PermissionsState.java10
-rw-r--r--services/core/java/com/android/server/pm/SettingBase.java21
-rw-r--r--services/core/java/com/android/server/pm/Settings.java13
5 files changed, 69 insertions, 12 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5d3b0f1..4dfb161 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -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,16 +7026,32 @@ 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.
- grant = GRANT_UPGRADE;
- } else {
+ final int[] updatedUserIds = ps.getPermissionsUpdatedForUserIds();
if (origPermissions.hasInstallPermission(bp.name)) {
- // For legacy apps that became modern, install becomes runtime.
+ // 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;
- } else if (replace) {
- // For upgraded modern apps keep runtime permissions unchanged.
+ upgradeUserIds = currentUserIds;
+ for (int userId : updatedUserIds) {
+ upgradeUserIds = ArrayUtils.removeInt(upgradeUserIds, userId);
+ }
+ } else {
+ // 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;
@@ -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) {
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 9e8b3df..c40784b 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -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;
diff --git a/services/core/java/com/android/server/pm/PermissionsState.java b/services/core/java/com/android/server/pm/PermissionsState.java
index 3e0e342..705abf8 100644
--- a/services/core/java/com/android/server/pm/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/PermissionsState.java
@@ -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);
}
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index d350c09..3a7b6ee 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -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
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 82aa74a..95ee990 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -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);
}