diff options
author | Roman Birg <roman@cyngn.com> | 2016-07-19 12:37:33 -0700 |
---|---|---|
committer | Gerrit Code Review <gerrit@cyanogenmod.org> | 2016-07-21 14:51:54 -0700 |
commit | d8d4e7c567872fa4596c2f63c85092a90b36a6b3 (patch) | |
tree | b3a78edc26abf41f5e559a3d4f8cbf5e4117776c | |
parent | 1c93b57a38aabff28a46eacd56d46bae4c803352 (diff) | |
download | frameworks_base-d8d4e7c567872fa4596c2f63c85092a90b36a6b3.zip frameworks_base-d8d4e7c567872fa4596c2f63c85092a90b36a6b3.tar.gz frameworks_base-d8d4e7c567872fa4596c2f63c85092a90b36a6b3.tar.bz2 |
PackageManager: make protected-broadcasts permission aware
This extends the <protected-broadcast> mechanism to allow protecting
actions based on a permission for system apps.
For instance:
<protected-broadcast android:name="ACTION_A"
android:permission="PERMISSION_X" />
will restrict intents with action "ACTION_A" to be only sent with
apps holding the "PERMISSION_X" permission. Note that system UIDs will
bypass the permission check and always be allowed, just like the normal
protected-broadcast mechanism.
You must still be a system application to delcare a protected broadcast.
Change-Id: Id25cffd233d400800dcb5249c5f487134e1b4152
Signed-off-by: Roman Birg <roman@cyngn.com>
5 files changed, 33 insertions, 8 deletions
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index a3329db..51f13af 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -523,4 +523,7 @@ interface IPackageManager { /** Protected Apps */ boolean isComponentProtected(in String callingPackage, in int callingUid, in ComponentName componentName, int userId); + + /** protected broadcast ext */ + boolean isProtectedBroadcastAllowed(in String actionName, in int callingUid); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 6a07b31..bb46ef0 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1877,14 +1877,18 @@ public class PackageParser { String name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name); + String permission = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_permission); + sa.recycle(); if (name != null && (flags&PARSE_IS_SYSTEM) != 0) { if (pkg.protectedBroadcasts == null) { - pkg.protectedBroadcasts = new ArrayList<String>(); + pkg.protectedBroadcasts = new ArrayMap<>(); } - if (!pkg.protectedBroadcasts.contains(name)) { - pkg.protectedBroadcasts.add(name.intern()); + if (!pkg.protectedBroadcasts.containsKey(name)) { + pkg.protectedBroadcasts.put(name.intern(), + permission != null ? permission.intern() : null); } } @@ -4519,7 +4523,10 @@ public class PackageParser { public final ArrayList<String> requestedPermissions = new ArrayList<String>(); - public ArrayList<String> protectedBroadcasts; + /** + * Maps from package -> permission, null for system (default behavior) + */ + public ArrayMap<String,String> protectedBroadcasts; public ArrayList<String> libraryNames = null; public ArrayList<String> usesLibraries = null; diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index a0b92b9..6da5941 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1595,6 +1595,7 @@ {@link #AndroidManifest manifest} tag. --> <declare-styleable name="AndroidManifestProtectedBroadcast" parent="AndroidManifest"> <attr name="name" /> + <attr name="permission" /> </declare-styleable> <!-- Private tag to declare the original package name that this package is diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 6d9ed28..17d8d47 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -16962,7 +16962,8 @@ public final class ActivityManagerService extends ActivityManagerNative } else if (callerApp == null || !callerApp.persistent) { try { if (AppGlobals.getPackageManager().isProtectedBroadcast( - intent.getAction())) { + intent.getAction()) && !AppGlobals.getPackageManager() + .isProtectedBroadcastAllowed(intent.getAction(), callingUid)) { String msg = "Permission Denial: not allowed to send broadcast " + intent.getAction() + " from pid=" + callingPid + ", uid=" + callingUid; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 95a150a..fc3d79c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -617,7 +617,7 @@ public class PackageManagerService extends IPackageManager.Stub { final ArraySet<String> mTransferedPackages = new ArraySet<String>(); // Broadcast actions that are only available to the system. - final ArraySet<String> mProtectedBroadcasts = new ArraySet<String>(); + final ArrayMap<String, String> mProtectedBroadcasts = new ArrayMap<>(); /** List of packages waiting for verification. */ final SparseArray<PackageVerificationState> mPendingVerification @@ -4041,7 +4041,19 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public boolean isProtectedBroadcast(String actionName) { synchronized (mPackages) { - return mProtectedBroadcasts.contains(actionName); + return mProtectedBroadcasts.containsKey(actionName); + } + } + + @Override + public boolean isProtectedBroadcastAllowed(String actionName, int callingUid) { + synchronized (mPackages) { + if (mProtectedBroadcasts.containsKey(actionName)) { + final int result = checkUidPermission(mProtectedBroadcasts.get(actionName), + callingUid); + return result == PackageManager.PERMISSION_GRANTED; + } + return false; } } @@ -7841,7 +7853,8 @@ public class PackageManagerService extends IPackageManager.Stub { if (pkg.protectedBroadcasts != null) { N = pkg.protectedBroadcasts.size(); for (i=0; i<N; i++) { - mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i)); + mProtectedBroadcasts.put(pkg.protectedBroadcasts.keyAt(i), + pkg.protectedBroadcasts.valueAt(i)); } } |