diff options
6 files changed, 67 insertions, 28 deletions
diff --git a/data/etc/platform.xml b/data/etc/platform.xml index 6659769..c517201 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -58,11 +58,11 @@ <group gid="log" /> </permission> - <permission name="android.permission.READ_EXTERNAL_STORAGE" > + <permission name="android.permission.READ_EXTERNAL_STORAGE" perUser="true" > <group gid="sdcard_r" /> </permission> - <permission name="android.permission.WRITE_EXTERNAL_STORAGE" > + <permission name="android.permission.WRITE_EXTERNAL_STORAGE" perUser="true" > <group gid="sdcard_r" /> <group gid="sdcard_rw" /> </permission> diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java index 6ad128c..4c9d7d3 100644 --- a/services/core/java/com/android/server/SystemConfig.java +++ b/services/core/java/com/android/server/SystemConfig.java @@ -71,9 +71,11 @@ public class SystemConfig { public static final class PermissionEntry { public final String name; public int[] gids; + public boolean perUser; - PermissionEntry(String _name) { - name = _name; + PermissionEntry(String name, boolean perUser) { + this.name = name; + this.perUser = perUser; } } @@ -363,14 +365,14 @@ public class SystemConfig { void readPermission(XmlPullParser parser, String name) throws IOException, XmlPullParserException { + if (mPermissions.containsKey(name)) { + throw new IllegalStateException("Duplicate permission definition for " + name); + } - name = name.intern(); + final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false); + final PermissionEntry perm = new PermissionEntry(name, perUser); + mPermissions.put(name, perm); - PermissionEntry perm = mPermissions.get(name); - if (perm == null) { - perm = new PermissionEntry(name); - mPermissions.put(name, perm); - } int outerDepth = parser.getDepth(); int type; while ((type=parser.next()) != XmlPullParser.END_DOCUMENT diff --git a/services/core/java/com/android/server/pm/BasePermission.java b/services/core/java/com/android/server/pm/BasePermission.java index 138a146..ec290ef 100644 --- a/services/core/java/com/android/server/pm/BasePermission.java +++ b/services/core/java/com/android/server/pm/BasePermission.java @@ -18,6 +18,9 @@ package com.android.server.pm; import android.content.pm.PackageParser; import android.content.pm.PermissionInfo; +import android.os.UserHandle; + +import com.android.internal.util.ArrayUtils; final class BasePermission { final static int TYPE_NORMAL = 0; @@ -40,9 +43,17 @@ final class BasePermission { PermissionInfo pendingInfo; + /** UID that owns the definition of this permission */ int uid; - int[] gids; + /** Additional GIDs given to apps granted this permission */ + private int[] gids; + + /** + * Flag indicating that {@link #gids} should be adjusted based on the + * {@link UserHandle} the granted app is running as. + */ + private boolean perUser; BasePermission(String _name, String _sourcePackage, int _type) { name = _name; @@ -52,11 +63,33 @@ final class BasePermission { protectionLevel = PermissionInfo.PROTECTION_SIGNATURE; } + @Override public String toString() { return "BasePermission{" + Integer.toHexString(System.identityHashCode(this)) + " " + name + "}"; } + public void setGids(int[] gids, boolean perUser) { + this.gids = gids; + this.perUser = perUser; + } + + public boolean hasGids() { + return ArrayUtils.isEmpty(gids); + } + + public int[] computeGids(int userId) { + if (perUser) { + final int[] userGids = new int[gids.length]; + for (int i = 0; i < gids.length; i++) { + userGids[i] = UserHandle.getUid(userId, gids[i]); + } + return userGids; + } else { + return gids; + } + } + public boolean isRuntime() { return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) == PermissionInfo.PROTECTION_DANGEROUS; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 26b29a2..668dd1a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1429,7 +1429,7 @@ public class PackageManagerService extends IPackageManager.Stub { mSettings.mPermissions.put(perm.name, bp); } if (perm.gids != null) { - bp.gids = appendInts(bp.gids, perm.gids); + bp.setGids(perm.gids, perm.perUser); } } diff --git a/services/core/java/com/android/server/pm/PermissionsState.java b/services/core/java/com/android/server/pm/PermissionsState.java index f6417ce..3e0e342 100644 --- a/services/core/java/com/android/server/pm/PermissionsState.java +++ b/services/core/java/com/android/server/pm/PermissionsState.java @@ -19,6 +19,7 @@ package com.android.server.pm; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; + import com.android.internal.util.ArrayUtils; import java.util.Arrays; @@ -214,7 +215,7 @@ public final class PermissionsState { int result = PERMISSION_OPERATION_SUCCESS; PermissionData permissionData = mPermissions.get(permission.name); - if (permissionData.getGids() != NO_GIDS) { + if (permissionData.hasGids()) { for (int userId : permissionData.getUserIds()) { if (revokePermission(permission, userId) == PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) { @@ -226,7 +227,7 @@ public final class PermissionsState { mPermissions.remove(permission.name); - return result; + return result; } /** @@ -333,7 +334,7 @@ public final class PermissionsState { continue; } PermissionData permissionData = mPermissions.valueAt(i); - final int[] permGids = permissionData.getGids(); + final int[] permGids = permissionData.computeGids(userId); if (permGids != NO_GIDS) { gids = appendInts(gids, permGids); } @@ -373,7 +374,7 @@ public final class PermissionsState { return PERMISSION_OPERATION_FAILURE; } - final boolean hasGids = permission.gids != NO_GIDS; + final boolean hasGids = permission.hasGids(); final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS; if (mPermissions == null) { @@ -382,7 +383,7 @@ public final class PermissionsState { PermissionData permissionData = mPermissions.get(permission.name); if (permissionData == null) { - permissionData = new PermissionData(permission.gids); + permissionData = new PermissionData(permission); mPermissions.put(permission.name, permissionData); } @@ -405,7 +406,7 @@ public final class PermissionsState { return PERMISSION_OPERATION_FAILURE; } - final boolean hasGids = permission.gids != NO_GIDS; + final boolean hasGids = permission.hasGids(); final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS; PermissionData permissionData = mPermissions.get(permission.name); @@ -448,17 +449,15 @@ public final class PermissionsState { } private static final class PermissionData { - private final int[] mGids; + private final BasePermission mPerm; private int[] mUserIds = USERS_NONE; - public PermissionData(int[] gids) { - mGids = !ArrayUtils.isEmpty(gids) - ? Arrays.copyOf(gids, gids.length) - : NO_GIDS; + public PermissionData(BasePermission perm) { + mPerm = perm; } public PermissionData(PermissionData other) { - this(other.mGids); + this(other.mPerm); if (other.mUserIds == USERS_ALL || other.mUserIds == USERS_NONE) { mUserIds = other.mUserIds; @@ -467,8 +466,12 @@ public final class PermissionsState { } } - public int[] getGids() { - return mGids; + public boolean hasGids() { + return mPerm.hasGids(); + } + + public int[] computeGids(int userId) { + return mPerm.computeGids(userId); } public int[] getUserIds() { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 1e0a49e..82aa74a 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -485,7 +485,7 @@ final class Settings { bp.pendingInfo.packageName = newPkg; } bp.uid = 0; - bp.gids = null; + bp.setGids(null, false); } } } @@ -3700,7 +3700,8 @@ final class Settings { pw.println("):"); pw.print(" sourcePackage="); pw.println(p.sourcePackage); pw.print(" uid="); pw.print(p.uid); - pw.print(" gids="); pw.print(PackageManagerService.arrayToString(p.gids)); + pw.print(" gids="); pw.print(Arrays.toString( + p.computeGids(UserHandle.USER_OWNER))); pw.print(" type="); pw.print(p.type); pw.print(" prot="); pw.println(PermissionInfo.protectionToString(p.protectionLevel)); |