summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Hai Zhang <zhanghai@google.com> 2020-03-05 16:03:35 -0800
committer Hai Zhang <zhanghai@google.com> 2020-04-13 15:46:36 -0700
commita7c60c045719eb7f90ed49b9bd3b712471f822f8 (patch)
treeb37823265bfb7efb0a19eeef523bf168c0ca2d54
parentbba1891e80420c4f064d8da8a212a7220f8595ed (diff)
Reset mode for app op permission when app no longer requests it.
Fixes: 149765004 Test: Ensure the same set of tests pass with the following command: Test: atest ExternalStorageHostTest StorageHostTest Change-Id: Ic3847f136e059e3517154b909d07b68553ebf82b
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java26
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java8
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java116
3 files changed, 138 insertions, 12 deletions
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 b7c9ecb604f8..49de68f6b0f4 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -4607,11 +4607,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtection(
+ public @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtection(
@PermissionInfo.Protection int protection) {
ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
- synchronized (PermissionManagerService.this.mLock) {
+ synchronized (mLock) {
int numTotalPermissions = mSettings.mPermissions.size();
for (int i = 0; i < numTotalPermissions; i++) {
@@ -4628,6 +4628,28 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
+ public @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
+ @PermissionInfo.ProtectionFlags int protectionFlags) {
+ ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
+
+ synchronized (mLock) {
+ int numTotalPermissions = mSettings.mPermissions.size();
+
+ for (int i = 0; i < numTotalPermissions; i++) {
+ BasePermission bp = mSettings.mPermissions.valueAt(i);
+
+ if (bp.perm != null && (bp.perm.getProtectionFlags() & protectionFlags)
+ == protectionFlags) {
+ matchingPermissions.add(
+ PackageInfoUtils.generatePermissionInfo(bp.perm, 0));
+ }
+ }
+ }
+
+ return matchingPermissions;
+ }
+
+ @Override
public @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) {
return PermissionManagerService.this.backupRuntimePermissions(user);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 356d0abc1d19..57a25eddf7ce 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -302,10 +302,14 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
/** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
- /** Get all permission that have a certain protection level */
- public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtection(
+ /** Get all permissions that have a certain protection */
+ public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtection(
@PermissionInfo.Protection int protection);
+ /** Get all permissions that have certain protection flags */
+ public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
+ @PermissionInfo.ProtectionFlags int protectionFlags);
+
/**
* Returns the delegate used to influence permission checking.
*
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 27288d852fb2..adc653f60251 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -72,6 +72,7 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -107,6 +108,15 @@ public final class PermissionPolicyService extends SystemService {
@GuardedBy("mLock")
private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>();
+ /**
+ * Whether an async {@link #resetAppOpPermissionsIfNotRequestedForUid} is currently
+ * scheduled for a uid.
+ */
+ @GuardedBy("mLock")
+ private final SparseBooleanArray mIsUidSyncScheduled = new SparseBooleanArray();
+
+ private List<String> mAppOpPermissions;
+
public PermissionPolicyService(@NonNull Context context) {
super(context);
@@ -117,7 +127,7 @@ public final class PermissionPolicyService extends SystemService {
public void onStart() {
final PackageManagerInternal packageManagerInternal = LocalServices.getService(
PackageManagerInternal.class);
- final PermissionManagerServiceInternal permManagerInternal = LocalServices.getService(
+ final PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
PermissionManagerServiceInternal.class);
final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
@@ -125,38 +135,44 @@ public final class PermissionPolicyService extends SystemService {
packageManagerInternal.getPackageList(new PackageListObserver() {
@Override
public void onPackageAdded(String packageName, int uid) {
- onPackageChanged(packageName, uid);
+ final int userId = UserHandle.getUserId(uid);
+ if (isStarted(userId)) {
+ synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
+ }
}
@Override
public void onPackageChanged(String packageName, int uid) {
final int userId = UserHandle.getUserId(uid);
-
if (isStarted(userId)) {
synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
+ resetAppOpPermissionsIfNotRequestedForUid(uid);
}
}
@Override
public void onPackageRemoved(String packageName, int uid) {
- /* do nothing */
+ final int userId = UserHandle.getUserId(uid);
+ if (isStarted(userId)) {
+ resetAppOpPermissionsIfNotRequestedForUid(uid);
+ }
}
});
- permManagerInternal.addOnRuntimePermissionStateChangedListener(
+ permissionManagerInternal.addOnRuntimePermissionStateChangedListener(
this::synchronizePackagePermissionsAndAppOpsAsyncForUser);
mAppOpsCallback = new IAppOpsCallback.Stub() {
public void opChanged(int op, int uid, String packageName) {
synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
UserHandle.getUserId(uid));
+ resetAppOpPermissionsIfNotRequestedForUidAsync(uid);
}
};
final ArrayList<PermissionInfo> dangerousPerms =
- permManagerInternal.getAllPermissionWithProtection(
+ permissionManagerInternal.getAllPermissionsWithProtection(
PermissionInfo.PROTECTION_DANGEROUS);
-
try {
int numDangerousPerms = dangerousPerms.size();
for (int i = 0; i < numDangerousPerms; i++) {
@@ -179,6 +195,26 @@ public final class PermissionPolicyService extends SystemService {
Slog.wtf(LOG_TAG, "Cannot set up app-ops listener");
}
+ final List<PermissionInfo> appOpPermissionInfos =
+ permissionManagerInternal.getAllPermissionsWithProtectionFlags(
+ PermissionInfo.PROTECTION_FLAG_APPOP);
+ mAppOpPermissions = new ArrayList<>();
+ final int appOpPermissionInfosSize = appOpPermissionInfos.size();
+ for (int i = 0; i < appOpPermissionInfosSize; i++) {
+ final PermissionInfo appOpPermissionInfo = appOpPermissionInfos.get(i);
+
+ final int appOpCode = AppOpsManager.permissionToOpCode(appOpPermissionInfo.name);
+ if (appOpCode != OP_NONE) {
+ mAppOpPermissions.add(appOpPermissionInfo.name);
+
+ try {
+ appOpsService.startWatchingMode(appOpCode, null, mAppOpsCallback);
+ } catch (RemoteException e) {
+ Slog.wtf(LOG_TAG, "Cannot set up app-ops listener", e);
+ }
+ }
+ }
+
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
@@ -445,6 +481,70 @@ public final class PermissionPolicyService extends SystemService {
synchronizer.syncPackages();
}
+ private void resetAppOpPermissionsIfNotRequestedForUidAsync(int uid) {
+ if (isStarted(UserHandle.getUserId(uid))) {
+ synchronized (mLock) {
+ if (!mIsUidSyncScheduled.get(uid)) {
+ mIsUidSyncScheduled.put(uid, true);
+ FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
+ PermissionPolicyService::resetAppOpPermissionsIfNotRequestedForUid,
+ this, uid));
+ }
+ }
+ }
+ }
+
+ private void resetAppOpPermissionsIfNotRequestedForUid(int uid) {
+ synchronized (mLock) {
+ mIsUidSyncScheduled.delete(uid);
+ }
+
+ final Context context = getContext();
+ final PackageManager userPackageManager = getUserContext(context,
+ UserHandle.getUserHandleForUid(uid)).getPackageManager();
+ final String[] packageNames = userPackageManager.getPackagesForUid(uid);
+ if (packageNames == null || packageNames.length == 0) {
+ return;
+ }
+
+ final ArraySet<String> requestedPermissions = new ArraySet<>();
+ for (String packageName : packageNames) {
+ final PackageInfo packageInfo;
+ try {
+ packageInfo = userPackageManager.getPackageInfo(packageName, GET_PERMISSIONS);
+ } catch (NameNotFoundException e) {
+ continue;
+ }
+ if (packageInfo == null || packageInfo.requestedPermissions == null) {
+ continue;
+ }
+ Collections.addAll(requestedPermissions, packageInfo.requestedPermissions);
+ }
+
+ final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+ final AppOpsManagerInternal appOpsManagerInternal = LocalServices.getService(
+ AppOpsManagerInternal.class);
+ final int appOpPermissionsSize = mAppOpPermissions.size();
+ for (int i = 0; i < appOpPermissionsSize; i++) {
+ final String appOpPermission = mAppOpPermissions.get(i);
+
+ if (!requestedPermissions.contains(appOpPermission)) {
+ final int appOpCode = AppOpsManager.permissionToOpCode(appOpPermission);
+ final int defaultAppOpMode = AppOpsManager.opToDefaultMode(appOpCode);
+ for (String packageName : packageNames) {
+ final int appOpMode = appOpsManager.unsafeCheckOpRawNoThrow(appOpCode, uid,
+ packageName);
+ if (appOpMode != defaultAppOpMode) {
+ appOpsManagerInternal.setUidModeFromPermissionPolicy(appOpCode, uid,
+ defaultAppOpMode, mAppOpsCallback);
+ appOpsManagerInternal.setModeFromPermissionPolicy(appOpCode, uid,
+ packageName, defaultAppOpMode, mAppOpsCallback);
+ }
+ }
+ }
+ }
+ }
+
/**
* Synchronizes permission to app ops. You *must* always sync all packages
* in a shared UID at the same time to ensure proper synchronization.
@@ -499,7 +599,7 @@ public final class PermissionPolicyService extends SystemService {
PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
PermissionManagerServiceInternal.class);
List<PermissionInfo> permissionInfos =
- permissionManagerInternal.getAllPermissionWithProtection(
+ permissionManagerInternal.getAllPermissionsWithProtection(
PermissionInfo.PROTECTION_DANGEROUS);
int permissionInfosSize = permissionInfos.size();
for (int i = 0; i < permissionInfosSize; i++) {