From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 31 Jul 2022 18:00:35 +0300 Subject: [PATCH] improve compatibility of INTERNET special runtime permission There are apps that refuse to work when they detect that INTERNET is revoked, usually because of a library check that reminds the app developer to add INTERNET uses-permission element to app's AndroidManifest. Always report that INTERNET is granted unless the app has declaration inside element in its AndroidManifest, or is a system app. --- core/api/system-current.txt | 5 +++++ core/java/android/app/DownloadManager.java | 13 ++++++++++++ .../content/pm/AppPermissionUtils.java | 7 +++++++ .../pm/SpecialRuntimePermAppUtils.java | 20 +++++++++++++++++++ .../permission/SpecialRuntimePermUtils.java | 17 ++++++++++++++++ 5 files changed, 62 insertions(+) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 531b03cd7c0c..64115f76caf4 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -3547,6 +3547,11 @@ package android.content.pm { } public class SpecialRuntimePermAppUtils { + method public static boolean awareOfRuntimeInternetPermission(); + method public static boolean isInternetCompatEnabled(); + method public static boolean requestsInternetPermission(); + field public static final int FLAG_AWARE_OF_RUNTIME_INTERNET_PERMISSION = 4; // 0x4 + field public static final int FLAG_REQUESTS_INTERNET_PERMISSION = 2; // 0x2 } public final class SuspendDialogInfo implements android.os.Parcelable { diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java index c209660f4197..ee412eb50064 100644 --- a/core/java/android/app/DownloadManager.java +++ b/core/java/android/app/DownloadManager.java @@ -34,6 +34,7 @@ import android.content.Context; import android.database.Cursor; import android.database.CursorWrapper; import android.database.DatabaseUtils; +import android.database.MatrixCursor; import android.net.ConnectivityManager; import android.net.NetworkPolicyManager; import android.net.Uri; @@ -53,6 +54,8 @@ import android.util.LongSparseArray; import android.util.Pair; import android.webkit.MimeTypeMap; +import android.content.pm.SpecialRuntimePermAppUtils; + import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; @@ -1123,6 +1126,11 @@ public class DownloadManager { * calls related to this download. */ public long enqueue(Request request) { + if (SpecialRuntimePermAppUtils.isInternetCompatEnabled()) { + // invalid id (DownloadProvider uses SQLite and returns a row id) + return -1; + } + ContentValues values = request.toContentValues(mPackageName); Uri downloadUri = mResolver.insert(Downloads.Impl.CONTENT_URI, values); long id = Long.parseLong(downloadUri.getLastPathSegment()); @@ -1170,6 +1178,11 @@ public class DownloadManager { /** @hide */ public Cursor query(Query query, String[] projection) { + if (SpecialRuntimePermAppUtils.isInternetCompatEnabled()) { + // underlying provider is protected by the INTERNET permission + return new MatrixCursor(projection); + } + Cursor underlyingCursor = query.runQuery(mResolver, projection, mBaseUri); if (underlyingCursor == null) { return null; diff --git a/core/java/android/content/pm/AppPermissionUtils.java b/core/java/android/content/pm/AppPermissionUtils.java index 7dc20eec8485..6a96f70dcfcf 100644 --- a/core/java/android/content/pm/AppPermissionUtils.java +++ b/core/java/android/content/pm/AppPermissionUtils.java @@ -24,6 +24,13 @@ public class AppPermissionUtils { // android.app.ApplicationPackageManager#checkPermission(String permName, String pkgName) // android.app.ContextImpl#checkPermission(String permission, int pid, int uid) public static boolean shouldSpoofSelfCheck(String permName) { + if (Manifest.permission.INTERNET.equals(permName) + && SpecialRuntimePermAppUtils.requestsInternetPermission() + && !SpecialRuntimePermAppUtils.awareOfRuntimeInternetPermission()) + { + return true; + } + return false; } } diff --git a/core/java/android/content/pm/SpecialRuntimePermAppUtils.java b/core/java/android/content/pm/SpecialRuntimePermAppUtils.java index efd48cb49aa3..2f973a585d5c 100644 --- a/core/java/android/content/pm/SpecialRuntimePermAppUtils.java +++ b/core/java/android/content/pm/SpecialRuntimePermAppUtils.java @@ -28,9 +28,29 @@ import android.permission.PermissionManager; @SystemApi public class SpecialRuntimePermAppUtils { private static final int FLAG_INITED = 1; + public static final int FLAG_REQUESTS_INTERNET_PERMISSION = 1 << 1; + public static final int FLAG_AWARE_OF_RUNTIME_INTERNET_PERMISSION = 1 << 2; private static volatile int cachedFlags; + private static boolean hasInternetPermission() { + // checkSelfPermission() is spoofed, query the underlying API directly + return PermissionManager.checkPermission(Manifest.permission.INTERNET, Process.myPid(), Process.myUid()) + == PackageManager.PERMISSION_GRANTED; + } + + public static boolean requestsInternetPermission() { + return (getFlags() & FLAG_REQUESTS_INTERNET_PERMISSION) != 0; + } + + public static boolean awareOfRuntimeInternetPermission() { + return (getFlags() & FLAG_AWARE_OF_RUNTIME_INTERNET_PERMISSION) != 0; + } + + public static boolean isInternetCompatEnabled() { + return !hasInternetPermission() && requestsInternetPermission() && !awareOfRuntimeInternetPermission(); + } + private static int getFlags() { int cache = cachedFlags; if (cache != 0) { diff --git a/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java b/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java index fe946ff5d5ca..6f5cabb8a8fc 100644 --- a/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java +++ b/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java @@ -34,11 +34,28 @@ public class SpecialRuntimePermUtils { for (ParsedUsesPermission perm : pkg.getUsesPermissions()) { String name = perm.getName(); switch (name) { + case Manifest.permission.INTERNET: + flags |= FLAG_REQUESTS_INTERNET_PERMISSION; + continue; default: continue; } } + if ((flags & FLAG_REQUESTS_INTERNET_PERMISSION) != 0) { + if (pkg.isSystem()) { + flags |= FLAG_AWARE_OF_RUNTIME_INTERNET_PERMISSION; + } else { + Bundle metadata = pkg.getMetaData(); + if (metadata != null) { + String key = Manifest.permission.INTERNET + ".mode"; + if ("runtime".equals(metadata.getString(key))) { + flags |= FLAG_AWARE_OF_RUNTIME_INTERNET_PERMISSION; + } + } + } + } + return flags; }