Loading services/core/java/com/android/server/appop/AppOpsService.java +63 −25 Original line number Diff line number Diff line Loading @@ -699,7 +699,7 @@ public class AppOpsService extends IAppOpsService.Stub { } } /** Returned from {@link #verifyAndGetBypass(int, String, String, String, boolean)}. */ /** Returned from {@link #verifyAndGetBypass(int, String, String, int, String, boolean)}. */ private static final class PackageVerificationResult { final RestrictionBypass bypass; Loading Loading @@ -3336,7 +3336,7 @@ public class AppOpsService extends IAppOpsService.Stub { verifyAndGetBypass(uid, packageName, null); // When the caller is the system, it's possible that the packageName is the special // one (e.g., "root") which isn't actually existed. if (resolveUid(packageName) == uid if (resolveNonAppUid(packageName) == uid || (isPackageExisted(packageName) && !filterAppAccessUnlocked(packageName))) { return AppOpsManager.MODE_ALLOWED; } Loading Loading @@ -3460,7 +3460,7 @@ public class AppOpsService extends IAppOpsService.Stub { boolean shouldCollectMessage) { PackageVerificationResult pvr; try { pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName); pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName); boolean wasNull = attributionTag == null; if (!pvr.isAttributionTagValid) { attributionTag = null; Loading Loading @@ -3979,7 +3979,7 @@ public class AppOpsService extends IAppOpsService.Stub { int attributionChainId, boolean dryRun) { PackageVerificationResult pvr; try { pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName); pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName); if (!pvr.isAttributionTagValid) { attributionTag = null; } Loading Loading @@ -4442,8 +4442,12 @@ public class AppOpsService extends IAppOpsService.Stub { private boolean isCallerAndAttributionTrusted(@NonNull AttributionSource attributionSource) { if (attributionSource.getUid() != Binder.getCallingUid() && attributionSource.isTrusted(mContext)) { // if there is a next attribution source, it must be trusted, as well. if (attributionSource.getNext() == null || attributionSource.getNext().isTrusted(mContext)) { return true; } } return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, Binder.getCallingPid(), Binder.getCallingUid(), null) == PackageManager.PERMISSION_GRANTED; Loading Loading @@ -4580,11 +4584,20 @@ public class AppOpsService extends IAppOpsService.Stub { } /** * @see #verifyAndGetBypass(int, String, String, String) * @see #verifyAndGetBypass(int, String, String, int, String, boolean) */ private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag) { return verifyAndGetBypass(uid, packageName, attributionTag, null); return verifyAndGetBypass(uid, packageName, attributionTag, Process.INVALID_UID, null); } /** * @see #verifyAndGetBypass(int, String, String, int, String, boolean) */ private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName) { return verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName, false); } /** Loading @@ -4595,13 +4608,16 @@ public class AppOpsService extends IAppOpsService.Stub { * @param uid The uid the package belongs to * @param packageName The package the might belong to the uid * @param attributionTag attribution tag or {@code null} if no need to verify * @param proxyPackageName The proxy package, from which the attribution tag is to be pulled * @param proxyUid The proxy uid, from which the attribution tag is to be pulled * @param proxyPackageName The proxy package, from which the attribution tag may be pulled * @param suppressErrorLogs Whether to print to logcat about nonmatching parameters * * @return PackageVerificationResult containing {@link RestrictionBypass} and whether the * attribution tag is valid */ private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag, @Nullable String proxyPackageName) { @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName, boolean suppressErrorLogs) { if (uid == Process.ROOT_UID) { // For backwards compatibility, don't check package name for root UID. return new PackageVerificationResult(null, Loading Loading @@ -4645,31 +4661,47 @@ public class AppOpsService extends IAppOpsService.Stub { int callingUid = Binder.getCallingUid(); // Allow any attribution tag for resolvable uids int pkgUid; // Allow any attribution tag for resolvable, non-app uids int nonAppUid; if (Objects.equals(packageName, "com.android.shell")) { // Special case for the shell which is a package but should be able // to bypass app attribution tag restrictions. pkgUid = Process.SHELL_UID; nonAppUid = Process.SHELL_UID; } else { pkgUid = resolveUid(packageName); nonAppUid = resolveNonAppUid(packageName); } if (pkgUid != Process.INVALID_UID) { if (pkgUid != UserHandle.getAppId(uid)) { if (nonAppUid != Process.INVALID_UID) { if (nonAppUid != UserHandle.getAppId(uid)) { if (!suppressErrorLogs) { Slog.e(TAG, "Bad call made by uid " + callingUid + ". " + "Package \"" + packageName + "\" does not belong to uid " + uid + "."); String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not"; throw new SecurityException("Specified package \"" + packageName + "\" under uid " + UserHandle.getAppId(uid) + otherUidMessage); + "Package \"" + packageName + "\" does not belong to uid " + uid + "."); } String otherUidMessage = DEBUG ? " but it is really " + nonAppUid : " but it is not"; throw new SecurityException("Specified package \"" + packageName + "\" under uid " + UserHandle.getAppId(uid) + otherUidMessage); } // We only allow bypassing the attribution tag verification if the proxy is a // system app (or is null), in order to prevent abusive apps clogging the appops // system with unlimited attribution tags via proxy calls. boolean proxyIsSystemAppOrNull = true; if (proxyPackageName != null) { int proxyAppId = UserHandle.getAppId(proxyUid); if (proxyAppId >= Process.FIRST_APPLICATION_UID) { proxyIsSystemAppOrNull = mPackageManagerInternal.isSystemPackage(proxyPackageName); } } return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED, /* isAttributionTagValid */ true); /* isAttributionTagValid */ proxyIsSystemAppOrNull); } int userId = UserHandle.getUserId(uid); RestrictionBypass bypass = null; boolean isAttributionTagValid = false; int pkgUid = nonAppUid; final long ident = Binder.clearCallingIdentity(); try { PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); Loading Loading @@ -5536,7 +5568,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (nonpackageUid != -1) { packageName = null; } else { packageUid = resolveUid(packageName); packageUid = resolveNonAppUid(packageName); if (packageUid < 0) { packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); Loading Loading @@ -6720,11 +6752,17 @@ public class AppOpsService extends IAppOpsService.Stub { if (restricted && attrOp.isRunning()) { attrOp.pause(); } else if (attrOp.isPaused()) { RestrictionBypass bypass = verifyAndGetBypass(uid, ops.packageName, attrOp.tag) .bypass; if (!isOpRestrictedLocked(uid, code, ops.packageName, attrOp.tag, bypass, false)) { // Only resume if there are no other restrictions remaining on this op attrOp.resume(); } } } } } private void notifyWatchersOfChange(int code, int uid) { final ArraySet<ModeCallback> clonedCallbacks; Loading Loading @@ -7165,7 +7203,7 @@ public class AppOpsService extends IAppOpsService.Stub { } } private static int resolveUid(String packageName) { private static int resolveNonAppUid(String packageName) { if (packageName == null) { return -1; } Loading Loading
services/core/java/com/android/server/appop/AppOpsService.java +63 −25 Original line number Diff line number Diff line Loading @@ -699,7 +699,7 @@ public class AppOpsService extends IAppOpsService.Stub { } } /** Returned from {@link #verifyAndGetBypass(int, String, String, String, boolean)}. */ /** Returned from {@link #verifyAndGetBypass(int, String, String, int, String, boolean)}. */ private static final class PackageVerificationResult { final RestrictionBypass bypass; Loading Loading @@ -3336,7 +3336,7 @@ public class AppOpsService extends IAppOpsService.Stub { verifyAndGetBypass(uid, packageName, null); // When the caller is the system, it's possible that the packageName is the special // one (e.g., "root") which isn't actually existed. if (resolveUid(packageName) == uid if (resolveNonAppUid(packageName) == uid || (isPackageExisted(packageName) && !filterAppAccessUnlocked(packageName))) { return AppOpsManager.MODE_ALLOWED; } Loading Loading @@ -3460,7 +3460,7 @@ public class AppOpsService extends IAppOpsService.Stub { boolean shouldCollectMessage) { PackageVerificationResult pvr; try { pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName); pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName); boolean wasNull = attributionTag == null; if (!pvr.isAttributionTagValid) { attributionTag = null; Loading Loading @@ -3979,7 +3979,7 @@ public class AppOpsService extends IAppOpsService.Stub { int attributionChainId, boolean dryRun) { PackageVerificationResult pvr; try { pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName); pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName); if (!pvr.isAttributionTagValid) { attributionTag = null; } Loading Loading @@ -4442,8 +4442,12 @@ public class AppOpsService extends IAppOpsService.Stub { private boolean isCallerAndAttributionTrusted(@NonNull AttributionSource attributionSource) { if (attributionSource.getUid() != Binder.getCallingUid() && attributionSource.isTrusted(mContext)) { // if there is a next attribution source, it must be trusted, as well. if (attributionSource.getNext() == null || attributionSource.getNext().isTrusted(mContext)) { return true; } } return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, Binder.getCallingPid(), Binder.getCallingUid(), null) == PackageManager.PERMISSION_GRANTED; Loading Loading @@ -4580,11 +4584,20 @@ public class AppOpsService extends IAppOpsService.Stub { } /** * @see #verifyAndGetBypass(int, String, String, String) * @see #verifyAndGetBypass(int, String, String, int, String, boolean) */ private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag) { return verifyAndGetBypass(uid, packageName, attributionTag, null); return verifyAndGetBypass(uid, packageName, attributionTag, Process.INVALID_UID, null); } /** * @see #verifyAndGetBypass(int, String, String, int, String, boolean) */ private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName) { return verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName, false); } /** Loading @@ -4595,13 +4608,16 @@ public class AppOpsService extends IAppOpsService.Stub { * @param uid The uid the package belongs to * @param packageName The package the might belong to the uid * @param attributionTag attribution tag or {@code null} if no need to verify * @param proxyPackageName The proxy package, from which the attribution tag is to be pulled * @param proxyUid The proxy uid, from which the attribution tag is to be pulled * @param proxyPackageName The proxy package, from which the attribution tag may be pulled * @param suppressErrorLogs Whether to print to logcat about nonmatching parameters * * @return PackageVerificationResult containing {@link RestrictionBypass} and whether the * attribution tag is valid */ private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName, @Nullable String attributionTag, @Nullable String proxyPackageName) { @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName, boolean suppressErrorLogs) { if (uid == Process.ROOT_UID) { // For backwards compatibility, don't check package name for root UID. return new PackageVerificationResult(null, Loading Loading @@ -4645,31 +4661,47 @@ public class AppOpsService extends IAppOpsService.Stub { int callingUid = Binder.getCallingUid(); // Allow any attribution tag for resolvable uids int pkgUid; // Allow any attribution tag for resolvable, non-app uids int nonAppUid; if (Objects.equals(packageName, "com.android.shell")) { // Special case for the shell which is a package but should be able // to bypass app attribution tag restrictions. pkgUid = Process.SHELL_UID; nonAppUid = Process.SHELL_UID; } else { pkgUid = resolveUid(packageName); nonAppUid = resolveNonAppUid(packageName); } if (pkgUid != Process.INVALID_UID) { if (pkgUid != UserHandle.getAppId(uid)) { if (nonAppUid != Process.INVALID_UID) { if (nonAppUid != UserHandle.getAppId(uid)) { if (!suppressErrorLogs) { Slog.e(TAG, "Bad call made by uid " + callingUid + ". " + "Package \"" + packageName + "\" does not belong to uid " + uid + "."); String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not"; throw new SecurityException("Specified package \"" + packageName + "\" under uid " + UserHandle.getAppId(uid) + otherUidMessage); + "Package \"" + packageName + "\" does not belong to uid " + uid + "."); } String otherUidMessage = DEBUG ? " but it is really " + nonAppUid : " but it is not"; throw new SecurityException("Specified package \"" + packageName + "\" under uid " + UserHandle.getAppId(uid) + otherUidMessage); } // We only allow bypassing the attribution tag verification if the proxy is a // system app (or is null), in order to prevent abusive apps clogging the appops // system with unlimited attribution tags via proxy calls. boolean proxyIsSystemAppOrNull = true; if (proxyPackageName != null) { int proxyAppId = UserHandle.getAppId(proxyUid); if (proxyAppId >= Process.FIRST_APPLICATION_UID) { proxyIsSystemAppOrNull = mPackageManagerInternal.isSystemPackage(proxyPackageName); } } return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED, /* isAttributionTagValid */ true); /* isAttributionTagValid */ proxyIsSystemAppOrNull); } int userId = UserHandle.getUserId(uid); RestrictionBypass bypass = null; boolean isAttributionTagValid = false; int pkgUid = nonAppUid; final long ident = Binder.clearCallingIdentity(); try { PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); Loading Loading @@ -5536,7 +5568,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (nonpackageUid != -1) { packageName = null; } else { packageUid = resolveUid(packageName); packageUid = resolveNonAppUid(packageName); if (packageUid < 0) { packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); Loading Loading @@ -6720,11 +6752,17 @@ public class AppOpsService extends IAppOpsService.Stub { if (restricted && attrOp.isRunning()) { attrOp.pause(); } else if (attrOp.isPaused()) { RestrictionBypass bypass = verifyAndGetBypass(uid, ops.packageName, attrOp.tag) .bypass; if (!isOpRestrictedLocked(uid, code, ops.packageName, attrOp.tag, bypass, false)) { // Only resume if there are no other restrictions remaining on this op attrOp.resume(); } } } } } private void notifyWatchersOfChange(int code, int uid) { final ArraySet<ModeCallback> clonedCallbacks; Loading Loading @@ -7165,7 +7203,7 @@ public class AppOpsService extends IAppOpsService.Stub { } } private static int resolveUid(String packageName) { private static int resolveNonAppUid(String packageName) { if (packageName == null) { return -1; } Loading