summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/downloads/DownloadProvider.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/providers/downloads/DownloadProvider.java')
-rw-r--r--src/com/android/providers/downloads/DownloadProvider.java47
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);
}
}