diff options
| author | 2021-05-07 11:16:08 -0700 | |
|---|---|---|
| committer | 2021-05-11 15:29:18 -0700 | |
| commit | 10b5c81409d5e952b527ea792389b603bc20d492 (patch) | |
| tree | 94357a737212c962c280e01d0c3fefbabdfd8a5a | |
| parent | 3d46ae52dccb4c519fb3ab733d6b82b5c83b67de (diff) | |
Ensure that proxy operations look for attribution tag in proxy's pkg
When calling note/startProxyOp, we should look for both attribution
tags, proxy and proxied, in the proxy app. Log an error, instead of
throwing, when we find the proxied attribution tag in the proxy app
Bug: 187313675
Test: manual
Change-Id: I8a5db05b9728c0bb92f334fbac9baa7ef62fe619
| -rw-r--r-- | services/core/java/com/android/server/appop/AppOpsService.java | 70 |
1 files changed, 50 insertions, 20 deletions
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 99b0d81285f0..a3669e2adb9e 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -3161,7 +3161,7 @@ public class AppOpsService extends IAppOpsService.Stub { boolean shouldCollectMessage) { RestrictionBypass bypass; try { - bypass = verifyAndGetBypass(uid, packageName, attributionTag); + bypass = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName); } catch (SecurityException e) { Slog.e(TAG, "noteOperation", e); return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, @@ -3653,7 +3653,7 @@ public class AppOpsService extends IAppOpsService.Stub { boolean shouldCollectMessage, boolean dryRun) { RestrictionBypass bypass; try { - bypass = verifyAndGetBypass(uid, packageName, attributionTag); + bypass = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName); } catch (SecurityException e) { Slog.e(TAG, "startOperation", e); return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag, @@ -4187,17 +4187,26 @@ public class AppOpsService extends IAppOpsService.Stub { } /** + * @see verifyAndGetBypass(int, String, String, String) + */ + private @Nullable RestrictionBypass verifyAndGetBypass(int uid, String packageName, + @Nullable String attributionTag) { + return verifyAndGetBypass(uid, packageName, attributionTag, null); + } + + /** * Verify that package belongs to uid and return the {@link RestrictionBypass bypass * description} for the package. * * @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 * * @return {@code true} iff the package is privileged */ private @Nullable RestrictionBypass verifyAndGetBypass(int uid, String packageName, - @Nullable String attributionTag) { + @Nullable String attributionTag, @Nullable String proxyPackageName) { if (uid == Process.ROOT_UID) { // For backwards compatibility, don't check package name for root UID. return null; @@ -4235,34 +4244,36 @@ public class AppOpsService extends IAppOpsService.Stub { final long ident = Binder.clearCallingIdentity(); try { boolean isAttributionTagValid = false; - AndroidPackage pkg = LocalServices.getService(PackageManagerInternal.class) - .getPackage(packageName); + PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); + AndroidPackage pkg = pmInt.getPackage(packageName); if (pkg != null) { - if (attributionTag == null) { - isAttributionTagValid = true; - } else { - if (pkg.getAttributions() != null) { - int numAttributions = pkg.getAttributions().size(); - for (int i = 0; i < numAttributions; i++) { - if (pkg.getAttributions().get(i).tag.equals(attributionTag)) { - isAttributionTagValid = true; - } - } - } - } + isAttributionTagValid = isAttributionInPackage(pkg, attributionTag); pkgUid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid())); bypass = getBypassforPackage(pkg); } if (!isAttributionTagValid) { - String msg = "attributionTag " + attributionTag + " not declared in" - + " manifest of " + packageName; + AndroidPackage proxyPkg = proxyPackageName != null + ? pmInt.getPackage(proxyPackageName) : null; + boolean foundInProxy = isAttributionInPackage(proxyPkg, attributionTag); + String msg; + if (pkg != null && foundInProxy) { + msg = "attributionTag " + attributionTag + " declared in manifest of the proxy" + + " package " + proxyPackageName + ", this is not advised"; + } else if (pkg != null) { + msg = "attributionTag " + attributionTag + " not declared in manifest of " + + packageName; + } else { + msg = "package " + packageName + " not found, can't check for " + + "attributionTag " + attributionTag; + } + try { if (mPlatformCompat.isChangeEnabledByPackageName( SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, packageName, userId) && mPlatformCompat.isChangeEnabledByUid( SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, - callingUid)) { + callingUid) && !foundInProxy) { throw new SecurityException(msg); } else { Slog.e(TAG, msg); @@ -4282,6 +4293,25 @@ public class AppOpsService extends IAppOpsService.Stub { return bypass; } + private boolean isAttributionInPackage(@Nullable AndroidPackage pkg, + @Nullable String attributionTag) { + if (pkg == null) { + return false; + } else if (attributionTag == null) { + return true; + } + if (pkg.getAttributions() != null) { + int numAttributions = pkg.getAttributions().size(); + for (int i = 0; i < numAttributions; i++) { + if (pkg.getAttributions().get(i).tag.equals(attributionTag)) { + return true; + } + } + } + + return false; + } + /** * Get (and potentially create) ops. * |