FPII-1901:DO NOT MERGE security: Test OOB arbitrary write at AMessage::FromParcel
CR:954346-CVE-2015-6620 Buffer overflow vulnerability in libstagefright
Bug: 24123723
Change-Id:Icf427b0b3ef2e559c38e0a778dfbcbe60e522ef4
(cherry picked from commit b69bdab25e7f215752a4867661fc8361509ed0a7)
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index cbf0756..3b7956b 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -33,10 +33,11 @@
android_security_cts_MMapExecutableTest.cpp \
android_security_cts_NetlinkSocket.cpp \
android_security_cts_AudioPolicyBinderTest.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 libselinux libdl
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia libselinux libdl libstagefright_foundation
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 75ebf66..49c4cf7 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -28,6 +28,7 @@
extern int register_android_security_cts_MMapExecutableTest(JNIEnv* env);
extern int register_android_security_cts_AudioPolicyBinderTest(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;
@@ -80,5 +81,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();
+}