DO NOT MERGE security: Test OOB arbitrary write at AMessage::FromParcel
Bug: 24123723
Change-Id: Icf427b0b3ef2e559c38e0a778dfbcbe60e522ef4
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index 8642028..a84e6ed 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -31,10 +31,11 @@
android_security_cts_AudioPolicyBinderTest.cpp \
android_security_cts_AudioFlingerBinderTest.cpp \
android_security_cts_MediaPlayerInfoLeakTest.cpp \
- android_security_cts_AudioEffectBinderTest.cpp
+ android_security_cts_AudioEffectBinderTest.cpp \
+ android_security_cts_StagefrightFoundationTest.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia libstagefright_foundation
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 73d0581..9cb6220 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -26,6 +26,7 @@
extern int register_android_security_cts_AudioFlingerBinderTest(JNIEnv* env);
extern int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env);
extern int register_android_security_cts_AudioEffectBinderTest(JNIEnv* env);
+extern int register_android_security_cts_StagefrightFoundationTest(JNIEnv* env);
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
@@ -70,5 +71,9 @@
return JNI_ERR;
}
+ if (register_android_security_cts_StagefrightFoundationTest(env)) {
+ return JNI_ERR;
+ }
+
return JNI_VERSION_1_4;
}
diff --git a/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
new file mode 100644
index 0000000..d16bd38
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioEffectBinderTest-JNI"
+
+#include <cstdio>
+#include <jni.h>
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+using namespace android;
+
+/*
+ * Native methods used by
+ * cts/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
+ */
+
+static jboolean android_security_cts_StagefrightFoundation_test_aMessageFromParcel(
+ JNIEnv* env __unused, jobject thiz __unused)
+{
+ const int kMaxNumItems = 64;
+ const int kNumItems = kMaxNumItems + 1 + 1000;
+ char name[128];
+
+ Parcel data;
+ data.writeInt32(0); // what
+ data.writeInt32(kNumItems); // numItems
+ for (int i = 0; i < kMaxNumItems; ++i) {
+ snprintf(name, sizeof(name), "item-%d", i);
+ data.writeCString(name); // name
+ data.writeInt32(0); // kTypeInt32
+ data.writeInt32(i); // value
+ }
+ data.writeCString("evil"); // name
+ data.writeInt32(0); // kTypeInt32
+ data.writeInt32(0); // value
+ // NOTE: This could overwrite mNumItems!
+
+ for (int i = 0; i < 1000; ++i) {
+ snprintf(name, sizeof(name), "evil-%d", i);
+ data.writeCString(name); // name
+ data.writeInt32(0); // kTypeInt32
+ data.writeInt32(0); // value
+ }
+
+ data.setDataPosition(0);
+ sp<AMessage> msg = AMessage::FromParcel(data);
+
+ for (int i = 0; i < kMaxNumItems; ++i) {
+ snprintf(name, sizeof(name), "item-%d", i);
+ int32_t value;
+ if (!msg->findInt32(name, &value)) {
+ ALOGE("cannot find value for %s", name);
+ return JNI_FALSE;
+ }
+ if (value != i) {
+ ALOGE("value is changed: expected %d actual %d", i, value);
+ return JNI_FALSE;
+ }
+ }
+ return JNI_TRUE;
+}
+
+int register_android_security_cts_StagefrightFoundationTest(JNIEnv *env)
+{
+ static JNINativeMethod methods[] = {
+ { "native_test_aMessageFromParcel", "()Z",
+ (void *) android_security_cts_StagefrightFoundation_test_aMessageFromParcel},
+ };
+
+ jclass clazz = env->FindClass("android/security/cts/StagefrightFoundationTest");
+ return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
new file mode 100644
index 0000000..9999d88
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import junit.framework.TestCase;
+
+public class StagefrightFoundationTest extends TestCase {
+
+ static {
+ System.loadLibrary("ctssecurity_jni");
+ }
+
+ /**
+ * Checks that IEffect::command() cannot leak data.
+ */
+ public void test_aMessageFromParcel() throws Exception {
+ assertTrue(native_test_aMessageFromParcel());
+ }
+
+ private static native boolean native_test_aMessageFromParcel();
+}