mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-15 02:44:23 -05:00
8b43c0a51a
Signed-off-by: Tavi <tavi@divested.dev>
138 lines
5.6 KiB
Diff
138 lines
5.6 KiB
Diff
From e1c64096a439b5d54a5cb6de77242217b1516ca1 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 53e17e35953d1..a722c08605083 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.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 @@ protected boolean shouldHideDocument(@NonNull String documentId) {
|
|
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>
|