Revert "Cleanup vroot test and fix false positive."
code compiles on klp-dev but not on jb-dev. *sigh*
In file included from cts/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp:31:0:
bionic/libc/kernel/common/linux/sysctl.h:37:43: error: expected unqualified-id before '[' token
make: *** [out/target/product/generic/obj/SHARED_LIBRARIES/libctssecurity_jni_intermediates/android_security_cts_NativeCodeTest.o] Error 1
This reverts commit 65809bca4f0e2381b0a97a1db5f8166a19ca0d46.
Bug: 15408470
Change-Id: I35ac2f25e5a00c21628a1139a7426ca0f046d6d4
diff --git a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
index f858b11..162223c 100644
--- a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
@@ -28,7 +28,6 @@
#include <fcntl.h>
#include <cutils/log.h>
#include <linux/perf_event.h>
-#include <linux/sysctl.h>
/*
* Returns true iff this device is vulnerable to CVE-2013-2094.
@@ -78,6 +77,67 @@
return true;
}
+#define SEARCH_SIZE 0x4000
+
+static int secret;
+
+static bool isValidChildAddress(pid_t child, uintptr_t addr) {
+ long word;
+ long ret = syscall(__NR_ptrace, PTRACE_PEEKDATA, child, addr, &word);
+ return (ret == 0);
+}
+
+/* A lazy, do nothing child. GET A JOB. */
+static void child() {
+ int res;
+ ALOGE("in child");
+ secret = 0xbaadadd4;
+ res = prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
+ if (res != 0) {
+ ALOGE("prctl failed");
+ }
+ res = ptrace(PTRACE_TRACEME, 0, 0, 0);
+ if (res != 0) {
+ ALOGE("child ptrace failed");
+ }
+ signal(SIGSTOP, SIG_IGN);
+ kill(getpid(), SIGSTOP);
+}
+
+static jboolean parent(pid_t child) {
+ int status;
+ // Wait for the child to suspend itself so we can trace it.
+ waitpid(child, &status, 0);
+ jboolean result = true;
+
+ uintptr_t addr;
+ for (addr = 0x00000000; addr < 0xFFFF1000; addr+=SEARCH_SIZE) {
+ if (isValidChildAddress(child, addr)) {
+ // Don't scribble on our memory.
+ // (which has the same mapping as our child)
+ // We don't want to corrupt ourself.
+ continue;
+ }
+
+ errno = 0;
+ syscall(__NR_ptrace, PTRACE_PEEKDATA, child, &secret, addr);
+ if (errno == 0) {
+ result = false;
+ // We found an address which isn't in our our, or our child's,
+ // address space, but yet which is still writable. Scribble
+ // all over it.
+ ALOGE("parent: found writable at %x", addr);
+ uintptr_t addr2;
+ for (addr2 = addr; addr2 < addr + SEARCH_SIZE; addr2++) {
+ syscall(__NR_ptrace, PTRACE_PEEKDATA, child, &secret, addr2);
+ }
+ }
+ }
+
+ ptrace(PTRACE_DETACH, child, 0, 0);
+ return result;
+}
+
/*
* Prior to https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm/include/asm/uaccess.h?id=8404663f81d212918ff85f493649a7991209fa04
* there was a flaw in the kernel's handling of get_user and put_user
@@ -85,32 +145,25 @@
* that reads/writes outside the process's address space are not
* allowed.
*
- * In this test, we use sysctl to force a read from an address outside
- * of our address space (but in the kernel's address space). Without the
- * patch applied, this read succeeds, because sysctl uses the
- * vulnerable get_user call.
- *
- * This function returns true if the patch above is applied, or false
- * otherwise.
- *
- * Credit: https://twitter.com/grsecurity/status/401443359912239105
+ * In this test, we use prctl(PTRACE_PEEKDATA) to force a write to
+ * an address outside of our address space. Without the patch applied,
+ * this write succeeds, because prctl(PTRACE_PEEKDATA) uses the
+ * vulnerable put_user call.
*/
static jboolean android_security_cts_NativeCodeTest_doVrootTest(JNIEnv*, jobject)
{
ALOGE("Starting doVrootTest");
+ pid_t pid = fork();
+ if (pid == -1) {
+ return false;
+ }
- struct __sysctl_args args;
- char osname[100];
- int name[] = { CTL_KERN, KERN_OSTYPE };
+ if (pid == 0) {
+ child();
+ exit(0);
+ }
- memset(&args, 0, sizeof(struct __sysctl_args));
- args.name = name;
- args.nlen = sizeof(name)/sizeof(name[0]);
- args.oldval = osname;
- args.oldlenp = (size_t *) 0xc0000000; // PAGE_OFFSET
-
- int result = syscall(__NR__sysctl, &args);
- return ((result == -1) && (errno == EFAULT));
+ return parent(pid);
}
static void* mmap_syscall(void* addr, size_t len, int prot, int flags, int fd, off_t offset)
diff --git a/tests/tests/security/src/android/security/cts/NativeCodeTest.java b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
index f6e6029..116272d 100644
--- a/tests/tests/security/src/android/security/cts/NativeCodeTest.java
+++ b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
@@ -25,10 +25,7 @@
}
public void testVroot() throws Exception {
- assertTrue("Device is vulnerable to CVE-2013-6282. Please apply security patch at "
- + "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/"
- + "commit/arch/arm/include/asm/uaccess.h?id="
- + "8404663f81d212918ff85f493649a7991209fa04", doVrootTest());
+ assertTrue(doVrootTest());
}
public void testPerfEvent() throws Exception {
@@ -73,9 +70,13 @@
private static native boolean doPerfEventTest2();
/**
- * ANDROID-11234878 / CVE-2013-6282
+ * ANDROID-11234878
*
- * Returns true if the device is patched against the vroot vulnerability, false otherwise.
+ * Returns true if the device is patched against the vroot
+ * vulnerability. Returns false if there was some problem running
+ * the test (for example, out of memory), or the test fails but wasn't
+ * able to crash the device. Most of the time, however, the device will
+ * crash if the vulnerability is present.
*
* The following patch addresses this bug:
* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm/include/asm/uaccess.h?id=8404663f81d212918ff85f493649a7991209fa04