diff options
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); } } |