diff options
Diffstat (limited to 'services')
5 files changed, 266 insertions, 202 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index ecbb0d9..1bbdf3b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -17,8 +17,10 @@ package com.android.server.am; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static com.android.internal.util.XmlUtils.readBooleanAttribute; import static com.android.internal.util.XmlUtils.readIntAttribute; import static com.android.internal.util.XmlUtils.readLongAttribute; +import static com.android.internal.util.XmlUtils.writeBooleanAttribute; import static com.android.internal.util.XmlUtils.writeIntAttribute; import static com.android.internal.util.XmlUtils.writeLongAttribute; import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST; @@ -724,6 +726,7 @@ public final class ActivityManagerService extends ActivityManagerNative private static final String ATTR_URI = "uri"; private static final String ATTR_MODE_FLAGS = "modeFlags"; private static final String ATTR_CREATED_TIME = "createdTime"; + private static final String ATTR_PREFIX = "prefix"; /** * Global set of specific {@link Uri} permissions that have been granted. @@ -731,8 +734,41 @@ public final class ActivityManagerService extends ActivityManagerNative * to {@link UriPermission#uri} to {@link UriPermission}. */ @GuardedBy("this") - private final SparseArray<ArrayMap<Uri, UriPermission>> - mGrantedUriPermissions = new SparseArray<ArrayMap<Uri, UriPermission>>(); + private final SparseArray<ArrayMap<GrantUri, UriPermission>> + mGrantedUriPermissions = new SparseArray<ArrayMap<GrantUri, UriPermission>>(); + + public static class GrantUri { + public final Uri uri; + public final boolean prefix; + + public GrantUri(Uri uri, boolean prefix) { + this.uri = uri; + this.prefix = prefix; + } + + @Override + public int hashCode() { + return toString().hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof GrantUri) { + GrantUri other = (GrantUri) o; + return uri.equals(other.uri) && prefix == other.prefix; + } + return false; + } + + @Override + public String toString() { + if (prefix) { + return uri.toString() + " [prefix]"; + } else { + return uri.toString(); + } + } + } CoreSettingsObserver mCoreSettingsObserver; @@ -5822,7 +5858,7 @@ public final class ActivityManagerService extends ActivityManagerNative * in {@link ContentProvider}. */ private final boolean checkHoldingPermissionsLocked( - IPackageManager pm, ProviderInfo pi, Uri uri, int uid, int modeFlags) { + IPackageManager pm, ProviderInfo pi, Uri uri, int uid, final int modeFlags) { if (DEBUG_URI_PERMISSION) Slog.v(TAG, "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid); @@ -5918,18 +5954,17 @@ public final class ActivityManagerService extends ActivityManagerNative return pi; } - private UriPermission findUriPermissionLocked(int targetUid, Uri uri) { - ArrayMap<Uri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid); + private UriPermission findUriPermissionLocked(int targetUid, GrantUri uri) { + final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid); if (targetUris != null) { return targetUris.get(uri); - } else { - return null; } + return null; } - private UriPermission findOrCreateUriPermissionLocked( - String sourcePkg, String targetPkg, int targetUid, Uri uri) { - ArrayMap<Uri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid); + private UriPermission findOrCreateUriPermissionLocked(String sourcePkg, + String targetPkg, int targetUid, GrantUri uri) { + ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid); if (targetUris == null) { targetUris = Maps.newArrayMap(); mGrantedUriPermissions.put(targetUid, targetUris); @@ -5945,20 +5980,36 @@ public final class ActivityManagerService extends ActivityManagerNative } private final boolean checkUriPermissionLocked( - Uri uri, int uid, int modeFlags, int minStrength) { + Uri uri, int uid, final int modeFlags, int minStrength) { // Root gets to do everything. if (uid == 0) { return true; } - ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid); + + final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid); if (perms == null) return false; - UriPermission perm = perms.get(uri); - if (perm == null) return false; - return perm.getStrength(modeFlags) >= minStrength; + + // First look for exact match + final UriPermission exactPerm = perms.get(new GrantUri(uri, false)); + if (exactPerm != null && exactPerm.getStrength(modeFlags) >= minStrength) { + return true; + } + + // No exact match, look for prefixes + final int N = perms.size(); + for (int i = 0; i < N; i++) { + final UriPermission perm = perms.valueAt(i); + if (perm.uri.prefix && uri.isPathPrefixMatch(perm.uri.uri) + && perm.getStrength(modeFlags) >= minStrength) { + return true; + } + } + + return false; } @Override - public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) { + public int checkUriPermission(Uri uri, int pid, int uid, final int modeFlags) { enforceNotIsolatedCaller("checkUriPermission"); // Another redirected-binder-call permissions check as in @@ -5990,11 +6041,8 @@ public final class ActivityManagerService extends ActivityManagerNative * lastTargetUid else set that to -1. */ int checkGrantUriPermissionLocked(int callingUid, String targetPkg, - Uri uri, int modeFlags, int lastTargetUid) { - final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0; - modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION - | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - if (modeFlags == 0) { + Uri uri, final int modeFlags, int lastTargetUid) { + if (!Intent.isAccessUriMode(modeFlags)) { return -1; } @@ -6089,6 +6137,8 @@ public final class ActivityManagerService extends ActivityManagerNative if (callingUid != Process.myUid()) { if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) { // Require they hold a strong enough Uri permission + final boolean persistable = + (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0; final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE : UriPermission.STRENGTH_OWNED; if (!checkUriPermissionLocked(uri, callingUid, modeFlags, minStrength)) { @@ -6103,19 +6153,16 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public int checkGrantUriPermission(int callingUid, String targetPkg, - Uri uri, int modeFlags) { + Uri uri, final int modeFlags) { enforceNotIsolatedCaller("checkGrantUriPermission"); synchronized(this) { return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags, -1); } } - void grantUriPermissionUncheckedLocked( - int targetUid, String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) { - final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0; - modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION - | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - if (modeFlags == 0) { + void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg, Uri uri, + final int modeFlags, UriPermissionOwner owner) { + if (!Intent.isAccessUriMode(modeFlags)) { return; } @@ -6133,13 +6180,14 @@ public final class ActivityManagerService extends ActivityManagerNative return; } + final boolean prefix = (modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0; final UriPermission perm = findOrCreateUriPermissionLocked( - pi.packageName, targetPkg, targetUid, uri); - perm.grantModes(modeFlags, persistable, owner); + pi.packageName, targetPkg, targetUid, new GrantUri(uri, prefix)); + perm.grantModes(modeFlags, owner); } void grantUriPermissionLocked(int callingUid, String targetPkg, Uri uri, - int modeFlags, UriPermissionOwner owner) { + final int modeFlags, UriPermissionOwner owner) { if (targetPkg == null) { throw new NullPointerException("targetPkg"); } @@ -6253,7 +6301,7 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public void grantUriPermission(IApplicationThread caller, String targetPkg, - Uri uri, int modeFlags) { + Uri uri, final int modeFlags) { enforceNotIsolatedCaller("grantUriPermission"); synchronized(this) { final ProcessRecord r = getRecordForAppLocked(caller); @@ -6269,32 +6317,32 @@ public final class ActivityManagerService extends ActivityManagerNative throw new IllegalArgumentException("null uri"); } - // Persistable only supported through Intents - Preconditions.checkFlagsArgument(modeFlags, - Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + Preconditions.checkFlagsArgument(modeFlags, Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION + | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION + | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); - grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags, - null); + grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags, null); } } void removeUriPermissionIfNeededLocked(UriPermission perm) { - if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION - |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) { - ArrayMap<Uri, UriPermission> perms - = mGrantedUriPermissions.get(perm.targetUid); + if (perm.modeFlags == 0) { + final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get( + perm.targetUid); if (perms != null) { if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Removing " + perm.targetUid + " permission to " + perm.uri); + perms.remove(perm.uri); - if (perms.size() == 0) { + if (perms.isEmpty()) { mGrantedUriPermissions.remove(perm.targetUid); } } } } - private void revokeUriPermissionLocked(int callingUid, Uri uri, int modeFlags) { + private void revokeUriPermissionLocked(int callingUid, Uri uri, final int modeFlags) { if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Revoking all granted permissions to " + uri); final IPackageManager pm = AppGlobals.getPackageManager(); @@ -6318,46 +6366,29 @@ public final class ActivityManagerService extends ActivityManagerNative boolean persistChanged = false; // Go through all of the permissions and remove any that match. - final List<String> SEGMENTS = uri.getPathSegments(); - if (SEGMENTS != null) { - final int NS = SEGMENTS.size(); - int N = mGrantedUriPermissions.size(); - for (int i=0; i<N; i++) { - ArrayMap<Uri, UriPermission> perms - = mGrantedUriPermissions.valueAt(i); - Iterator<UriPermission> it = perms.values().iterator(); - toploop: - while (it.hasNext()) { - UriPermission perm = it.next(); - Uri targetUri = perm.uri; - if (!authority.equals(targetUri.getAuthority())) { - continue; - } - List<String> targetSegments = targetUri.getPathSegments(); - if (targetSegments == null) { - continue; - } - if (targetSegments.size() < NS) { - continue; - } - for (int j=0; j<NS; j++) { - if (!SEGMENTS.get(j).equals(targetSegments.get(j))) { - continue toploop; - } - } - if (DEBUG_URI_PERMISSION) Slog.v(TAG, - "Revoking " + perm.targetUid + " permission to " + perm.uri); - persistChanged |= perm.clearModes(modeFlags, true); + int N = mGrantedUriPermissions.size(); + for (int i = 0; i < N; i++) { + final int targetUid = mGrantedUriPermissions.keyAt(i); + final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i); + + for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) { + final UriPermission perm = it.next(); + if (perm.uri.uri.isPathPrefixMatch(uri)) { + if (DEBUG_URI_PERMISSION) + Slog.v(TAG, + "Revoking " + perm.targetUid + " permission to " + perm.uri); + persistChanged |= perm.revokeModes( + modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); if (perm.modeFlags == 0) { it.remove(); } } - if (perms.size() == 0) { - mGrantedUriPermissions.remove( - mGrantedUriPermissions.keyAt(i)); - N--; - i--; - } + } + + if (perms.isEmpty()) { + mGrantedUriPermissions.remove(targetUid); + N--; + i--; } } @@ -6368,7 +6399,7 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public void revokeUriPermission(IApplicationThread caller, Uri uri, - int modeFlags) { + final int modeFlags) { enforceNotIsolatedCaller("revokeUriPermission"); synchronized(this) { final ProcessRecord r = getRecordForAppLocked(caller); @@ -6382,9 +6413,7 @@ public final class ActivityManagerService extends ActivityManagerNative return; } - modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION - | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - if (modeFlags == 0) { + if (!Intent.isAccessUriMode(modeFlags)) { return; } @@ -6419,20 +6448,22 @@ public final class ActivityManagerService extends ActivityManagerNative boolean persistChanged = false; - final int size = mGrantedUriPermissions.size(); - for (int i = 0; i < size; i++) { + int N = mGrantedUriPermissions.size(); + for (int i = 0; i < N; i++) { + final int targetUid = mGrantedUriPermissions.keyAt(i); + final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i); + // Only inspect grants matching user if (userHandle == UserHandle.USER_ALL - || userHandle == UserHandle.getUserId(mGrantedUriPermissions.keyAt(i))) { - final Iterator<UriPermission> it = mGrantedUriPermissions.valueAt(i) - .values().iterator(); - while (it.hasNext()) { + || userHandle == UserHandle.getUserId(targetUid)) { + for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) { final UriPermission perm = it.next(); // Only inspect grants matching package if (packageName == null || perm.sourcePkg.equals(packageName) || perm.targetPkg.equals(packageName)) { - persistChanged |= perm.clearModes(~0, persistable); + persistChanged |= perm.revokeModes( + persistable ? ~0 : ~Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); // Only remove when no modes remain; any persisted grants // will keep this alive. @@ -6441,6 +6472,12 @@ public final class ActivityManagerService extends ActivityManagerNative } } } + + if (perms.isEmpty()) { + mGrantedUriPermissions.remove(targetUid); + N--; + i--; + } } } @@ -6460,7 +6497,7 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, - Uri uri, int modeFlags) { + Uri uri, final int modeFlags) { synchronized(this) { UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token); if (owner == null) { @@ -6514,8 +6551,9 @@ public final class ActivityManagerService extends ActivityManagerNative ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList(); synchronized (this) { final int size = mGrantedUriPermissions.size(); - for (int i = 0 ; i < size; i++) { - for (UriPermission perm : mGrantedUriPermissions.valueAt(i).values()) { + for (int i = 0; i < size; i++) { + final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i); + for (UriPermission perm : perms.values()) { if (perm.persistedModeFlags != 0) { persist.add(perm.snapshot()); } @@ -6536,7 +6574,8 @@ public final class ActivityManagerService extends ActivityManagerNative writeIntAttribute(out, ATTR_USER_HANDLE, perm.userHandle); out.attribute(null, ATTR_SOURCE_PKG, perm.sourcePkg); out.attribute(null, ATTR_TARGET_PKG, perm.targetPkg); - out.attribute(null, ATTR_URI, String.valueOf(perm.uri)); + out.attribute(null, ATTR_URI, String.valueOf(perm.uri.uri)); + writeBooleanAttribute(out, ATTR_PREFIX, perm.uri.prefix); writeIntAttribute(out, ATTR_MODE_FLAGS, perm.persistedModeFlags); writeLongAttribute(out, ATTR_CREATED_TIME, perm.persistedCreateTime); out.endTag(null, TAG_URI_GRANT); @@ -6572,6 +6611,7 @@ public final class ActivityManagerService extends ActivityManagerNative final String sourcePkg = in.getAttributeValue(null, ATTR_SOURCE_PKG); final String targetPkg = in.getAttributeValue(null, ATTR_TARGET_PKG); final Uri uri = Uri.parse(in.getAttributeValue(null, ATTR_URI)); + final boolean prefix = readBooleanAttribute(in, ATTR_PREFIX); final int modeFlags = readIntAttribute(in, ATTR_MODE_FLAGS); final long createdTime = readLongAttribute(in, ATTR_CREATED_TIME, now); @@ -6587,7 +6627,7 @@ public final class ActivityManagerService extends ActivityManagerNative } if (targetUid != -1) { final UriPermission perm = findOrCreateUriPermissionLocked( - sourcePkg, targetPkg, targetUid, uri); + sourcePkg, targetPkg, targetUid, new GrantUri(uri, prefix)); perm.initPersistedModes(modeFlags, createdTime); } } else { @@ -6609,7 +6649,7 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public void takePersistableUriPermission(Uri uri, int modeFlags) { + public void takePersistableUriPermission(Uri uri, final int modeFlags) { enforceNotIsolatedCaller("takePersistableUriPermission"); Preconditions.checkFlagsArgument(modeFlags, @@ -6617,13 +6657,28 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { final int callingUid = Binder.getCallingUid(); - final UriPermission perm = findUriPermissionLocked(callingUid, uri); - if (perm == null) { - throw new SecurityException("No permission grant found for UID " + callingUid - + " and Uri " + uri.toSafeString()); + boolean persistChanged = false; + + UriPermission exactPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, false)); + UriPermission prefixPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, true)); + + final boolean exactValid = (exactPerm != null) + && ((modeFlags & exactPerm.persistableModeFlags) == modeFlags); + final boolean prefixValid = (prefixPerm != null) + && ((modeFlags & prefixPerm.persistableModeFlags) == modeFlags); + + if (!(exactValid || prefixValid)) { + throw new SecurityException("No persistable permission grants found for UID " + + callingUid + " and Uri " + uri.toSafeString()); + } + + if (exactValid) { + persistChanged |= exactPerm.takePersistableModes(modeFlags); + } + if (prefixValid) { + persistChanged |= prefixPerm.takePersistableModes(modeFlags); } - boolean persistChanged = perm.takePersistableModes(modeFlags); persistChanged |= maybePrunePersistedUriGrantsLocked(callingUid); if (persistChanged) { @@ -6633,7 +6688,7 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public void releasePersistableUriPermission(Uri uri, int modeFlags) { + public void releasePersistableUriPermission(Uri uri, final int modeFlags) { enforceNotIsolatedCaller("releasePersistableUriPermission"); Preconditions.checkFlagsArgument(modeFlags, @@ -6641,16 +6696,24 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { final int callingUid = Binder.getCallingUid(); + boolean persistChanged = false; - final UriPermission perm = findUriPermissionLocked(callingUid, uri); - if (perm == null) { - Slog.w(TAG, "No permission grant found for UID " + callingUid + " and Uri " - + uri.toSafeString()); - return; + UriPermission exactPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, false)); + UriPermission prefixPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, true)); + if (exactPerm == null && prefixPerm == null) { + throw new SecurityException("No permission grants found for UID " + callingUid + + " and Uri " + uri.toSafeString()); + } + + if (exactPerm != null) { + persistChanged |= exactPerm.releasePersistableModes(modeFlags); + removeUriPermissionIfNeededLocked(exactPerm); + } + if (prefixPerm != null) { + persistChanged |= prefixPerm.releasePersistableModes(modeFlags); + removeUriPermissionIfNeededLocked(prefixPerm); } - final boolean persistChanged = perm.releasePersistableModes(modeFlags); - removeUriPermissionIfNeededLocked(perm); if (persistChanged) { schedulePersistUriGrants(); } @@ -6664,7 +6727,7 @@ public final class ActivityManagerService extends ActivityManagerNative * @return if any mutations occured that require persisting. */ private boolean maybePrunePersistedUriGrantsLocked(int uid) { - final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid); + final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid); if (perms == null) return false; if (perms.size() < MAX_PERSISTED_URI_GRANTS) return false; @@ -6714,13 +6777,12 @@ public final class ActivityManagerService extends ActivityManagerNative final ArrayList<android.content.UriPermission> result = Lists.newArrayList(); synchronized (this) { if (incoming) { - final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid); + final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get( + callingUid); if (perms == null) { Slog.w(TAG, "No permission grants found for " + packageName); } else { - final int size = perms.size(); - for (int i = 0; i < size; i++) { - final UriPermission perm = perms.valueAt(i); + for (UriPermission perm : perms.values()) { if (packageName.equals(perm.targetPkg) && perm.persistedModeFlags != 0) { result.add(perm.buildPersistedPublicApiObject()); } @@ -6729,10 +6791,9 @@ public final class ActivityManagerService extends ActivityManagerNative } else { final int size = mGrantedUriPermissions.size(); for (int i = 0; i < size; i++) { - final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.valueAt(i); - final int permsSize = perms.size(); - for (int j = 0; j < permsSize; j++) { - final UriPermission perm = perms.valueAt(j); + final ArrayMap<GrantUri, UriPermission> perms = + mGrantedUriPermissions.valueAt(i); + for (UriPermission perm : perms.values()) { if (packageName.equals(perm.sourcePkg) && perm.persistedModeFlags != 0) { result.add(perm.buildPersistedPublicApiObject()); } @@ -7602,11 +7663,11 @@ public final class ActivityManagerService extends ActivityManagerNative } } } - - ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid); + + final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid); if (perms != null) { - for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) { - if (uri.getKey().getAuthority().equals(cpi.authority)) { + for (GrantUri uri : perms.keySet()) { + if (uri.uri.getAuthority().equals(cpi.authority)) { return null; } } @@ -11573,8 +11634,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (dumpUid >= -1 && UserHandle.getAppId(uid) != dumpUid) { continue; } - ArrayMap<Uri, UriPermission> perms - = mGrantedUriPermissions.valueAt(i); + final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i); if (!printed) { if (needSep) pw.println(); needSep = true; @@ -11582,8 +11642,7 @@ public final class ActivityManagerService extends ActivityManagerNative printed = true; printedAnything = true; } - pw.print(" * UID "); pw.print(uid); - pw.println(" holds:"); + pw.print(" * UID "); pw.print(uid); pw.println(" holds:"); for (UriPermission perm : perms.values()) { pw.print(" "); pw.println(perm); if (dumpAll) { diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 60adfb0..3e59def 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -215,14 +215,7 @@ final class ActivityRecord { pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions); } if (uriPermissions != null) { - if (uriPermissions.readUriPermissions != null) { - pw.print(prefix); pw.print("readUriPermissions="); - pw.println(uriPermissions.readUriPermissions); - } - if (uriPermissions.writeUriPermissions != null) { - pw.print(prefix); pw.print("writeUriPermissions="); - pw.println(uriPermissions.writeUriPermissions); - } + uriPermissions.dump(pw, prefix); } pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed); pw.print(" launchCount="); pw.print(launchCount); diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 363a9b7..e54c95e 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -193,14 +193,7 @@ final class ServiceRecord extends Binder { pw.println(si.neededGrants); } if (si.uriPermissions != null) { - if (si.uriPermissions.readUriPermissions != null) { - pw.print(prefix); pw.print(" readUriPermissions="); - pw.println(si.uriPermissions.readUriPermissions); - } - if (si.uriPermissions.writeUriPermissions != null) { - pw.print(prefix); pw.print(" writeUriPermissions="); - pw.println(si.uriPermissions.writeUriPermissions); - } + si.uriPermissions.dump(pw, prefix); } } } diff --git a/services/core/java/com/android/server/am/UriPermission.java b/services/core/java/com/android/server/am/UriPermission.java index 1f12b74..4970b8d 100644 --- a/services/core/java/com/android/server/am/UriPermission.java +++ b/services/core/java/com/android/server/am/UriPermission.java @@ -17,15 +17,16 @@ package com.android.server.am; import android.content.Intent; -import android.net.Uri; import android.os.UserHandle; +import android.util.ArraySet; import android.util.Log; +import android.util.Slog; +import com.android.server.am.ActivityManagerService.GrantUri; import com.google.android.collect.Sets; import java.io.PrintWriter; import java.util.Comparator; -import java.util.HashSet; /** * Description of a permission granted to an app to access a particular URI. @@ -50,7 +51,7 @@ final class UriPermission { /** Cached UID of {@link #targetPkg}; should not be persisted */ final int targetUid; - final Uri uri; + final GrantUri uri; /** * Allowed modes. All permission enforcement should use this field. Must @@ -61,12 +62,13 @@ final class UriPermission { */ int modeFlags = 0; - /** Allowed modes with explicit owner. */ + /** Allowed modes with active owner. */ int ownedModeFlags = 0; /** Allowed modes without explicit owner. */ int globalModeFlags = 0; /** Allowed modes that have been offered for possible persisting. */ int persistableModeFlags = 0; + /** Allowed modes that should be persisted across device boots. */ int persistedModeFlags = 0; @@ -78,12 +80,12 @@ final class UriPermission { private static final long INVALID_TIME = Long.MIN_VALUE; - private HashSet<UriPermissionOwner> mReadOwners; - private HashSet<UriPermissionOwner> mWriteOwners; + private ArraySet<UriPermissionOwner> mReadOwners; + private ArraySet<UriPermissionOwner> mWriteOwners; private String stringName; - UriPermission(String sourcePkg, String targetPkg, int targetUid, Uri uri) { + UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) { this.userHandle = UserHandle.getUserId(targetUid); this.sourcePkg = sourcePkg; this.targetPkg = targetPkg; @@ -100,6 +102,9 @@ final class UriPermission { * global or owner grants. */ void initPersistedModes(int modeFlags, long createdTime) { + modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + persistableModeFlags = modeFlags; persistedModeFlags = modeFlags; persistedCreateTime = createdTime; @@ -107,7 +112,11 @@ final class UriPermission { updateModeFlags(); } - void grantModes(int modeFlags, boolean persistable, UriPermissionOwner owner) { + void grantModes(int modeFlags, UriPermissionOwner owner) { + final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0; + modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + if (persistable) { persistableModeFlags |= modeFlags; } @@ -130,10 +139,14 @@ final class UriPermission { * @return if mode changes should trigger persisting. */ boolean takePersistableModes(int modeFlags) { + modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + if ((modeFlags & persistableModeFlags) != modeFlags) { - throw new SecurityException("Requested flags 0x" + Slog.w(TAG, "Requested flags 0x" + Integer.toHexString(modeFlags) + ", but only 0x" + Integer.toHexString(persistableModeFlags) + " are allowed"); + return false; } final int before = persistedModeFlags; @@ -148,6 +161,9 @@ final class UriPermission { } boolean releasePersistableModes(int modeFlags) { + modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + final int before = persistedModeFlags; persistableModeFlags &= ~modeFlags; @@ -164,7 +180,11 @@ final class UriPermission { /** * @return if mode changes should trigger persisting. */ - boolean clearModes(int modeFlags, boolean persistable) { + boolean revokeModes(int modeFlags) { + final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0; + modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + final int before = persistedModeFlags; if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { @@ -208,6 +228,8 @@ final class UriPermission { * Return strength of this permission grant for the given flags. */ public int getStrength(int modeFlags) { + modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); if ((persistableModeFlags & modeFlags) == modeFlags) { return STRENGTH_PERSISTABLE; } else if ((globalModeFlags & modeFlags) == modeFlags) { @@ -221,7 +243,7 @@ final class UriPermission { private void addReadOwner(UriPermissionOwner owner) { if (mReadOwners == null) { - mReadOwners = Sets.newHashSet(); + mReadOwners = Sets.newArraySet(); ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION; updateModeFlags(); } @@ -246,7 +268,7 @@ final class UriPermission { private void addWriteOwner(UriPermissionOwner owner) { if (mWriteOwners == null) { - mWriteOwners = Sets.newHashSet(); + mWriteOwners = Sets.newArraySet(); ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION; updateModeFlags(); } @@ -333,7 +355,7 @@ final class UriPermission { final int userHandle; final String sourcePkg; final String targetPkg; - final Uri uri; + final GrantUri uri; final int persistedModeFlags; final long persistedCreateTime; @@ -352,6 +374,6 @@ final class UriPermission { } public android.content.UriPermission buildPersistedPublicApiObject() { - return new android.content.UriPermission(uri, persistedModeFlags, persistedCreateTime); + return new android.content.UriPermission(uri.uri, persistedModeFlags, persistedCreateTime); } } diff --git a/services/core/java/com/android/server/am/UriPermissionOwner.java b/services/core/java/com/android/server/am/UriPermissionOwner.java index 7bbd3bc..65d7047 100644 --- a/services/core/java/com/android/server/am/UriPermissionOwner.java +++ b/services/core/java/com/android/server/am/UriPermissionOwner.java @@ -20,8 +20,11 @@ import android.content.Intent; import android.net.Uri; import android.os.Binder; import android.os.IBinder; +import android.util.ArraySet; -import java.util.HashSet; +import com.google.android.collect.Sets; + +import java.io.PrintWriter; import java.util.Iterator; final class UriPermissionOwner { @@ -30,8 +33,8 @@ final class UriPermissionOwner { Binder externalToken; - HashSet<UriPermission> readUriPermissions; // special access to reading uris. - HashSet<UriPermission> writeUriPermissions; // special access to writing uris. + private ArraySet<UriPermission> mReadPerms; + private ArraySet<UriPermission> mWritePerms; class ExternalToken extends Binder { UriPermissionOwner getOwner() { @@ -39,9 +42,9 @@ final class UriPermissionOwner { } } - UriPermissionOwner(ActivityManagerService _service, Object _owner) { - service = _service; - owner = _owner; + UriPermissionOwner(ActivityManagerService service, Object owner) { + this.service = service; + this.owner = owner; } Binder getExternalTokenLocked() { @@ -64,82 +67,76 @@ final class UriPermissionOwner { } void removeUriPermissionsLocked(int mode) { - if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 - && readUriPermissions != null) { - for (UriPermission perm : readUriPermissions) { - perm.removeReadOwner(this); - service.removeUriPermissionIfNeededLocked(perm); - } - readUriPermissions = null; - } - if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 - && writeUriPermissions != null) { - for (UriPermission perm : writeUriPermissions) { - perm.removeWriteOwner(this); - service.removeUriPermissionIfNeededLocked(perm); - } - writeUriPermissions = null; - } + removeUriPermissionLocked(null, mode); } void removeUriPermissionLocked(Uri uri, int mode) { - if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 - && readUriPermissions != null) { - Iterator<UriPermission> it = readUriPermissions.iterator(); + if ((mode & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 + && mReadPerms != null) { + Iterator<UriPermission> it = mReadPerms.iterator(); while (it.hasNext()) { UriPermission perm = it.next(); - if (uri.equals(perm.uri)) { + if (uri == null || uri.equals(perm.uri)) { perm.removeReadOwner(this); service.removeUriPermissionIfNeededLocked(perm); it.remove(); } } - if (readUriPermissions.size() == 0) { - readUriPermissions = null; + if (mReadPerms.isEmpty()) { + mReadPerms = null; } } - if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 - && writeUriPermissions != null) { - Iterator<UriPermission> it = writeUriPermissions.iterator(); + if ((mode & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 + && mWritePerms != null) { + Iterator<UriPermission> it = mWritePerms.iterator(); while (it.hasNext()) { UriPermission perm = it.next(); - if (uri.equals(perm.uri)) { + if (uri == null || uri.equals(perm.uri)) { perm.removeWriteOwner(this); service.removeUriPermissionIfNeededLocked(perm); it.remove(); } } - if (writeUriPermissions.size() == 0) { - writeUriPermissions = null; + if (mWritePerms.isEmpty()) { + mWritePerms = null; } } } public void addReadPermission(UriPermission perm) { - if (readUriPermissions == null) { - readUriPermissions = new HashSet<UriPermission>(); + if (mReadPerms == null) { + mReadPerms = Sets.newArraySet(); } - readUriPermissions.add(perm); + mReadPerms.add(perm); } public void addWritePermission(UriPermission perm) { - if (writeUriPermissions == null) { - writeUriPermissions = new HashSet<UriPermission>(); + if (mWritePerms == null) { + mWritePerms = Sets.newArraySet(); } - writeUriPermissions.add(perm); + mWritePerms.add(perm); } public void removeReadPermission(UriPermission perm) { - readUriPermissions.remove(perm); - if (readUriPermissions.size() == 0) { - readUriPermissions = null; + mReadPerms.remove(perm); + if (mReadPerms.isEmpty()) { + mReadPerms = null; } } public void removeWritePermission(UriPermission perm) { - writeUriPermissions.remove(perm); - if (writeUriPermissions.size() == 0) { - writeUriPermissions = null; + mWritePerms.remove(perm); + if (mWritePerms.isEmpty()) { + mWritePerms = null; + } + } + + public void dump(PrintWriter pw, String prefix) { + if (mReadPerms != null) { + pw.print(prefix); pw.print("readUriPermissions="); pw.println(mReadPerms); + } + if (mWritePerms != null) { + pw.print(prefix); pw.print("writeUriPermissions="); pw.println(mWritePerms); } } |