Add test for CVE-2014-3153

Change-Id: I827bf644d81457cc8901a187f4cb91f3d1e7e208
diff --git a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
index 2f3fb79..7c05008 100644
--- a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <jni.h>
+#include <linux/futex.h>
 #include <linux/netlink.h>
 #include <linux/sock_diag.h>
 #include <stdio.h>
@@ -293,6 +294,31 @@
     return result;
 }
 
+static inline int futex_syscall(volatile int* uaddr, int op, int val, const struct timespec* ts,
+                                volatile int* uaddr2, int val3) {
+    return syscall(__NR_futex, uaddr, op, val, ts, uaddr2, val3);
+}
+
+/*
+ * Test for vulnerability to CVE-2014-3153, a bug in the futex() syscall that can
+ * lead to privilege escalation and was used by the towelroot exploit. Returns true
+ * if device is patched, false if still vulnerable.
+ */
+static jboolean android_security_cts_NativeCodeTest_doFutexTest(JNIEnv*, jobject)
+{
+    jboolean result = false;
+
+    int futex = 1;
+    int ret;
+
+    /* The patch will reject FUTEX_CMP_REQUEUE_PI calls where addr == addr2, so
+     * that's what we're checking for - they're both &futex. Patched systems will
+     * return -1 and set errno to 22 (EINVAL), vulnerable systems will return 0.
+     */
+    ret = futex_syscall(&futex, FUTEX_CMP_REQUEUE_PI, 1, NULL, &futex, 0);
+    return (ret == -1 && errno == EINVAL);
+}
+
 
 static JNINativeMethod gMethods[] = {
     {  "doPerfEventTest", "()Z",
@@ -305,6 +331,8 @@
             (void *) android_security_cts_NativeCodeTest_doVrootTest },
     {  "doCVE20141710Test", "()Z",
             (void *) android_security_cts_NativeCodeTest_doCVE20141710Test },
+    {  "doFutexTest", "()Z",
+            (void *) android_security_cts_NativeCodeTest_doFutexTest },
 };
 
 int register_android_security_cts_NativeCodeTest(JNIEnv* env)
diff --git a/tests/tests/security/src/android/security/cts/NativeCodeTest.java b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
index 5e3ffa4..685036f 100644
--- a/tests/tests/security/src/android/security/cts/NativeCodeTest.java
+++ b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
@@ -45,6 +45,14 @@
         assertEquals(0, result);
     }
 
+    public void testFutex() throws Exception {
+        assertTrue("Device is vulnerable to CVE-2014-3153, a vulnerability in the futex() system "
+                   + "call. Please apply the security patch at "
+                   + "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/"
+                   + "?id=e9c243a5a6de0be8e584c604d353412584b592f8",
+                   doFutexTest());
+    }
+
     /**
      * Returns true iff this device is vulnerable to CVE-2013-2094.
      * A patch for CVE-2013-2094 can be found at
@@ -92,6 +100,17 @@
     }
 
     /**
+     * ANDROID-15455425 / CVE-2014-3153
+     *
+     * Returns true if the device is patched against the futex() system call vulnerability.
+     *
+     * More information on this vulnerability is at http://seclists.org/oss-sec/2014/q2/467 and
+     * the patch is at:
+     * https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e9c243a5a6de0be8e584c604d353412584b592f8
+     */
+    private static native boolean doFutexTest();
+
+    /**
      * Returns true if the device is immune to CVE-2014-1710,
      * false if the device is vulnerable.
      */