DivestOS/Patches/LineageOS-18.1/android_frameworks_base/408448.patch
Tavi 7ecc843451
Churn
Signed-off-by: Tavi <tavi@divested.dev>
2024-11-13 08:02:54 -05:00

138 lines
5.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dipankar Bhardwaj <dipankarb@google.com>
Date: Wed, 21 Aug 2024 14:26:50 +0000
Subject: [PATCH] Restrict access to directories
Restricted access to Android/data, Android/obb and Android/sandbox
directories and its sub-directories. Replacing path's pattern match
check with file equality check.
Test: atest DocumentsClientTest
Bug: 341680936
Flag: EXEMPT bug fix
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:22ea85377ad49594e46c57b398fb477d3d12c668)
Merged-In: I8879900e57e1702d11797b81e86d0cc3f55bac22
Change-Id: I8879900e57e1702d11797b81e86d0cc3f55bac22
---
.../ExternalStorageProvider.java | 79 ++++++++++++++++---
1 file changed, 68 insertions(+), 11 deletions(-)
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 53e17e35953d..a722c0860508 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -16,8 +16,6 @@
package com.android.externalstorage;
-import static java.util.regex.Pattern.CASE_INSENSITIVE;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.usage.StorageStatsManager;
@@ -61,12 +59,15 @@ import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.UUID;
-import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/**
* Presents content of the shared (a.k.a. "external") storage.
@@ -89,12 +90,9 @@ public class ExternalStorageProvider extends FileSystemProvider {
private static final Uri BASE_URI =
new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY).build();
- /**
- * Regex for detecting {@code /Android/data/}, {@code /Android/obb/} and
- * {@code /Android/sandbox/} along with all their subdirectories and content.
- */
- private static final Pattern PATTERN_RESTRICTED_ANDROID_SUBTREES =
- Pattern.compile("^Android/(?:data|obb|sandbox)(?:/.+)?", CASE_INSENSITIVE);
+ private static final String PRIMARY_EMULATED_STORAGE_PATH = "/storage/emulated/";
+
+ private static final String STORAGE_PATH = "/storage/";
private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
@@ -308,10 +306,69 @@ public class ExternalStorageProvider extends FileSystemProvider {
return false;
}
- final String path = getPathFromDocId(documentId);
- return PATTERN_RESTRICTED_ANDROID_SUBTREES.matcher(path).matches();
+ try {
+ final RootInfo root = getRootFromDocId(documentId);
+ final String canonicalPath = getPathFromDocId(documentId);
+ return isRestrictedPath(root.rootId, canonicalPath);
+ } catch (Exception e) {
+ return true;
+ }
}
+ /**
+ * Based on the given root id and path, we restrict path access if file is Android/data or
+ * Android/obb or Android/sandbox or one of their subdirectories.
+ *
+ * @param canonicalPath of the file
+ * @return true if path is restricted
+ */
+ private boolean isRestrictedPath(String rootId, String canonicalPath) {
+ if (rootId == null || canonicalPath == null) {
+ return true;
+ }
+
+ final String rootPath;
+ if (rootId.equalsIgnoreCase(ROOT_ID_PRIMARY_EMULATED)) {
+ // Creates "/storage/emulated/<user-id>"
+ rootPath = PRIMARY_EMULATED_STORAGE_PATH + UserHandle.myUserId();
+ } else {
+ // Creates "/storage/<volume-uuid>"
+ rootPath = STORAGE_PATH + rootId;
+ }
+ List<java.nio.file.Path> restrictedPathList = Arrays.asList(
+ Paths.get(rootPath, "Android", "data"),
+ Paths.get(rootPath, "Android", "obb"),
+ Paths.get(rootPath, "Android", "sandbox"));
+ // We need to identify restricted parent paths which actually exist on the device
+ List<java.nio.file.Path> validRestrictedPathsToCheck = restrictedPathList.stream().filter(
+ Files::exists).collect(Collectors.toList());
+
+ boolean isRestricted = false;
+ java.nio.file.Path filePathToCheck = Paths.get(rootPath, canonicalPath);
+ try {
+ while (filePathToCheck != null) {
+ for (java.nio.file.Path restrictedPath : validRestrictedPathsToCheck) {
+ if (Files.isSameFile(restrictedPath, filePathToCheck)) {
+ isRestricted = true;
+ Log.v(TAG, "Restricting access for path: " + filePathToCheck);
+ break;
+ }
+ }
+ if (isRestricted) {
+ break;
+ }
+
+ filePathToCheck = filePathToCheck.getParent();
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Error in checking file equality check.", e);
+ isRestricted = true;
+ }
+
+ return isRestricted;
+ }
+
+
/**
* Check that the directory is the root of storage or blocked file from tree.
* <p>