From d2b64d70189f3451aa1f7e018274dbc4c3529bf1 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 19 Oct 2018 15:40:03 -0600 Subject: [PATCH] Add ContentProvider.clearCallingIdentity(). ContentProvider has a getCallingPackage() method, which verifies the remote package name against the current Binder identity. When a provider wants to clear that IPC identity, they need to clear both the Binder state and the ContentProvider.getCallingPackage() state together, so add methods to facilitate that. Also fix subtle bug so we don't try translating relative paths. Bug: 117627072 Test: atest cts/tests/tests/provider/src/android/provider/cts/MediaStore* Change-Id: Ifa3e1f745334abf625fdcc314b308a047c49ce73 --- api/current.txt | 5 +++ .../java/android/content/ContentProvider.java | 42 +++++++++++++++++++ .../android/os/storage/StorageManager.java | 6 +++ 3 files changed, 53 insertions(+) diff --git a/api/current.txt b/api/current.txt index a52c1cc1cd41c..1983fb483ecd5 100755 --- a/api/current.txt +++ b/api/current.txt @@ -9168,6 +9168,7 @@ package android.content { method public int bulkInsert(android.net.Uri, android.content.ContentValues[]); method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle); method public android.net.Uri canonicalize(android.net.Uri); + method public final android.content.ContentProvider.CallingIdentity clearCallingIdentity(); method public abstract int delete(android.net.Uri, java.lang.String, java.lang.String[]); method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); method public final java.lang.String getCallingPackage(); @@ -9195,6 +9196,7 @@ package android.content { method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal); method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal); method public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal); + method public final void restoreCallingIdentity(android.content.ContentProvider.CallingIdentity); method protected final void setPathPermissions(android.content.pm.PathPermission[]); method protected final void setReadPermission(java.lang.String); method protected final void setWritePermission(java.lang.String); @@ -9203,6 +9205,9 @@ package android.content { method public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]); } + public final class ContentProvider.CallingIdentity { + } + public static abstract interface ContentProvider.PipeDataWriter { method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T); } diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 2a03787f134cc..145c92731458d 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -821,6 +821,48 @@ public abstract class ContentProvider implements ComponentCallbacks2 { return pkg; } + /** + * Opaque token representing the identity of an incoming IPC. + */ + public final class CallingIdentity { + /** {@hide} */ + public final long binderToken; + /** {@hide} */ + public final String callingPackage; + + /** {@hide} */ + public CallingIdentity(long binderToken, String callingPackage) { + this.binderToken = binderToken; + this.callingPackage = callingPackage; + } + } + + /** + * Reset the identity of the incoming IPC on the current thread. + *

+ * Internally this calls {@link Binder#clearCallingIdentity()} and also + * clears any value stored in {@link #getCallingPackage()}. + * + * @return Returns an opaque token that can be used to restore the original + * calling identity by passing it to + * {@link #restoreCallingIdentity}. + */ + public final @NonNull CallingIdentity clearCallingIdentity() { + return new CallingIdentity(Binder.clearCallingIdentity(), setCallingPackage(null)); + } + + /** + * Restore the identity of the incoming IPC on the current thread back to a + * previously identity that was returned by {@link #clearCallingIdentity}. + *

+ * Internally this calls {@link Binder#restoreCallingIdentity(long)} and + * also restores any value stored in {@link #getCallingPackage()}. + */ + public final void restoreCallingIdentity(@NonNull CallingIdentity identity) { + Binder.restoreCallingIdentity(identity.binderToken); + mCallingPackage.set(identity.callingPackage); + } + /** * Change the authorities of the ContentProvider. * This is normally set for you from its manifest information when the provider is first diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 50ca4abd67135..df771df5de0de 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1538,6 +1538,9 @@ public class StorageManager { * @hide */ public File translateAppToSystem(File file, String packageName) { + // We can only translate absolute paths + if (!file.isAbsolute()) return file; + try { return new File(mStorageManager.translateAppToSystem(file.getAbsolutePath(), packageName, mContext.getUserId())); @@ -1553,6 +1556,9 @@ public class StorageManager { * @hide */ public File translateSystemToApp(File file, String packageName) { + // We can only translate absolute paths + if (!file.isAbsolute()) return file; + try { return new File(mStorageManager.translateSystemToApp(file.getAbsolutePath(), packageName, mContext.getUserId()));