Introduce per-user GIDs for storage.

This will eventually allow us to have a single unified filesystem
instead of requiring zygote to use bind mounts.

Change-Id: I29b819ab51498b4bab874e0367b1ab4165f84025
This commit is contained in:
Jeff Sharkey
2015-03-23 16:51:22 -07:00
parent 95c1adea0c
commit 00f3904629
6 changed files with 68 additions and 29 deletions

View File

@@ -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>

View File

@@ -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 {
name = name.intern();
PermissionEntry perm = mPermissions.get(name);
if (perm == null) {
perm = new PermissionEntry(name);
mPermissions.put(name, perm);
if (mPermissions.containsKey(name)) {
throw new IllegalStateException("Duplicate permission definition for " + name);
}
final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
final PermissionEntry perm = new PermissionEntry(name, perUser);
mPermissions.put(name, perm);
int outerDepth = parser.getDepth();
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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() {

View File

@@ -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));