diff options
author | Fyodor Kupolov <fkupolov@google.com> | 2017-02-09 16:46:06 -0800 |
---|---|---|
committer | MSe <mse1969@posteo.de> | 2017-07-06 23:05:15 +0200 |
commit | 636a75380a27069d72a9a8bdb318d418488e3c82 (patch) | |
tree | e9c737b15043791225efec786bcff6244faeb65a | |
parent | ed512acf8a61e407772696ebb3660fc492f135ea (diff) | |
download | android_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-x | src/com/android/providers/media/MediaProvider.java | 43 |
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])) { |