diff options
author | Jeff Sharkey <jsharkey@android.com> | 2015-07-13 10:25:58 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2015-07-14 13:04:39 -0700 |
commit | ed30deae5fe5b9de142b44933001c9b098c47712 (patch) | |
tree | f2bca00dbce87798aca9e73c43b8abb074e10d14 /src/com/android/providers/downloads/DownloadProvider.java | |
parent | d473cf8f85f60d53b20270a263afe6b138671cb5 (diff) | |
download | android_packages_providers_DownloadProvider-ed30deae5fe5b9de142b44933001c9b098c47712.tar.gz android_packages_providers_DownloadProvider-ed30deae5fe5b9de142b44933001c9b098c47712.tar.bz2 android_packages_providers_DownloadProvider-ed30deae5fe5b9de142b44933001c9b098c47712.zip |
Relax permissions on package-specific paths.
Normally apps must hold the WRITE_EXTERNAL_STORAGE permission in
order to use DownloadManager. However, now that the platform has
relaxed permissions on package-specific directories, we relax the
DownloadManager check in a similar way. This also opens up using
DownloadManager to save files on secondary external storage devices.
Fix bug so that we now check the relevant volume state when thinking
about resuming a download.
Bug: 22135060
Change-Id: If439340ea48789ea167f49709b5b69a4f0883150
Diffstat (limited to 'src/com/android/providers/downloads/DownloadProvider.java')
-rw-r--r-- | src/com/android/providers/downloads/DownloadProvider.java | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java index 2087c227..b080d703 100644 --- a/src/com/android/providers/downloads/DownloadProvider.java +++ b/src/com/android/providers/downloads/DownloadProvider.java @@ -16,6 +16,7 @@ package com.android.providers.downloads; +import android.app.AppOpsManager; import android.app.DownloadManager; import android.app.DownloadManager.Request; import android.content.ContentProvider; @@ -34,7 +35,6 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import android.os.Binder; -import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.ParcelFileDescriptor; @@ -47,12 +47,12 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; +import libcore.io.IoUtils; + import com.android.internal.util.IndentingPrintWriter; import com.google.android.collect.Maps; import com.google.common.annotations.VisibleForTesting; -import libcore.io.IoUtils; - import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; @@ -555,11 +555,19 @@ public final class DownloadProvider extends ContentProvider { dest = Downloads.Impl.DESTINATION_CACHE_PARTITION; } if (dest == Downloads.Impl.DESTINATION_FILE_URI) { - getContext().enforcePermission( - android.Manifest.permission.WRITE_EXTERNAL_STORAGE, - Binder.getCallingPid(), Binder.getCallingUid(), - "need WRITE_EXTERNAL_STORAGE permission to use DESTINATION_FILE_URI"); checkFileUriDestination(values); + + } else if (dest == Downloads.Impl.DESTINATION_EXTERNAL) { + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.WRITE_EXTERNAL_STORAGE, + "No permission to write"); + + final AppOpsManager appOps = getContext().getSystemService(AppOpsManager.class); + if (appOps.noteOp(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, Binder.getCallingUid(), + getCallingPackage()) != AppOpsManager.MODE_ALLOWED) { + throw new SecurityException("No permission to write"); + } + } else if (dest == Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION) { getContext().enforcePermission( android.Manifest.permission.ACCESS_CACHE_FILESYSTEM, @@ -706,14 +714,25 @@ public final class DownloadProvider extends ContentProvider { if (path == null) { throw new IllegalArgumentException("Invalid file URI: " + uri); } - try { - final String canonicalPath = new File(path).getCanonicalPath(); - final String externalPath = Environment.getExternalStorageDirectory().getAbsolutePath(); - if (!canonicalPath.startsWith(externalPath)) { - throw new SecurityException("Destination must be on external storage: " + uri); + + final File file = new File(path); + if (Helpers.isFilenameValidInExternalPackage(getContext(), file, getCallingPackage())) { + // No permissions required for paths belonging to calling package + return; + } else if (Helpers.isFilenameValidInExternal(getContext(), file)) { + // Otherwise we require write permission + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.WRITE_EXTERNAL_STORAGE, + "No permission to write to " + file); + + final AppOpsManager appOps = getContext().getSystemService(AppOpsManager.class); + if (appOps.noteOp(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, Binder.getCallingUid(), + getCallingPackage()) != AppOpsManager.MODE_ALLOWED) { + throw new SecurityException("No permission to write to " + file); } - } catch (IOException e) { - throw new SecurityException("Problem resolving path: " + uri); + + } else { + throw new SecurityException("Unsupported path " + file); } } |