From d8323e8684a837040d7dd291ce4c356979b5f519 Mon Sep 17 00:00:00 2001 From: mattgilbride Date: Tue, 25 Oct 2022 14:22:51 +0000 Subject: [PATCH] Make getCallingUidOrThrow() not throw in clearCallingIdentity() blocks The new method hasExplicitIdentity will track whether the caller is within a Binder.clearCallingIdentity/restoreCallingIdentity block based on packing this state information into the token returned by clearCallingIdentity. Bug: b/252975769 Test: android.os.cts.BinderTest Change-Id: I162db933f9e52cd6f9f46796bda11ad6216d3d66 --- core/java/android/os/Binder.java | 18 +++++++++++++++--- core/jni/android_util_Binder.cpp | 6 ++++++ .../coretests/src/android/os/BinderTest.java | 10 ++++------ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 3d10661062eae..0f3ed19e091c6 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -327,17 +327,29 @@ public class Binder implements IBinder { @CriticalNative public static final native boolean isDirectlyHandlingTransaction(); + /** + * Returns {@code true} if the current thread has had its identity + * set explicitly via {@link #clearCallingIdentity()} + * + * @hide + */ + @CriticalNative + private static native boolean hasExplicitIdentity(); + /** * Return the Linux UID assigned to the process that sent the transaction * currently being processed. * * @throws IllegalStateException if the current thread is not currently - * executing an incoming transaction. + * executing an incoming transaction and the calling identity has not been + * explicitly set with {@link #clearCallingIdentity()} */ public static final int getCallingUidOrThrow() { - if (!isDirectlyHandlingTransaction()) { + if (!isDirectlyHandlingTransaction() && !hasExplicitIdentity()) { throw new IllegalStateException( - "Thread is not in a binder transcation"); + "Thread is not in a binder transaction, " + + "and the calling identity has not been " + + "explicitly set with clearCallingIdentity"); } return getCallingUid(); } diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 01837f483f105..a7c7d0ba35bcd 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -983,6 +983,10 @@ static void android_os_Binder_restoreCallingIdentity(jlong token) IPCThreadState::self()->restoreCallingIdentity(token); } +static jboolean android_os_Binder_hasExplicitIdentity() { + return IPCThreadState::self()->hasExplicitIdentity(); +} + static void android_os_Binder_setThreadStrictModePolicy(jint policyMask) { IPCThreadState::self()->setStrictModePolicy(policyMask); @@ -1079,6 +1083,8 @@ static const JNINativeMethod gBinderMethods[] = { // @CriticalNative { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, // @CriticalNative + { "hasExplicitIdentity", "()Z", (void*)android_os_Binder_hasExplicitIdentity }, + // @CriticalNative { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy }, // @CriticalNative { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy }, diff --git a/core/tests/coretests/src/android/os/BinderTest.java b/core/tests/coretests/src/android/os/BinderTest.java index 99dbe64456623..02f87901318d0 100644 --- a/core/tests/coretests/src/android/os/BinderTest.java +++ b/core/tests/coretests/src/android/os/BinderTest.java @@ -20,6 +20,8 @@ import androidx.test.filters.SmallTest; import junit.framework.TestCase; +import static org.testng.Assert.assertThrows; + public class BinderTest extends TestCase { private static final int UID = 100; @@ -45,12 +47,8 @@ public class BinderTest extends TestCase { } @SmallTest - public void testGetCallingUidOrThrow() throws Exception { - try { - Binder.getCallingUidOrThrow(); - throw new AssertionError("IllegalStateException expected"); - } catch (IllegalStateException expected) { - } + public void testGetCallingUidOrThrow_throws() throws Exception { + assertThrows(IllegalStateException.class, () -> Binder.getCallingUidOrThrow()); } @SmallTest