summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Manish Singh <psych@google.com> 2021-02-05 23:50:08 +0000
committer Manish Singh <psych@google.com> 2021-02-14 03:20:28 +0000
commit9a6ccce2f749cc1db5555b5e105d5ac234bc8bdb (patch)
tree73e25003759afccf2870cb0255eb5705439581b2
parent461ff39241095f1d88c4d2fceeaeb13856361ee5 (diff)
Change who gets marked for the cost of transcoding
Since we now provide the ability to specify EXTRA_MEDIA_CAPABILITIES_UID, the decision to transcode or not is based on that uid. In such cases, it's not fair to mark the uid that called us with the request for transcoding as the one causing the transform. In normal cases, this change will have no effect, the calling app will get marked as the one causing transcoding. In cases where MediaDocumentsProvider or ExternalStorageProvider are opening on behalf of another app (that cannot handle the modern format), we use the uid of this app to mark as the one causing transcoding cost. In cases where a modern app opens and shares the fd with a legacy app, we want to mark the legacy app (transcoding actaully happened because of the legacy app after all). And finally, if a legacy app uses the EXTRA_MEDIA_CAPABILITIES_UID of another legacy app, but reads the file itself, in such cases we want to mark the first app itself, so as to prevent any abuse of this facility. Therefore, we store and then pass the media capabilities uid via jni to MediaProvider at the time of read. This allows us to make the correct decision for all the cases mentioned above. BUG: 176157500, 154734139 Test: manual Change-Id: I8f2bd759685e884cb0565c2f677755583987cb78
-rwxr-xr-xjni/FuseDaemon.cpp23
-rw-r--r--jni/MediaProviderWrapper.cpp18
-rw-r--r--jni/MediaProviderWrapper.h11
-rw-r--r--jni/node-inl.h11
-rw-r--r--jni/node_test.cpp5
-rw-r--r--src/com/android/providers/media/FileOpenResult.java4
-rw-r--r--src/com/android/providers/media/MediaProvider.java126
7 files changed, 140 insertions, 58 deletions
diff --git a/jni/FuseDaemon.cpp b/jni/FuseDaemon.cpp
index 53e54d046..37a8faac3 100755
--- a/jni/FuseDaemon.cpp
+++ b/jni/FuseDaemon.cpp
@@ -1037,17 +1037,22 @@ static void pf_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t new_parent,
*/
static handle* create_handle_for_node(struct fuse* fuse, const string& path, int fd, uid_t uid,
- node* node, const RedactionInfo* ri, int* keep_cache) {
+ uid_t transforms_uid, node* node, const RedactionInfo* ri,
+ int* keep_cache) {
std::lock_guard<std::recursive_mutex> guard(fuse->lock);
bool redaction_needed = ri->isRedactionNeeded();
handle* handle = nullptr;
+ int transforms = node->GetTransforms();
+ if (transforms_uid > 0) {
+ CHECK(transforms);
+ }
if (fuse->passthrough) {
*keep_cache = 1;
handle = new struct handle(fd, ri, true /* cached */,
- !redaction_needed || node->GetTransforms() /* passthrough */,
- uid);
+ !redaction_needed || transforms /* passthrough */, uid,
+ transforms_uid);
} else {
// Without fuse->passthrough, we don't want to use the FUSE VFS cache in two cases:
// 1. When redaction is needed because app A with EXIF access might access
@@ -1075,7 +1080,8 @@ static handle* create_handle_for_node(struct fuse* fuse, const string& path, int
} else {
*keep_cache = 1;
}
- handle = new struct handle(fd, ri, !direct_io /* cached */, false /* passthrough */, uid);
+ handle = new struct handle(fd, ri, !direct_io /* cached */, false /* passthrough */, uid,
+ transforms_uid);
}
node->AddHandle(handle);
@@ -1153,7 +1159,7 @@ static void pf_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) {
}
int keep_cache = 1;
- handle* h = create_handle_for_node(fuse, io_path, fd, result->uid, node,
+ handle* h = create_handle_for_node(fuse, io_path, fd, result->uid, result->transforms_uid, node,
result->redaction_info.release(), &keep_cache);
fi->fh = ptr_to_id(h);
fi->keep_cache = keep_cache;
@@ -1256,7 +1262,8 @@ static void pf_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
if (!node->IsTransformsComplete()) {
if (!fuse->mp->Transform(node->BuildPath(), node->GetIoPath(), node->GetTransforms(),
- node->GetTransformsReason(), h->uid)) {
+ node->GetTransformsReason(), req->ctx.uid, h->uid,
+ h->transforms_uid)) {
fuse_reply_err(req, EFAULT);
return;
}
@@ -1714,8 +1721,8 @@ static void pf_create(fuse_req_t req,
// to the file before all the EXIF content is written. We could special case reads before the
// first close after a file has just been created.
int keep_cache = 1;
- handle* h = create_handle_for_node(fuse, child_path, fd, req->ctx.uid, node,
- new RedactionInfo(), &keep_cache);
+ handle* h = create_handle_for_node(fuse, child_path, fd, req->ctx.uid, 0 /* transforms_uid */,
+ node, new RedactionInfo(), &keep_cache);
fi->fh = ptr_to_id(h);
fi->keep_cache = keep_cache;
fi->direct_io = !h->cached;
diff --git a/jni/MediaProviderWrapper.cpp b/jni/MediaProviderWrapper.cpp
index c049ddbba..9f8a7597a 100644
--- a/jni/MediaProviderWrapper.cpp
+++ b/jni/MediaProviderWrapper.cpp
@@ -253,7 +253,7 @@ MediaProviderWrapper::MediaProviderWrapper(JNIEnv* env, jobject media_provider)
/*is_static*/ false);
mid_is_app_clone_user_ = CacheMethod(env, "isAppCloneUser", "(I)Z",
/*is_static*/ false);
- mid_transform_ = CacheMethod(env, "transform", "(Ljava/lang/String;Ljava/lang/String;III)Z",
+ mid_transform_ = CacheMethod(env, "transform", "(Ljava/lang/String;Ljava/lang/String;IIIII)Z",
/*is_static*/ false);
mid_file_lookup_ =
CacheMethod(env, "onFileLookup",
@@ -286,6 +286,7 @@ MediaProviderWrapper::MediaProviderWrapper(JNIEnv* env, jobject media_provider)
file_open_result_class_ = reinterpret_cast<jclass>(env->NewGlobalRef(file_open_result_class_));
fid_file_open_status_ = CacheField(env, file_open_result_class_, "status", "I");
fid_file_open_uid_ = CacheField(env, file_open_result_class_, "uid", "I");
+ fid_file_open_transforms_uid_ = CacheField(env, file_open_result_class_, "transformsUid", "I");
fid_file_open_redaction_ranges_ =
CacheField(env, file_open_result_class_, "redactionRanges", "[J");
}
@@ -322,7 +323,7 @@ std::unique_ptr<FileOpenResult> MediaProviderWrapper::OnFileOpen(const string& p
bool log_transforms_metrics) {
JNIEnv* env = MaybeAttachCurrentThread();
if (shouldBypassMediaProvider(uid)) {
- return std::make_unique<FileOpenResult>(0, uid, new RedactionInfo());
+ return std::make_unique<FileOpenResult>(0, uid, 0 /* transforms_uid */, new RedactionInfo());
}
ScopedLocalRef<jstring> j_path(env, env->NewStringUTF(path.c_str()));
@@ -338,6 +339,8 @@ std::unique_ptr<FileOpenResult> MediaProviderWrapper::OnFileOpen(const string& p
int status = env->GetIntField(j_res_file_open_object.get(), fid_file_open_status_);
int original_uid = env->GetIntField(j_res_file_open_object.get(), fid_file_open_uid_);
+ int transforms_uid =
+ env->GetIntField(j_res_file_open_object.get(), fid_file_open_transforms_uid_);
if (redact) {
ScopedLocalRef<jlongArray> redaction_ranges_local_ref(
@@ -355,9 +358,10 @@ std::unique_ptr<FileOpenResult> MediaProviderWrapper::OnFileOpen(const string& p
// No ranges to redact
ri = std::make_unique<RedactionInfo>();
}
- return std::make_unique<FileOpenResult>(status, original_uid, ri.release());
+ return std::make_unique<FileOpenResult>(status, original_uid, transforms_uid, ri.release());
} else {
- return std::make_unique<FileOpenResult>(status, original_uid, new RedactionInfo());
+ return std::make_unique<FileOpenResult>(status, original_uid, transforms_uid,
+ new RedactionInfo());
}
}
@@ -503,13 +507,15 @@ std::unique_ptr<FileLookupResult> MediaProviderWrapper::FileLookup(const std::st
}
bool MediaProviderWrapper::Transform(const std::string& src, const std::string& dst, int transforms,
- int transforms_reason, uid_t uid) {
+ int transforms_reason, uid_t read_uid, uid_t open_uid,
+ uid_t transforms_uid) {
JNIEnv* env = MaybeAttachCurrentThread();
ScopedLocalRef<jstring> j_src(env, env->NewStringUTF(src.c_str()));
ScopedLocalRef<jstring> j_dst(env, env->NewStringUTF(dst.c_str()));
bool res = env->CallBooleanMethod(media_provider_object_, mid_transform_, j_src.get(),
- j_dst.get(), transforms, transforms_reason, uid);
+ j_dst.get(), transforms, transforms_reason, read_uid,
+ open_uid, transforms_uid);
if (CheckForJniException(env)) {
return false;
diff --git a/jni/MediaProviderWrapper.h b/jni/MediaProviderWrapper.h
index c33ee62ec..2ad176997 100644
--- a/jni/MediaProviderWrapper.h
+++ b/jni/MediaProviderWrapper.h
@@ -38,11 +38,13 @@ namespace fuse {
/** Represents file open result from MediaProvider */
struct FileOpenResult {
- FileOpenResult(const int status, const int uid, const RedactionInfo* redaction_info)
- : status(status), uid(uid), redaction_info(redaction_info) {}
+ FileOpenResult(const int status, const int uid, uid_t transforms_uid,
+ const RedactionInfo* redaction_info)
+ : status(status), uid(uid), transforms_uid(transforms_uid), redaction_info(redaction_info) {}
const int status;
const int uid;
+ const uid_t transforms_uid;
std::unique_ptr<const RedactionInfo> redaction_info;
};
@@ -65,7 +67,7 @@ struct FileLookupResult {
}
/**
- * This field is not to be interpreted, it is determined and populated from MediaProvider
+ * These fields are not to be interpreted, they are determined and populated from MediaProvider
* via a JNI call.
*/
const int transforms;
@@ -221,7 +223,7 @@ class MediaProviderWrapper final {
/** Transforms from src to dst file */
bool Transform(const std::string& src, const std::string& dst, int transforms,
- int transforms_reason, uid_t uid);
+ int transforms_reason, uid_t read_uid, uid_t open_uid, uid_t transforms_uid);
/**
* Determines if to allow FUSE_LOOKUP for uid. Might allow uids that don't belong to the
@@ -277,6 +279,7 @@ class MediaProviderWrapper final {
/** Cached FileOpenResult field IDs **/
jfieldID fid_file_open_status_;
jfieldID fid_file_open_uid_;
+ jfieldID fid_file_open_transforms_uid_;
jfieldID fid_file_open_redaction_ranges_;
/**
diff --git a/jni/node-inl.h b/jni/node-inl.h
index 99960ed30..8a974966d 100644
--- a/jni/node-inl.h
+++ b/jni/node-inl.h
@@ -41,8 +41,14 @@ namespace mediaprovider {
namespace fuse {
struct handle {
- explicit handle(int fd, const RedactionInfo* ri, bool cached, bool passthrough, uid_t uid)
- : fd(fd), ri(ri), cached(cached), passthrough(passthrough), uid(uid) {
+ explicit handle(int fd, const RedactionInfo* ri, bool cached, bool passthrough, uid_t uid,
+ uid_t transforms_uid)
+ : fd(fd),
+ ri(ri),
+ cached(cached),
+ passthrough(passthrough),
+ uid(uid),
+ transforms_uid(transforms_uid) {
CHECK(ri != nullptr);
}
@@ -51,6 +57,7 @@ struct handle {
const bool cached;
const bool passthrough;
const uid_t uid;
+ const uid_t transforms_uid;
~handle() { close(fd); }
};
diff --git a/jni/node_test.cpp b/jni/node_test.cpp
index ddb15ceb6..8df06f8c8 100644
--- a/jni/node_test.cpp
+++ b/jni/node_test.cpp
@@ -350,7 +350,7 @@ TEST_F(NodeTest, AddDestroyHandle) {
unique_node_ptr node = CreateNode(nullptr, "/path");
handle* h = new handle(-1, new mediaprovider::fuse::RedactionInfo, true /* cached */,
- false /* passthrough */, 0 /* uid */);
+ false /* passthrough */, 0 /* uid */, 0 /* transforms_uid */);
node->AddHandle(h);
ASSERT_TRUE(node->HasCachedHandle());
@@ -362,7 +362,8 @@ TEST_F(NodeTest, AddDestroyHandle) {
EXPECT_DEATH(node->DestroyHandle(h), "");
EXPECT_DEATH(node->DestroyHandle(nullptr), "");
std::unique_ptr<handle> h2(new handle(-1, new mediaprovider::fuse::RedactionInfo,
- true /* cached */, false /* passthrough */, 0 /* uid */));
+ true /* cached */, false /* passthrough */, 0 /* uid */,
+ 0 /* transforms_uid */));
EXPECT_DEATH(node->DestroyHandle(h2.get()), "");
}
diff --git a/src/com/android/providers/media/FileOpenResult.java b/src/com/android/providers/media/FileOpenResult.java
index 7777b8bdb..1052f98ae 100644
--- a/src/com/android/providers/media/FileOpenResult.java
+++ b/src/com/android/providers/media/FileOpenResult.java
@@ -22,11 +22,13 @@ package com.android.providers.media;
public final class FileOpenResult {
public final int status;
public final int uid;
+ public final int transformsUid;
public final long[] redactionRanges;
- public FileOpenResult(int status, int uid, long[] redactionRanges) {
+ public FileOpenResult(int status, int uid, int transformsUid, long[] redactionRanges) {
this.status = status;
this.uid = uid;
+ this.transformsUid = transformsUid;
this.redactionRanges = redactionRanges;
}
}
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 9b46162b2..8b05a03c2 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -133,6 +133,7 @@ import android.os.Environment;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.OnCloseListener;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -1363,19 +1364,47 @@ public class MediaProvider extends ContentProvider {
* @param src file path to transform
* @param dst file path to save transformed file
* @param flags determines the kind of transform
- * @param uid app requesting transform
+ * @param readUid app that called us requesting transform
+ * @param openUid app that originally made the open call
+ * @param mediaCapabilitiesUid app for which the transform decision was made,
+ * 0 if decision was made with openUid
*
* Called from JNI in jni/MediaProviderWrapper.cpp
*/
@Keep
public boolean transformForFuse(String src, String dst, int transforms, int transformsReason,
- int uid) {
+ int readUid, int openUid, int mediaCapabilitiesUid) {
if ((transforms & FLAG_TRANSFORM_TRANSCODING) != 0) {
if (mTranscodeHelper.isTranscodeFileCached(src, dst)) {
Log.d(TAG, "Using transcode cache for " + src);
return true;
}
- return mTranscodeHelper.transcode(src, dst, uid, transformsReason);
+
+ // In general we always mark the opener as causing transcoding.
+ // However, if the mediaCapabilitiesUid is available then we mark the reader as causing
+ // transcoding. This handles the case where a malicious app might want to take
+ // advantage of mediaCapabilitiesUid by setting it to another app's uid and reading the
+ // media contents itself; in such cases we'd mark the reader (malicious app) for the
+ // cost of transcoding.
+ //
+ // openUid readUid mediaCapabilitiesUid
+ // -------------------------------------------------------------------------------------
+ // using picker SAF app app
+ // abusive case bad app bad app victim
+ // modern to lega-
+ // -cy sharing modern legacy legacy
+ //
+ // we'd not be here in the below case.
+ // legacy to mode-
+ // -rn sharing legacy modern modern
+
+ int transcodeUid = openUid;
+ if (mediaCapabilitiesUid > 0) {
+ Log.d(TAG, "Fix up transcodeUid to " + readUid + ". openUid " + openUid
+ + ", mediaCapabilitiesUid " + mediaCapabilitiesUid);
+ transcodeUid = readUid;
+ }
+ return mTranscodeHelper.transcode(src, dst, transcodeUid, transformsReason);
}
return true;
}
@@ -1410,8 +1439,7 @@ public class MediaProvider extends ContentProvider {
if (info != null && info.uid == uid) {
transformsReason = info.transcodeReason;
} else {
- transformsReason = mTranscodeHelper.shouldTranscode(path, uid,
- null /* bundle */);
+ transformsReason = mTranscodeHelper.shouldTranscode(path, uid, null /* bundle */);
}
if (transformsReason > 0) {
@@ -6720,15 +6748,19 @@ public class MediaProvider extends ContentProvider {
return new File(filePath);
}
- private ParcelFileDescriptor openWithFuse(String filePath, int uid, int modeBits,
- boolean shouldRedact, boolean shouldTranscode, int transcodeReason)
+ private ParcelFileDescriptor openWithFuse(String filePath, int uid, int mediaCapabilitiesUid,
+ int modeBits, boolean shouldRedact, boolean shouldTranscode, int transcodeReason)
throws FileNotFoundException {
- Log.d(TAG, "Open with FUSE. FilePath: " + filePath + ". Uid: " + uid
- + ". ShouldRedact: " + shouldRedact + ". ShouldTranscode: " + shouldTranscode);
+ Log.d(TAG, "Open with FUSE. FilePath: " + filePath
+ + ". Uid: " + uid
+ + ". Media Capabilities Uid: " + mediaCapabilitiesUid
+ + ". ShouldRedact: " + shouldRedact
+ + ". ShouldTranscode: " + shouldTranscode);
int tid = android.os.Process.myTid();
synchronized (mPendingOpenInfo) {
- mPendingOpenInfo.put(tid, new PendingOpenInfo(uid, shouldRedact, transcodeReason));
+ mPendingOpenInfo.put(tid,
+ new PendingOpenInfo(uid, mediaCapabilitiesUid, shouldRedact, transcodeReason));
}
try {
@@ -6869,16 +6901,22 @@ public class MediaProvider extends ContentProvider {
final ParcelFileDescriptor pfd;
final String filePath = file.getPath();
final int uid = Binder.getCallingUid();
- int transcodeReason = mTranscodeHelper.shouldTranscode(filePath, uid, opts);
- boolean shouldTranscode = transcodeReason > 0;
+ final int transcodeReason = mTranscodeHelper.shouldTranscode(filePath, uid, opts);
+ final boolean shouldTranscode = transcodeReason > 0;
+ int mediaCapabilitiesUid = opts.getInt(MediaStore.EXTRA_MEDIA_CAPABILITIES_UID);
+ if (!shouldTranscode || mediaCapabilitiesUid < Process.FIRST_APPLICATION_UID) {
+ // Although 0 is a valid UID, it's not a valid app uid.
+ // So, we use it to signify that mediaCapabilitiesUid is not set.
+ mediaCapabilitiesUid = 0;
+ }
if (redactionInfo.redactionRanges.length > 0) {
// If fuse is enabled, we can provide an fd that points to the fuse
// file system and handle redaction in the fuse handler when the caller reads.
- pfd = openWithFuse(filePath, uid, modeBits, true /* shouldRedact */,
- shouldTranscode, transcodeReason);
+ pfd = openWithFuse(filePath, uid, mediaCapabilitiesUid, modeBits,
+ true /* shouldRedact */, shouldTranscode, transcodeReason);
} else if (shouldTranscode) {
- pfd = openWithFuse(filePath, uid, modeBits, false /* shouldRedact */,
- shouldTranscode, transcodeReason);
+ pfd = openWithFuse(filePath, uid, mediaCapabilitiesUid, modeBits,
+ false /* shouldRedact */, shouldTranscode, transcodeReason);
} else {
FuseDaemon daemon = null;
try {
@@ -6889,15 +6927,16 @@ public class MediaProvider extends ContentProvider {
// Always acquire a readLock. This allows us make multiple opens via lower
// filesystem
boolean shouldOpenWithFuse = daemon != null
- && daemon.shouldOpenWithFuse(filePath, true /* forRead */, lowerFsFd.getFd());
+ && daemon.shouldOpenWithFuse(filePath, true /* forRead */,
+ lowerFsFd.getFd());
if (shouldOpenWithFuse) {
// If the file is already opened on the FUSE mount with VFS caching enabled
// we return an upper filesystem fd (via FUSE) to avoid file corruption
// resulting from cache inconsistencies between the upper and lower
// filesystem caches
- pfd = openWithFuse(filePath, uid, modeBits, false /* shouldRedact */,
- shouldTranscode, transcodeReason);
+ pfd = openWithFuse(filePath, uid, mediaCapabilitiesUid, modeBits,
+ false /* shouldRedact */, shouldTranscode, transcodeReason);
try {
lowerFsFd.close();
} catch (IOException e) {
@@ -7165,10 +7204,14 @@ public class MediaProvider extends ContentProvider {
private static final class PendingOpenInfo {
public final int uid;
+ public final int mediaCapabilitiesUid;
public final boolean shouldRedact;
public final int transcodeReason;
- public PendingOpenInfo(int uid, boolean shouldRedact, int transcodeReason) {
+
+ public PendingOpenInfo(int uid, int mediaCapabilitiesUid, boolean shouldRedact,
+ int transcodeReason) {
this.uid = uid;
+ this.mediaCapabilitiesUid = mediaCapabilitiesUid;
this.shouldRedact = shouldRedact;
this.transcodeReason = transcodeReason;
}
@@ -7341,28 +7384,39 @@ public class MediaProvider extends ContentProvider {
@Keep
public FileOpenResult onFileOpenForFuse(String path, String ioPath, int uid, int tid,
int transformsReason, boolean forWrite, boolean redact, boolean logTransformsMetrics) {
- int original_uid = getBinderUidForFuse(uid, tid);
-
final LocalCallingIdentity token =
clearLocalCallingIdentity(getCachedCallingIdentityForFuse(uid));
boolean isSuccess = false;
+
+ final int originalUid = getBinderUidForFuse(uid, tid);
+ int mediaCapabilitiesUid = 0;
+ final PendingOpenInfo pendingOpenInfo;
+ synchronized (mPendingOpenInfo) {
+ pendingOpenInfo = mPendingOpenInfo.get(tid);
+ }
+
+ if (pendingOpenInfo != null && pendingOpenInfo.uid == originalUid) {
+ mediaCapabilitiesUid = pendingOpenInfo.mediaCapabilitiesUid;
+ }
+
try {
if (isPrivatePackagePathNotAccessibleByCaller(path)) {
Log.e(TAG, "Can't open a file in another app's external directory!");
- return new FileOpenResult(OsConstants.ENOENT, original_uid, new long[0]);
+ return new FileOpenResult(OsConstants.ENOENT, originalUid, mediaCapabilitiesUid,
+ new long[0]);
}
if (shouldBypassFuseRestrictions(forWrite, path)) {
isSuccess = true;
- return new FileOpenResult(0 /* status */, original_uid,
- redact ? getRedactionRangesForFuse(path, ioPath, original_uid, uid, tid) :
- new long[0]);
+ return new FileOpenResult(0 /* status */, originalUid, mediaCapabilitiesUid,
+ redact ? getRedactionRangesForFuse(path, ioPath, originalUid, uid, tid) :
+ new long[0]);
}
// Legacy apps that made is this far don't have the right storage permission and hence
// are not allowed to access anything other than their external app directory
if (isCallingPackageRequestingLegacy()) {
- return new FileOpenResult(OsConstants.EACCES /* status */, original_uid,
- new long[0]);
+ return new FileOpenResult(OsConstants.EACCES /* status */, originalUid,
+ mediaCapabilitiesUid, new long[0]);
}
final Uri contentUri = FileUtils.getContentUriForPath(path);
@@ -7372,7 +7426,7 @@ public class MediaProvider extends ContentProvider {
MediaColumns.IS_PENDING,
FileColumns.MEDIA_TYPE};
final String selection = MediaColumns.DATA + "=?";
- final String[] selectionArgs = new String[]{ path };
+ final String[] selectionArgs = new String[]{path};
final long id;
final int mediaType;
final boolean isPending;
@@ -7410,22 +7464,24 @@ public class MediaProvider extends ContentProvider {
}
}
isSuccess = true;
- return new FileOpenResult(0 /* status */, original_uid,
- redact ? getRedactionRangesForFuse(path, ioPath, original_uid, uid, tid) :
- new long[0]);
+ return new FileOpenResult(0 /* status */, originalUid, mediaCapabilitiesUid,
+ redact ? getRedactionRangesForFuse(path, ioPath, originalUid, uid, tid) :
+ new long[0]);
} catch (IOException e) {
// We are here because
// * There is no db row corresponding to the requested path, which is more unlikely.
// * getRedactionRangesForFuse couldn't fetch the redaction info correctly
// In all of these cases, it means that app doesn't have access permission to the file.
Log.e(TAG, "Couldn't find file: " + path, e);
- return new FileOpenResult(OsConstants.EACCES /* status */, original_uid, new long[0]);
+ return new FileOpenResult(OsConstants.EACCES /* status */, originalUid,
+ mediaCapabilitiesUid, new long[0]);
} catch (IllegalStateException | SecurityException e) {
Log.e(TAG, "Permission to access file: " + path + " is denied");
- return new FileOpenResult(OsConstants.EACCES /* status */, original_uid, new long[0]);
+ return new FileOpenResult(OsConstants.EACCES /* status */, originalUid,
+ mediaCapabilitiesUid, new long[0]);
} finally {
if (isSuccess && logTransformsMetrics) {
- notifyTranscodeHelperOnFileOpen(path, ioPath, original_uid, transformsReason);
+ notifyTranscodeHelperOnFileOpen(path, ioPath, originalUid, transformsReason);
}
restoreLocalCallingIdentity(token);
}