diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-08-25 22:00:28 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-08-25 22:00:28 -0700 |
commit | 3003a017d312a55e3804d6cf4a80044b1f1d7993 (patch) | |
tree | bfd0910b8bde42c17967399981b5a347069eae18 /services | |
parent | 14e00621c81da6a0391da47afce77945b27c7231 (diff) | |
parent | 7e269644fcc319835f1e7f762f3cbd8087e3e22f (diff) | |
download | frameworks_base-3003a017d312a55e3804d6cf4a80044b1f1d7993.zip frameworks_base-3003a017d312a55e3804d6cf4a80044b1f1d7993.tar.gz frameworks_base-3003a017d312a55e3804d6cf4a80044b1f1d7993.tar.bz2 |
Merge "Don't retain global ref to last inflated context." into gingerbread
Diffstat (limited to 'services')
6 files changed, 272 insertions, 140 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index c316074..d535343 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -4294,12 +4294,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen + " when granting permission to uri " + uri); } if (targetPkg == null) { - Slog.w(TAG, "grantUriPermission: null target"); - return; + throw new IllegalArgumentException("null target"); } if (uri == null) { - Slog.w(TAG, "grantUriPermission: null uri"); - return; + throw new IllegalArgumentException("null uri"); } grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags, @@ -4451,6 +4449,56 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } + @Override + public IBinder newUriPermissionOwner(String name) { + synchronized(this) { + UriPermissionOwner owner = new UriPermissionOwner(this, name); + return owner.getExternalTokenLocked(); + } + } + + @Override + public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, + Uri uri, int modeFlags) { + synchronized(this) { + UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token); + if (owner == null) { + throw new IllegalArgumentException("Unknown owner: " + token); + } + if (fromUid != Binder.getCallingUid()) { + if (Binder.getCallingUid() != Process.myUid()) { + // Only system code can grant URI permissions on behalf + // of other users. + throw new SecurityException("nice try"); + } + } + if (targetPkg == null) { + throw new IllegalArgumentException("null target"); + } + if (uri == null) { + throw new IllegalArgumentException("null uri"); + } + + grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner); + } + } + + @Override + public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) { + synchronized(this) { + UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token); + if (owner == null) { + throw new IllegalArgumentException("Unknown owner: " + token); + } + + if (uri == null) { + owner.removeUriPermissionsLocked(mode); + } else { + owner.removeUriPermissionLocked(uri, mode); + } + } + } + public void showWaitingForDebugger(IApplicationThread who, boolean waiting) { synchronized (this) { ProcessRecord app = @@ -8260,7 +8308,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen si.deliveryCount++; if (si.targetPermissionUid >= 0) { grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid, - r.packageName, si.intent, si); + r.packageName, si.intent, si.getUriPermissionsLocked()); } if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r); bumpServiceExecutingLocked(r); diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 80a41b7..62be918 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -44,7 +44,7 @@ import java.util.HashSet; /** * An entry in the history stack, representing an activity. */ -class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwner { +class ActivityRecord extends IApplicationToken.Stub { final ActivityManagerService service; // owner final ActivityStack stack; // owner final ActivityInfo info; // all about me @@ -78,8 +78,7 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act ArrayList newIntents; // any pending new intents for single-top mode HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold - HashSet<UriPermission> readUriPermissions; // special access to reading uris. - HashSet<UriPermission> writeUriPermissions; // special access to writing uris. + UriPermissionOwner uriPermissions; // current special URI access perms. ProcessRecord app; // if non-null, hosting application Bitmap thumbnail; // icon representation of paused screen CharSequence description; // textual description of paused screen @@ -141,11 +140,15 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne if (pendingResults != null) { pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults); } - if (readUriPermissions != null) { - pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions); - } - if (writeUriPermissions != null) { - pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions); + 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); + } } pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed); pw.print(" haveState="); pw.print(haveState); @@ -301,6 +304,13 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne } } + UriPermissionOwner getUriPermissionsLocked() { + if (uriPermissions == null) { + uriPermissions = new UriPermissionOwner(service, this); + } + return uriPermissions; + } + void addResultLocked(ActivityRecord from, String resultWho, int requestCode, int resultCode, Intent resultData) { @@ -350,7 +360,7 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne intent = new Intent(intent); ar.add(intent); service.grantUriPermissionFromIntentLocked(callingUid, packageName, - intent, this); + intent, getUriPermissionsLocked()); app.thread.scheduleNewIntent(ar, this); sent = true; } catch (RemoteException e) { @@ -367,27 +377,9 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne } void removeUriPermissionsLocked() { - if (readUriPermissions != null) { - for (UriPermission perm : readUriPermissions) { - perm.readOwners.remove(this); - if (perm.readOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; - service.removeUriPermissionIfNeededLocked(perm); - } - } - readUriPermissions = null; - } - if (writeUriPermissions != null) { - for (UriPermission perm : writeUriPermissions) { - perm.writeOwners.remove(this); - if (perm.writeOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - service.removeUriPermissionIfNeededLocked(perm); - } - } - writeUriPermissions = null; + if (uriPermissions != null) { + uriPermissions.removeUriPermissionsLocked(); + uriPermissions = null; } } @@ -578,38 +570,6 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne state == ActivityState.RESUMED; } - @Override - public void addReadPermission(UriPermission perm) { - if (readUriPermissions == null) { - readUriPermissions = new HashSet<UriPermission>(); - } - readUriPermissions.add(perm); - } - - @Override - public void addWritePermission(UriPermission perm) { - if (writeUriPermissions == null) { - writeUriPermissions = new HashSet<UriPermission>(); - } - writeUriPermissions.add(perm); - } - - @Override - public void removeReadPermission(UriPermission perm) { - readUriPermissions.remove(perm); - if (readUriPermissions.size() == 0) { - readUriPermissions = null; - } - } - - @Override - public void removeWritePermission(UriPermission perm) { - writeUriPermissions.remove(perm); - if (writeUriPermissions.size() == 0) { - writeUriPermissions = null; - } - } - public String toString() { if (stringName != null) { return stringName; diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index a5f7e96..a99b48c 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -2327,12 +2327,12 @@ public class ActivityStack { if (grantedUriPermissions != null && callingUid > 0) { for (int i=0; i<grantedUriPermissions.length; i++) { mService.grantUriPermissionLocked(callingUid, r.packageName, - grantedUriPermissions[i], grantedMode, r); + grantedUriPermissions[i], grantedMode, r.getUriPermissionsLocked()); } } mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, - intent, r); + intent, r.getUriPermissionsLocked()); if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId); @@ -2557,7 +2557,7 @@ public class ActivityStack { if (callingUid > 0) { mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, - data, r); + data, r.getUriPermissionsLocked()); } if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r @@ -2885,7 +2885,7 @@ public class ActivityStack { + " res=" + resultCode + " data=" + resultData); if (r.info.applicationInfo.uid > 0) { mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid, - r.packageName, resultData, r); + r.packageName, resultData, r.getUriPermissionsLocked()); } resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, resultData); diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java index d5b050b..f35a68e 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/java/com/android/server/am/ServiceRecord.java @@ -96,7 +96,7 @@ class ServiceRecord extends Binder { String stringName; // caching of toString - static class StartItem implements UriPermissionOwner { + static class StartItem { final ServiceRecord sr; final int id; final Intent intent; @@ -104,12 +104,10 @@ class ServiceRecord extends Binder { long deliveredTime; int deliveryCount; int doneExecutingCount; + UriPermissionOwner uriPermissions; String stringName; // caching of toString - HashSet<UriPermission> readUriPermissions; // special access to reading uris. - HashSet<UriPermission> writeUriPermissions; // special access to writing uris. - StartItem(ServiceRecord _sr, int _id, Intent _intent, int _targetPermissionUid) { sr = _sr; id = _id; @@ -117,60 +115,17 @@ class ServiceRecord extends Binder { targetPermissionUid = _targetPermissionUid; } - void removeUriPermissionsLocked() { - if (readUriPermissions != null) { - for (UriPermission perm : readUriPermissions) { - perm.readOwners.remove(this); - if (perm.readOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; - sr.ams.removeUriPermissionIfNeededLocked(perm); - } - } - readUriPermissions = null; - } - if (writeUriPermissions != null) { - for (UriPermission perm : writeUriPermissions) { - perm.writeOwners.remove(this); - if (perm.writeOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - sr.ams.removeUriPermissionIfNeededLocked(perm); - } - } - writeUriPermissions = null; - } - } - - @Override - public void addReadPermission(UriPermission perm) { - if (readUriPermissions == null) { - readUriPermissions = new HashSet<UriPermission>(); + UriPermissionOwner getUriPermissionsLocked() { + if (uriPermissions == null) { + uriPermissions = new UriPermissionOwner(sr.ams, this); } - readUriPermissions.add(perm); + return uriPermissions; } - @Override - public void addWritePermission(UriPermission perm) { - if (writeUriPermissions == null) { - writeUriPermissions = new HashSet<UriPermission>(); - } - writeUriPermissions.add(perm); - } - - @Override - public void removeReadPermission(UriPermission perm) { - readUriPermissions.remove(perm); - if (readUriPermissions.size() == 0) { - readUriPermissions = null; - } - } - - @Override - public void removeWritePermission(UriPermission perm) { - writeUriPermissions.remove(perm); - if (writeUriPermissions.size() == 0) { - writeUriPermissions = null; + void removeUriPermissionsLocked() { + if (uriPermissions != null) { + uriPermissions.removeUriPermissionsLocked(); + uriPermissions = null; } } @@ -218,13 +173,15 @@ class ServiceRecord extends Binder { pw.print(prefix); pw.print(" targetPermissionUid="); pw.println(si.targetPermissionUid); } - if (si.readUriPermissions != null) { - pw.print(prefix); pw.print(" readUriPermissions="); - pw.println(si.readUriPermissions); - } - if (si.writeUriPermissions != null) { - pw.print(prefix); pw.print(" writeUriPermissions="); - pw.println(si.writeUriPermissions); + 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); + } } } } diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java index 93c59cc..c95546e 100644 --- a/services/java/com/android/server/am/UriPermission.java +++ b/services/java/com/android/server/am/UriPermission.java @@ -22,13 +22,14 @@ import android.net.Uri; import java.io.PrintWriter; import java.util.HashSet; -interface UriPermissionOwner { - void addReadPermission(UriPermission perm); - void addWritePermission(UriPermission perm); - void removeReadPermission(UriPermission perm); - void removeWritePermission(UriPermission perm); -} - +/** + * Description of a permission granted to an app to access a particular URI. + * + * CTS tests for this functionality can be run with "runtest cts-appsecurity". + * + * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert + * /src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java + */ class UriPermission { final int uid; final Uri uri; diff --git a/services/java/com/android/server/am/UriPermissionOwner.java b/services/java/com/android/server/am/UriPermissionOwner.java new file mode 100644 index 0000000..99c82e6 --- /dev/null +++ b/services/java/com/android/server/am/UriPermissionOwner.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.am; + +import android.content.Intent; +import android.net.Uri; +import android.os.Binder; +import android.os.IBinder; + +import java.util.HashSet; +import java.util.Iterator; + +class UriPermissionOwner { + final ActivityManagerService service; + final Object owner; + + Binder externalToken; + + HashSet<UriPermission> readUriPermissions; // special access to reading uris. + HashSet<UriPermission> writeUriPermissions; // special access to writing uris. + + class ExternalToken extends Binder { + UriPermissionOwner getOwner() { + return UriPermissionOwner.this; + } + } + + UriPermissionOwner(ActivityManagerService _service, Object _owner) { + service = _service; + owner = _owner; + } + + Binder getExternalTokenLocked() { + if (externalToken != null) { + externalToken = new ExternalToken(); + } + return externalToken; + } + + static UriPermissionOwner fromExternalToken(IBinder token) { + if (token instanceof ExternalToken) { + return ((ExternalToken)token).getOwner(); + } + return null; + } + + void removeUriPermissionsLocked() { + removeUriPermissionsLocked(Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + } + + void removeUriPermissionsLocked(int mode) { + if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 + && readUriPermissions != null) { + for (UriPermission perm : readUriPermissions) { + perm.readOwners.remove(this); + if (perm.readOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + } + readUriPermissions = null; + } + if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 + && writeUriPermissions != null) { + for (UriPermission perm : writeUriPermissions) { + perm.writeOwners.remove(this); + if (perm.writeOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + } + writeUriPermissions = null; + } + } + + void removeUriPermissionLocked(Uri uri, int mode) { + if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 + && readUriPermissions != null) { + Iterator<UriPermission> it = readUriPermissions.iterator(); + while (it.hasNext()) { + UriPermission perm = it.next(); + if (uri.equals(perm.uri)) { + perm.readOwners.remove(this); + if (perm.readOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + it.remove(); + } + } + if (readUriPermissions.size() == 0) { + readUriPermissions = null; + } + } + if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 + && writeUriPermissions != null) { + Iterator<UriPermission> it = writeUriPermissions.iterator(); + while (it.hasNext()) { + UriPermission perm = it.next(); + if (uri.equals(perm.uri)) { + perm.writeOwners.remove(this); + if (perm.writeOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + it.remove(); + } + } + if (writeUriPermissions.size() == 0) { + writeUriPermissions = null; + } + } + } + + public void addReadPermission(UriPermission perm) { + if (readUriPermissions == null) { + readUriPermissions = new HashSet<UriPermission>(); + } + readUriPermissions.add(perm); + } + + public void addWritePermission(UriPermission perm) { + if (writeUriPermissions == null) { + writeUriPermissions = new HashSet<UriPermission>(); + } + writeUriPermissions.add(perm); + } + + public void removeReadPermission(UriPermission perm) { + readUriPermissions.remove(perm); + if (readUriPermissions.size() == 0) { + readUriPermissions = null; + } + } + + public void removeWritePermission(UriPermission perm) { + writeUriPermissions.remove(perm); + if (writeUriPermissions.size() == 0) { + writeUriPermissions = null; + } + } + + @Override + public String toString() { + return owner.toString(); + } +} |