Add role as a new permission protection flag.
Permissions with the role protection flag will be able to be managed by role via grant/revokeRuntimePermission(), similar to development permissions but only manageable by role. Also fixed a bug that PermissionController can get any signature permission. Bug: 158736025 Test: presubmit Change-Id: I49603cee91466a791be66055a922ba1a8bd08d4e
This commit is contained in:
@@ -2291,6 +2291,7 @@ package android.content.pm {
|
||||
field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
|
||||
field public static final int PROTECTION_FLAG_RECENTS = 33554432; // 0x2000000
|
||||
field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000
|
||||
field public static final int PROTECTION_FLAG_ROLE = 67108864; // 0x4000000
|
||||
field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
|
||||
field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
|
||||
field @Nullable public final String backgroundPermission;
|
||||
|
||||
@@ -261,6 +261,15 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
|
||||
@SystemApi
|
||||
public static final int PROTECTION_FLAG_RECENTS = 0x2000000;
|
||||
|
||||
/**
|
||||
* Additional flag for {@link #protectionLevel}, corresponding to the <code>role</code> value of
|
||||
* {@link android.R.attr#protectionLevel}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public static final int PROTECTION_FLAG_ROLE = 0x4000000;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = {
|
||||
PROTECTION_FLAG_PRIVILEGED,
|
||||
@@ -285,6 +294,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
|
||||
PROTECTION_FLAG_COMPANION,
|
||||
PROTECTION_FLAG_RETAIL_DEMO,
|
||||
PROTECTION_FLAG_RECENTS,
|
||||
PROTECTION_FLAG_ROLE,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ProtectionFlags {}
|
||||
@@ -546,6 +556,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
|
||||
if ((level & PermissionInfo.PROTECTION_FLAG_RECENTS) != 0) {
|
||||
protLevel.append("|recents");
|
||||
}
|
||||
if ((level & PermissionInfo.PROTECTION_FLAG_ROLE) != 0) {
|
||||
protLevel.append("|role");
|
||||
}
|
||||
return protLevel.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -306,6 +306,8 @@
|
||||
<!-- Additional flag from base permission type: this permission will be granted to the
|
||||
recents app. -->
|
||||
<flag name="recents" value="0x2000000" />
|
||||
<!-- Additional flag from base permission type: this permission is managed by role. -->
|
||||
<flag name="role" value="0x4000000" />
|
||||
</attr>
|
||||
|
||||
<!-- Flags indicating more context for a permission group. -->
|
||||
|
||||
@@ -335,6 +335,10 @@ public final class Permission {
|
||||
return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_RECENTS) != 0;
|
||||
}
|
||||
|
||||
public boolean isRole() {
|
||||
return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_ROLE) != 0;
|
||||
}
|
||||
|
||||
public void transfer(@NonNull String oldPackageName, @NonNull String newPackageName) {
|
||||
if (!oldPackageName.equals(mPermissionInfo.packageName)) {
|
||||
return;
|
||||
|
||||
@@ -160,6 +160,7 @@ import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -1550,18 +1551,24 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
throw new IllegalArgumentException("Unknown package: " + packageName);
|
||||
}
|
||||
|
||||
final boolean isRolePermission;
|
||||
final boolean isSoftRestrictedPermission;
|
||||
synchronized (mLock) {
|
||||
final Permission permission = mRegistry.getPermission(permName);
|
||||
isSoftRestrictedPermission = permission != null && permission.isSoftRestricted();
|
||||
if (permission == null) {
|
||||
throw new IllegalArgumentException("Unknown permission: " + permName);
|
||||
}
|
||||
isRolePermission = permission.isRole();
|
||||
isSoftRestrictedPermission = permission.isSoftRestricted();
|
||||
}
|
||||
final boolean mayGrantRolePermission = isRolePermission
|
||||
&& mayManageRolePermission(callingUid);
|
||||
final boolean mayGrantSoftRestrictedPermission = isSoftRestrictedPermission
|
||||
&& SoftRestrictedPermissionPolicy.forPermission(mContext,
|
||||
pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName)
|
||||
.mayGrantPermission();
|
||||
|
||||
final boolean isRuntimePermission;
|
||||
final boolean isDevelopmentPermission;
|
||||
final boolean permissionHasGids;
|
||||
synchronized (mLock) {
|
||||
final Permission bp = mRegistry.getPermission(permName);
|
||||
@@ -1570,9 +1577,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
}
|
||||
|
||||
isRuntimePermission = bp.isRuntime();
|
||||
isDevelopmentPermission = bp.isDevelopment();
|
||||
permissionHasGids = bp.hasGids();
|
||||
if (!(isRuntimePermission || isDevelopmentPermission)) {
|
||||
if (isRuntimePermission || bp.isDevelopment()) {
|
||||
// Good.
|
||||
} else if (bp.isRole()) {
|
||||
if (!mayGrantRolePermission) {
|
||||
throw new SecurityException("Permission " + permName + " is managed by role");
|
||||
}
|
||||
} else {
|
||||
throw new SecurityException("Permission " + permName + " requested by "
|
||||
+ pkg.getPackageName() + " is not a changeable permission type");
|
||||
}
|
||||
@@ -1623,7 +1635,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bp.isDevelopment()) {
|
||||
if (bp.isDevelopment() || bp.isRole()) {
|
||||
// Development permissions must be handled specially, since they are not
|
||||
// normal runtime permissions. For now they apply to all users.
|
||||
// TODO(zhanghai): We are breaking the behavior above by making all permission state
|
||||
@@ -1654,10 +1666,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
|
||||
final int uid = UserHandle.getUid(userId, pkg.getUid());
|
||||
if (callback != null) {
|
||||
if (isDevelopmentPermission) {
|
||||
callback.onInstallPermissionGranted();
|
||||
} else {
|
||||
if (isRuntimePermission) {
|
||||
callback.onPermissionGranted(uid, userId);
|
||||
} else {
|
||||
callback.onInstallPermissionGranted();
|
||||
}
|
||||
if (permissionHasGids) {
|
||||
callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
|
||||
@@ -1715,8 +1727,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
throw new IllegalArgumentException("Unknown package: " + packageName);
|
||||
}
|
||||
|
||||
final boolean isRolePermission;
|
||||
synchronized (mLock) {
|
||||
final Permission permission = mRegistry.getPermission(permName);
|
||||
if (permission == null) {
|
||||
throw new IllegalArgumentException("Unknown permission: " + permName);
|
||||
}
|
||||
isRolePermission = permission.isRole();
|
||||
}
|
||||
final boolean mayRevokeRolePermission = isRolePermission
|
||||
&& mayManageRolePermission(callingUid);
|
||||
|
||||
final boolean isRuntimePermission;
|
||||
final boolean isDevelopmentPermission;
|
||||
synchronized (mLock) {
|
||||
final Permission bp = mRegistry.getPermission(permName);
|
||||
if (bp == null) {
|
||||
@@ -1724,8 +1746,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
}
|
||||
|
||||
isRuntimePermission = bp.isRuntime();
|
||||
isDevelopmentPermission = bp.isDevelopment();
|
||||
if (!(isRuntimePermission || isDevelopmentPermission)) {
|
||||
if (isRuntimePermission || bp.isDevelopment()) {
|
||||
// Good.
|
||||
} else if (bp.isRole()) {
|
||||
if (!mayRevokeRolePermission) {
|
||||
throw new SecurityException("Permission " + permName + " is managed by role");
|
||||
}
|
||||
} else {
|
||||
throw new SecurityException("Permission " + permName + " requested by "
|
||||
+ pkg.getPackageName() + " is not a changeable permission type");
|
||||
}
|
||||
@@ -1777,11 +1804,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
}
|
||||
|
||||
if (callback != null) {
|
||||
if (isDevelopmentPermission) {
|
||||
mDefaultPermissionCallback.onInstallPermissionRevoked();
|
||||
} else {
|
||||
if (isRuntimePermission) {
|
||||
callback.onPermissionRevoked(UserHandle.getUid(userId, pkg.getUid()), userId,
|
||||
reason);
|
||||
} else {
|
||||
mDefaultPermissionCallback.onInstallPermissionRevoked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1790,6 +1817,17 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mayManageRolePermission(int uid) {
|
||||
final PackageManager packageManager = mContext.getPackageManager();
|
||||
final String[] packageNames = packageManager.getPackagesForUid(uid);
|
||||
if (packageNames == null) {
|
||||
return false;
|
||||
}
|
||||
final String permissionControllerPackageName =
|
||||
packageManager.getPermissionControllerPackageName();
|
||||
return Arrays.asList(packageNames).contains(permissionControllerPackageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetRuntimePermissions() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
@@ -2906,7 +2944,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
|
||||
if ((bp.isNormal() && shouldGrantNormalPermission) || (bp.isSignature()
|
||||
&& (shouldGrantSignaturePermission.contains(permName)
|
||||
|| (bp.isDevelopment() && origState.isPermissionGranted(permName))))) {
|
||||
|| ((bp.isDevelopment() || bp.isRole())
|
||||
&& origState.isPermissionGranted(permName))))) {
|
||||
// Grant an install permission.
|
||||
if (uidState.grantPermission(bp)) {
|
||||
changedInstallPermission = true;
|
||||
@@ -3472,12 +3511,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
// need a separate flag anymore. Hence we need to check which
|
||||
// permissions are needed by the permission controller
|
||||
if (!allowed && bp.isInstaller()
|
||||
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
|
||||
&& (ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
|
||||
PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM),
|
||||
pkg.getPackageName()) || ArrayUtils.contains(
|
||||
mPackageManagerInt.getKnownPackageNames(
|
||||
PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER,
|
||||
UserHandle.USER_SYSTEM), pkg.getPackageName())) {
|
||||
UserHandle.USER_SYSTEM), pkg.getPackageName()))) {
|
||||
// If this permission is to be granted to the system installer and
|
||||
// this app is an installer, then it gets the permission.
|
||||
allowed = true;
|
||||
|
||||
Reference in New Issue
Block a user