summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Todd Kennedy <toddke@google.com> 2018-05-29 15:18:06 -0700
committer Todd Kennedy <toddke@google.com> 2018-05-30 13:56:17 -0700
commitef9acb6ed97ececa4c8554adb693ec948a963db1 (patch)
tree88965c52e964c34056ba99735d7f2a66577c45fc
parente3348a25935099838a917cf4556c4dccc714e0ef (diff)
Ensure permission held for MATCH_KNOWN_PACKAGES
There's an escape clause that passes the cross user permissions if the caller UID is identical to the target user ID [eg. we're not operating across users]. However, the method getInstalledPackagesList() uses android.permission.INTERACT_ACROSS_USERS to filter the results and a calling UID check is not sufficient. Ensuure the permission is actually held, regardless of the calling UID or target user. Change-Id: Iebf88668766d387a15246d6eea6420610665105a Fixes: 80435086 Test: atest CtsAppSecurityHostTestCases:ApplicationVisibilityTest
-rw-r--r--api/test-current.txt2
-rw-r--r--core/java/android/content/pm/PackageManager.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java6
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java34
5 files changed, 42 insertions, 10 deletions
diff --git a/api/test-current.txt b/api/test-current.txt
index ba2e4ecd53be..adb06c79eaf5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -248,6 +248,7 @@ package android.content.pm {
public abstract class PackageManager {
method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
method public abstract int getInstallReason(java.lang.String, android.os.UserHandle);
+ method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
method public abstract java.lang.String[] getNamesForUids(int[]);
method public abstract java.lang.String getPermissionControllerPackageName();
method public abstract java.lang.String getServicesSystemSharedLibraryPackageName();
@@ -256,6 +257,7 @@ package android.content.pm {
field public static final java.lang.String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
field public static final java.lang.String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
+ field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
}
public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 63de8bf49f8b..3f9798b7d6c9 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -461,6 +461,7 @@ public abstract class PackageManager {
* package.
* @hide
*/
+ @TestApi
public static final int MATCH_KNOWN_PACKAGES = MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER;
/**
@@ -3420,6 +3421,7 @@ public abstract class PackageManager {
* deleted with {@code DONT_DELETE_DATA} flag set).
* @hide
*/
+ @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public abstract List<PackageInfo> getInstalledPackagesAsUser(@PackageInfoFlags int flags,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d496ab67fec4..7b7bc41e4bbb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4786,8 +4786,10 @@ public class PackageManagerService extends IPackageManager.Stub
triaged = false;
}
if ((flags & PackageManager.MATCH_ANY_USER) != 0) {
+ // require the permission to be held; the calling uid and given user id referring
+ // to the same user is not sufficient
mPermissionManager.enforceCrossUserPermission(
- Binder.getCallingUid(), userId, false, false,
+ Binder.getCallingUid(), userId, false, false, true,
"MATCH_ANY_USER flag requires INTERACT_ACROSS_USERS permission at "
+ Debug.getCallers(5));
} else if ((flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0 && isCallerSystemUser
@@ -7871,7 +7873,7 @@ public class PackageManagerService extends IPackageManager.Stub
flags = updateFlagsForPackage(flags, userId, null);
final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
- true /* requireFullPermission */, false /* checkShell */,
+ false /* requireFullPermission */, false /* checkShell */,
"get installed packages");
// writer
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
index 2bd5b6793b10..a042fedf8b47 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
@@ -174,6 +174,14 @@ public abstract class PermissionManagerInternal {
*/
public abstract void enforceCrossUserPermission(int callingUid, int userId,
boolean requireFullPermission, boolean checkShell, @NonNull String message);
+ /**
+ * @see #enforceCrossUserPermission(int, int, boolean, boolean, String)
+ * @param requirePermissionWhenSameUser When {@code true}, still require the cross user
+ * permission to be held even if the callingUid and userId reference the same user.
+ */
+ public abstract void enforceCrossUserPermission(int callingUid, int userId,
+ boolean requireFullPermission, boolean checkShell,
+ boolean requirePermissionWhenSameUser, @NonNull String message);
public abstract void enforceGrantRevokeRuntimePermissionPermissions(@NonNull String message);
public abstract @NonNull PermissionSettings getPermissionSettings();
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 36fc1202006f..c51a72406b53 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1381,7 +1381,9 @@ public class PermissionManagerService {
"grantRuntimePermission");
enforceCrossUserPermission(callingUid, userId,
- true /* requireFullPermission */, true /* checkShell */,
+ true, // requireFullPermission
+ true, // checkShell
+ false, // requirePermissionWhenSameUser
"grantRuntimePermission");
final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
@@ -1501,7 +1503,9 @@ public class PermissionManagerService {
"revokeRuntimePermission");
enforceCrossUserPermission(Binder.getCallingUid(), userId,
- true /* requireFullPermission */, true /* checkShell */,
+ true, // requireFullPermission
+ true, // checkShell
+ false, // requirePermissionWhenSameUser
"revokeRuntimePermission");
final int appId;
@@ -1658,7 +1662,9 @@ public class PermissionManagerService {
enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
enforceCrossUserPermission(callingUid, userId,
- true /* requireFullPermission */, false /* checkShell */,
+ true, // requireFullPermission
+ false, // checkShell
+ false, // requirePermissionWhenSameUser
"getPermissionFlags");
final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
@@ -1849,7 +1855,9 @@ public class PermissionManagerService {
enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
enforceCrossUserPermission(callingUid, userId,
- true /* requireFullPermission */, true /* checkShell */,
+ true, // requireFullPermission
+ true, // checkShell
+ false, // requirePermissionWhenSameUser
"updatePermissionFlags");
// Only the system can change these flags and nothing else.
@@ -1904,7 +1912,9 @@ public class PermissionManagerService {
enforceGrantRevokeRuntimePermissionPermissions(
"updatePermissionFlagsForAllApps");
enforceCrossUserPermission(callingUid, userId,
- true /* requireFullPermission */, true /* checkShell */,
+ true, // requireFullPermission
+ true, // checkShell
+ false, // requirePermissionWhenSameUser
"updatePermissionFlagsForAllApps");
// Only the system can change system fixed flags.
@@ -1944,7 +1954,8 @@ public class PermissionManagerService {
* @param message the message to log on security exception
*/
private void enforceCrossUserPermission(int callingUid, int userId,
- boolean requireFullPermission, boolean checkShell, String message) {
+ boolean requireFullPermission, boolean checkShell,
+ boolean requirePermissionWhenSameUser, String message) {
if (userId < 0) {
throw new IllegalArgumentException("Invalid userId " + userId);
}
@@ -1952,7 +1963,7 @@ public class PermissionManagerService {
PackageManagerServiceUtils.enforceShellRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
}
- if (userId == UserHandle.getUserId(callingUid)) return;
+ if (!requirePermissionWhenSameUser && userId == UserHandle.getUserId(callingUid)) return;
if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
if (requireFullPermission) {
mContext.enforceCallingOrSelfPermission(
@@ -2139,7 +2150,14 @@ public class PermissionManagerService {
public void enforceCrossUserPermission(int callingUid, int userId,
boolean requireFullPermission, boolean checkShell, String message) {
PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,
- requireFullPermission, checkShell, message);
+ requireFullPermission, checkShell, false, message);
+ }
+ @Override
+ public void enforceCrossUserPermission(int callingUid, int userId,
+ boolean requireFullPermission, boolean checkShell,
+ boolean requirePermissionWhenSameUser, String message) {
+ PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,
+ requireFullPermission, checkShell, requirePermissionWhenSameUser, message);
}
@Override
public void enforceGrantRevokeRuntimePermissionPermissions(String message) {