summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFyodor Kupolov <fkupolov@google.com>2017-02-09 16:46:06 -0800
committerMSe <mse1969@posteo.de>2017-07-06 23:05:15 +0200
commit636a75380a27069d72a9a8bdb318d418488e3c82 (patch)
treee9c737b15043791225efec786bcff6244faeb65a
parented512acf8a61e407772696ebb3660fc492f135ea (diff)
downloadandroid_packages_providers_MediaProvider-636a75380a27069d72a9a8bdb318d418488e3c82.tar.gz
android_packages_providers_MediaProvider-636a75380a27069d72a9a8bdb318d418488e3c82.tar.bz2
android_packages_providers_MediaProvider-636a75380a27069d72a9a8bdb318d418488e3c82.zip
[DO NOT MERGE] Enforce user separation on external storagereplicant-6.0-0002
With WRITE_MEDIA_STORAGE permission, MediaProvider can access external storage across users. Access should be rejected for content in other user's external storage if the caller has no WRITE_MEDIA_STORAGE/INTERACT_ACROSS_USERS Test: manual + android.provider.cts.MediaStore_FilesTest Bug: 34114752 AOSP-Change-Id: I577cc33574185657592246c1103df4174ff3acf6 (cherry picked from commit cc1cecc9be51f9655d9acdf1729345d16f078c21) CVE-2017-0669 Change-Id: Id986720c8265eaba91c809277b97d0ff4a2fc6ba
-rwxr-xr-xsrc/com/android/providers/media/MediaProvider.java43
1 files changed, 42 insertions, 1 deletions
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index fb5551fc..1f15ab20 100755
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -17,6 +17,7 @@
package com.android.providers.media;
import static android.Manifest.permission.ACCESS_CACHE_FILESYSTEM;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
@@ -42,6 +43,7 @@ import android.content.SharedPreferences;
import android.content.UriMatcher;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.DatabaseUtils;
@@ -61,6 +63,7 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
+import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
@@ -68,6 +71,8 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
@@ -136,7 +141,6 @@ public class MediaProvider extends ContentProvider {
private void updateStoragePaths() {
mExternalStoragePaths = mStorageManager.getVolumePaths();
-
try {
mExternalPath =
Environment.getExternalStorageDirectory().getCanonicalPath() + File.separator;
@@ -4787,10 +4791,47 @@ public class MediaProvider extends ContentProvider {
// don't write to non-cache, non-sdcard files.
throw new FileNotFoundException("Can't access " + file);
} else {
+ boolean hasWriteMediaStorage = c.checkCallingOrSelfPermission(WRITE_MEDIA_STORAGE)
+ == PackageManager.PERMISSION_GRANTED;
+ boolean hasInteractAcrossUsers = c.checkCallingOrSelfPermission(INTERACT_ACROSS_USERS)
+ == PackageManager.PERMISSION_GRANTED;
+ if (!hasWriteMediaStorage && !hasInteractAcrossUsers && isOtherUserExternalDir(path)) {
+ throw new FileNotFoundException("Can't access across users " + file);
+ }
checkWorldReadAccess(path);
}
}
+ private boolean isOtherUserExternalDir(String path) {
+ List<VolumeInfo> volumes = mStorageManager.getVolumes();
+ for (VolumeInfo volume : volumes) {
+ if (contains(volume.path, path)) {
+ // If any of mExternalStoragePaths belongs to this volume and doesn't contain
+ // the path, then we consider the path to be from another user
+ for (String externalStoragePath : mExternalStoragePaths) {
+ if (contains(volume.path, externalStoragePath)
+ && !contains(externalStoragePath, path)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private static boolean contains(String dirPath, String filePath) {
+ if (dirPath== null || filePath == null) return false;
+
+ if (dirPath.equals(filePath)) {
+ return true;
+ }
+
+ if (!dirPath.endsWith("/")) {
+ dirPath += "/";
+ }
+ return filePath.startsWith(dirPath);
+ }
+
private boolean isSecondaryExternalPath(String path) {
for (int i = 1; i < mExternalStoragePaths.length; i++) {
if (path.startsWith(mExternalStoragePaths[i])) {